From dfa77bc52aab706148316bef19a687b032ecae06 Mon Sep 17 00:00:00 2001 From: Owen LeJeune Date: Wed, 7 Mar 2018 17:18:40 -0500 Subject: [PATCH] first commit --- README.txt | 74 + app.js | 309 + html/.DS_Store | Bin 0 -> 6148 bytes html/assignment3.html | 72 + html/ding.mp3 | Bin 0 -> 5605 bytes html/game.js | 251 + html/hit.mp3 | Bin 0 -> 3599 bytes html/mute.png | Bin 0 -> 1225 bytes html/rink.jpg | Bin 0 -> 189678 bytes html/sound.png | Bin 0 -> 1621 bytes html/style.css | 70 + node_modules/accepts/HISTORY.md | 224 + node_modules/accepts/LICENSE | 23 + node_modules/accepts/README.md | 143 + node_modules/accepts/index.js | 238 + node_modules/accepts/package.json | 88 + node_modules/after/.npmignore | 2 + node_modules/after/.travis.yml | 12 + node_modules/after/LICENCE | 19 + node_modules/after/README.md | 115 + node_modules/after/index.js | 28 + node_modules/after/package.json | 66 + node_modules/after/test/after-test.js | 120 + node_modules/arraybuffer.slice/.npmignore | 17 + node_modules/arraybuffer.slice/LICENCE | 18 + node_modules/arraybuffer.slice/Makefile | 8 + node_modules/arraybuffer.slice/README.md | 17 + node_modules/arraybuffer.slice/index.js | 29 + node_modules/arraybuffer.slice/package.json | 47 + .../arraybuffer.slice/test/slice-buffer.js | 227 + node_modules/async-limiter/.travis.yml | 7 + node_modules/async-limiter/LICENSE | 8 + .../async-limiter/coverage/coverage.json | 1 + .../lcov-report/async-throttle/index.html | 73 + .../lcov-report/async-throttle/index.js.html | 246 + .../coverage/lcov-report/base.css | 182 + .../coverage/lcov-report/index.html | 73 + .../coverage/lcov-report/prettify.css | 1 + .../coverage/lcov-report/prettify.js | 1 + .../lcov-report/sort-arrow-sprite.png | Bin 0 -> 209 bytes .../coverage/lcov-report/sorter.js | 156 + node_modules/async-limiter/coverage/lcov.info | 74 + node_modules/async-limiter/index.js | 67 + node_modules/async-limiter/package.json | 72 + node_modules/async-limiter/readme.md | 132 + node_modules/backo2/.npmignore | 1 + node_modules/backo2/History.md | 12 + node_modules/backo2/Makefile | 8 + node_modules/backo2/Readme.md | 34 + node_modules/backo2/component.json | 11 + node_modules/backo2/index.js | 85 + node_modules/backo2/package.json | 50 + node_modules/backo2/test/index.js | 18 + node_modules/base64-arraybuffer/.npmignore | 3 + node_modules/base64-arraybuffer/.travis.yml | 19 + node_modules/base64-arraybuffer/LICENSE-MIT | 22 + node_modules/base64-arraybuffer/README.md | 20 + .../lib/base64-arraybuffer.js | 67 + node_modules/base64-arraybuffer/package.json | 68 + node_modules/base64id/.npmignore | 3 + node_modules/base64id/LICENSE | 22 + node_modules/base64id/README.md | 18 + node_modules/base64id/lib/base64id.js | 103 + node_modules/base64id/package.json | 50 + node_modules/better-assert/.npmignore | 4 + node_modules/better-assert/History.md | 15 + node_modules/better-assert/Makefile | 5 + node_modules/better-assert/Readme.md | 61 + node_modules/better-assert/example.js | 10 + node_modules/better-assert/index.js | 38 + node_modules/better-assert/package.json | 68 + node_modules/blob/.npmignore | 2 + node_modules/blob/.zuul.yml | 14 + node_modules/blob/Makefile | 14 + node_modules/blob/README.md | 14 + node_modules/blob/index.js | 96 + node_modules/blob/package.json | 51 + node_modules/blob/test/index.js | 94 + node_modules/callsite/.npmignore | 4 + node_modules/callsite/History.md | 10 + node_modules/callsite/Makefile | 6 + node_modules/callsite/Readme.md | 44 + node_modules/callsite/index.js | 10 + node_modules/callsite/package.json | 51 + node_modules/component-bind/.npmignore | 4 + node_modules/component-bind/History.md | 13 + node_modules/component-bind/Makefile | 7 + node_modules/component-bind/Readme.md | 64 + node_modules/component-bind/component.json | 13 + node_modules/component-bind/index.js | 23 + node_modules/component-bind/package.json | 54 + node_modules/component-emitter/History.md | 68 + node_modules/component-emitter/LICENSE | 24 + node_modules/component-emitter/Readme.md | 74 + node_modules/component-emitter/index.js | 163 + node_modules/component-emitter/package.json | 61 + node_modules/component-inherit/.npmignore | 3 + node_modules/component-inherit/History.md | 5 + node_modules/component-inherit/Makefile | 16 + node_modules/component-inherit/Readme.md | 24 + node_modules/component-inherit/component.json | 10 + node_modules/component-inherit/index.js | 7 + node_modules/component-inherit/package.json | 51 + .../component-inherit/test/inherit.js | 21 + node_modules/cookie/HISTORY.md | 118 + node_modules/cookie/LICENSE | 24 + node_modules/cookie/README.md | 220 + node_modules/cookie/index.js | 195 + node_modules/cookie/package.json | 74 + node_modules/debug/.coveralls.yml | 1 + node_modules/debug/.eslintrc | 11 + node_modules/debug/.npmignore | 9 + node_modules/debug/.travis.yml | 14 + node_modules/debug/CHANGELOG.md | 362 + node_modules/debug/LICENSE | 19 + node_modules/debug/Makefile | 50 + node_modules/debug/README.md | 312 + node_modules/debug/component.json | 19 + node_modules/debug/karma.conf.js | 70 + node_modules/debug/node.js | 1 + node_modules/debug/package.json | 92 + node_modules/debug/src/browser.js | 185 + node_modules/debug/src/debug.js | 202 + node_modules/debug/src/index.js | 10 + node_modules/debug/src/inspector-log.js | 15 + node_modules/debug/src/node.js | 248 + node_modules/engine.io-client/LICENSE | 22 + node_modules/engine.io-client/README.md | 299 + node_modules/engine.io-client/engine.io.js | 4700 +++++++++++ node_modules/engine.io-client/lib/index.js | 10 + node_modules/engine.io-client/lib/socket.js | 743 ++ .../engine.io-client/lib/transport.js | 157 + .../engine.io-client/lib/transports/index.js | 53 + .../lib/transports/polling-jsonp.js | 231 + .../lib/transports/polling-xhr.js | 420 + .../lib/transports/polling.js | 245 + .../lib/transports/websocket.js | 286 + .../engine.io-client/lib/xmlhttprequest.js | 37 + .../node_modules/debug/.coveralls.yml | 1 + .../node_modules/debug/.eslintrc | 14 + .../node_modules/debug/.npmignore | 9 + .../node_modules/debug/.travis.yml | 20 + .../node_modules/debug/CHANGELOG.md | 395 + .../node_modules/debug/LICENSE | 19 + .../node_modules/debug/Makefile | 58 + .../node_modules/debug/README.md | 368 + .../node_modules/debug/karma.conf.js | 70 + .../node_modules/debug/node.js | 1 + .../node_modules/debug/package.json | 85 + .../node_modules/debug/src/browser.js | 195 + .../node_modules/debug/src/debug.js | 225 + .../node_modules/debug/src/index.js | 10 + .../node_modules/debug/src/node.js | 186 + node_modules/engine.io-client/package.json | 116 + node_modules/engine.io-parser/LICENSE | 22 + node_modules/engine.io-parser/Readme.md | 202 + node_modules/engine.io-parser/lib/browser.js | 606 ++ node_modules/engine.io-parser/lib/index.js | 480 ++ node_modules/engine.io-parser/lib/keys.js | 19 + node_modules/engine.io-parser/lib/utf8.js | 255 + node_modules/engine.io-parser/package.json | 65 + node_modules/engine.io/LICENSE | 19 + node_modules/engine.io/README.md | 539 ++ node_modules/engine.io/lib/engine.io.js | 126 + node_modules/engine.io/lib/server.js | 581 ++ node_modules/engine.io/lib/socket.js | 486 ++ node_modules/engine.io/lib/transport.js | 128 + .../engine.io/lib/transports/index.js | 36 + .../engine.io/lib/transports/polling-jsonp.js | 75 + .../engine.io/lib/transports/polling-xhr.js | 69 + .../engine.io/lib/transports/polling.js | 407 + .../engine.io/lib/transports/websocket.js | 134 + .../node_modules/debug/.coveralls.yml | 1 + .../engine.io/node_modules/debug/.eslintrc | 14 + .../engine.io/node_modules/debug/.npmignore | 9 + .../engine.io/node_modules/debug/.travis.yml | 20 + .../engine.io/node_modules/debug/CHANGELOG.md | 395 + .../engine.io/node_modules/debug/LICENSE | 19 + .../engine.io/node_modules/debug/Makefile | 58 + .../engine.io/node_modules/debug/README.md | 368 + .../node_modules/debug/karma.conf.js | 70 + .../engine.io/node_modules/debug/node.js | 1 + .../engine.io/node_modules/debug/package.json | 85 + .../node_modules/debug/src/browser.js | 195 + .../engine.io/node_modules/debug/src/debug.js | 225 + .../engine.io/node_modules/debug/src/index.js | 10 + .../engine.io/node_modules/debug/src/node.js | 186 + node_modules/engine.io/package.json | 101 + node_modules/has-binary2/History.md | 39 + node_modules/has-binary2/LICENSE | 20 + node_modules/has-binary2/README.md | 4 + node_modules/has-binary2/index.js | 62 + node_modules/has-binary2/package.json | 53 + node_modules/has-cors/.npmignore | 3 + node_modules/has-cors/History.md | 21 + node_modules/has-cors/Makefile | 11 + node_modules/has-cors/Readme.md | 24 + node_modules/has-cors/component.json | 13 + node_modules/has-cors/index.js | 17 + node_modules/has-cors/package.json | 69 + node_modules/has-cors/test.js | 24 + node_modules/indexof/.npmignore | 2 + node_modules/indexof/Makefile | 11 + node_modules/indexof/Readme.md | 15 + node_modules/indexof/component.json | 10 + node_modules/indexof/index.js | 10 + node_modules/indexof/package.json | 45 + node_modules/isarray/README.md | 54 + node_modules/isarray/index.js | 5 + node_modules/isarray/package.json | 80 + node_modules/mime-db/HISTORY.md | 368 + node_modules/mime-db/LICENSE | 22 + node_modules/mime-db/README.md | 94 + node_modules/mime-db/db.json | 7088 +++++++++++++++++ node_modules/mime-db/index.js | 11 + node_modules/mime-db/package.json | 103 + node_modules/mime-types/HISTORY.md | 260 + node_modules/mime-types/LICENSE | 23 + node_modules/mime-types/README.md | 108 + node_modules/mime-types/index.js | 188 + node_modules/mime-types/package.json | 89 + node_modules/ms/index.js | 152 + node_modules/ms/license.md | 21 + node_modules/ms/package.json | 75 + node_modules/ms/readme.md | 51 + node_modules/negotiator/HISTORY.md | 98 + node_modules/negotiator/LICENSE | 24 + node_modules/negotiator/README.md | 203 + node_modules/negotiator/index.js | 124 + node_modules/negotiator/lib/charset.js | 169 + node_modules/negotiator/lib/encoding.js | 184 + node_modules/negotiator/lib/language.js | 179 + node_modules/negotiator/lib/mediaType.js | 294 + node_modules/negotiator/package.json | 84 + node_modules/object-component/.npmignore | 3 + node_modules/object-component/History.md | 10 + node_modules/object-component/Makefile | 16 + node_modules/object-component/Readme.md | 31 + node_modules/object-component/component.json | 10 + node_modules/object-component/index.js | 84 + node_modules/object-component/package.json | 42 + node_modules/object-component/test/object.js | 48 + node_modules/parseqs/.npmignore | 3 + node_modules/parseqs/LICENSE | 21 + node_modules/parseqs/Makefile | 3 + node_modules/parseqs/README.md | 1 + node_modules/parseqs/index.js | 37 + node_modules/parseqs/package.json | 56 + node_modules/parseqs/test.js | 27 + node_modules/parseuri/.npmignore | 2 + node_modules/parseuri/History.md | 5 + node_modules/parseuri/LICENSE | 21 + node_modules/parseuri/Makefile | 3 + node_modules/parseuri/README.md | 2 + node_modules/parseuri/index.js | 39 + node_modules/parseuri/package.json | 54 + node_modules/parseuri/test.js | 51 + node_modules/safe-buffer/.travis.yml | 7 + node_modules/safe-buffer/LICENSE | 21 + node_modules/safe-buffer/README.md | 584 ++ node_modules/safe-buffer/index.js | 62 + node_modules/safe-buffer/package.json | 65 + node_modules/safe-buffer/test.js | 101 + node_modules/socket.io-adapter/.npmignore | 1 + node_modules/socket.io-adapter/LICENSE | 20 + node_modules/socket.io-adapter/Readme.md | 16 + node_modules/socket.io-adapter/index.js | 263 + node_modules/socket.io-adapter/package.json | 42 + node_modules/socket.io-client/LICENSE | 22 + node_modules/socket.io-client/README.md | 57 + .../socket.io-client/dist/socket.io.js | 3 + .../socket.io-client/dist/socket.io.js.map | 1 + .../socket.io-client/dist/socket.io.slim.js | 3 + .../dist/socket.io.slim.js.map | 1 + node_modules/socket.io-client/lib/index.js | 94 + node_modules/socket.io-client/lib/manager.js | 573 ++ node_modules/socket.io-client/lib/on.js | 24 + node_modules/socket.io-client/lib/socket.js | 418 + node_modules/socket.io-client/lib/url.js | 75 + node_modules/socket.io-client/package.json | 118 + node_modules/socket.io-parser/LICENSE | 20 + node_modules/socket.io-parser/Readme.md | 73 + node_modules/socket.io-parser/binary.js | 141 + node_modules/socket.io-parser/index.js | 408 + node_modules/socket.io-parser/is-buffer.js | 13 + .../node_modules/debug/.coveralls.yml | 1 + .../node_modules/debug/.eslintrc | 14 + .../node_modules/debug/.npmignore | 9 + .../node_modules/debug/.travis.yml | 20 + .../node_modules/debug/CHANGELOG.md | 395 + .../node_modules/debug/LICENSE | 19 + .../node_modules/debug/Makefile | 58 + .../node_modules/debug/README.md | 368 + .../node_modules/debug/karma.conf.js | 70 + .../node_modules/debug/node.js | 1 + .../node_modules/debug/package.json | 85 + .../node_modules/debug/src/browser.js | 195 + .../node_modules/debug/src/debug.js | 225 + .../node_modules/debug/src/index.js | 10 + .../node_modules/debug/src/node.js | 186 + node_modules/socket.io-parser/package.json | 67 + node_modules/socket.io/LICENSE | 22 + node_modules/socket.io/Readme.md | 242 + node_modules/socket.io/lib/client.js | 252 + node_modules/socket.io/lib/index.js | 474 ++ node_modules/socket.io/lib/namespace.js | 279 + node_modules/socket.io/lib/socket.js | 557 ++ node_modules/socket.io/package.json | 90 + node_modules/to-array/.npmignore | 3 + node_modules/to-array/LICENCE | 19 + node_modules/to-array/README.md | 22 + node_modules/to-array/index.js | 13 + node_modules/to-array/package.json | 71 + node_modules/ultron/LICENSE | 22 + node_modules/ultron/README.md | 113 + node_modules/ultron/index.js | 136 + node_modules/ultron/package.json | 71 + node_modules/uws/LICENSE | 17 + node_modules/uws/README.md | 32 + node_modules/uws/binding.gyp | 80 + node_modules/uws/build_log.txt | 19 + node_modules/uws/package.json | 59 + node_modules/uws/src/Asio.h | 188 + node_modules/uws/src/Backend.h | 15 + node_modules/uws/src/Epoll.cpp | 65 + node_modules/uws/src/Epoll.h | 261 + node_modules/uws/src/Extensions.cpp | 131 + node_modules/uws/src/Extensions.h | 29 + node_modules/uws/src/Group.cpp | 263 + node_modules/uws/src/Group.h | 144 + node_modules/uws/src/HTTPSocket.cpp | 310 + node_modules/uws/src/HTTPSocket.h | 285 + node_modules/uws/src/Hub.cpp | 213 + node_modules/uws/src/Hub.h | 98 + node_modules/uws/src/Libuv.h | 179 + node_modules/uws/src/Networking.cpp | 78 + node_modules/uws/src/Networking.h | 259 + node_modules/uws/src/Node.cpp | 83 + node_modules/uws/src/Node.h | 198 + node_modules/uws/src/Socket.cpp | 28 + node_modules/uws/src/Socket.h | 507 ++ node_modules/uws/src/WebSocket.cpp | 405 + node_modules/uws/src/WebSocket.h | 89 + node_modules/uws/src/WebSocketProtocol.h | 377 + node_modules/uws/src/addon.cpp | 24 + node_modules/uws/src/addon.h | 464 ++ node_modules/uws/src/http.h | 357 + node_modules/uws/src/uWS.h | 6 + node_modules/uws/uws.js | 563 ++ node_modules/uws/uws_darwin_46.node | Bin 0 -> 379476 bytes node_modules/uws/uws_darwin_47.node | Bin 0 -> 379476 bytes node_modules/uws/uws_darwin_48.node | Bin 0 -> 379468 bytes node_modules/uws/uws_darwin_51.node | Bin 0 -> 383636 bytes node_modules/uws/uws_darwin_57.node | Bin 0 -> 383636 bytes node_modules/uws/uws_darwin_59.node | Bin 0 -> 383636 bytes node_modules/uws/uws_linux_46.node | Bin 0 -> 1580112 bytes node_modules/uws/uws_linux_47.node | Bin 0 -> 1580112 bytes node_modules/uws/uws_linux_48.node | Bin 0 -> 1584208 bytes node_modules/uws/uws_linux_51.node | Bin 0 -> 1584176 bytes node_modules/uws/uws_linux_57.node | Bin 0 -> 1584176 bytes node_modules/uws/uws_linux_59.node | Bin 0 -> 1584176 bytes node_modules/uws/uws_win32_48.node | Bin 0 -> 643584 bytes node_modules/uws/uws_win32_51.node | Bin 0 -> 644096 bytes node_modules/uws/uws_win32_57.node | Bin 0 -> 644096 bytes node_modules/uws/uws_win32_59.node | Bin 0 -> 644096 bytes node_modules/ws/LICENSE | 21 + node_modules/ws/README.md | 341 + node_modules/ws/index.js | 15 + node_modules/ws/lib/.DS_Store | Bin 0 -> 6148 bytes node_modules/ws/lib/BufferUtil.js | 71 + node_modules/ws/lib/Constants.js | 10 + node_modules/ws/lib/ErrorCodes.js | 28 + node_modules/ws/lib/EventTarget.js | 151 + node_modules/ws/lib/Extensions.js | 203 + node_modules/ws/lib/PerMessageDeflate.js | 507 ++ node_modules/ws/lib/Receiver.js | 553 ++ node_modules/ws/lib/Sender.js | 412 + node_modules/ws/lib/Validation.js | 17 + node_modules/ws/lib/WebSocket.js | 717 ++ node_modules/ws/lib/WebSocketServer.js | 326 + node_modules/ws/package.json | 84 + node_modules/xmlhttprequest-ssl/LICENSE | 22 + node_modules/xmlhttprequest-ssl/README.md | 63 + .../xmlhttprequest-ssl/autotest.watchr | 8 + .../xmlhttprequest-ssl/example/demo.js | 16 + .../xmlhttprequest-ssl/lib/XMLHttpRequest.js | 651 ++ node_modules/xmlhttprequest-ssl/package.json | 66 + .../tests/test-constants.js | 13 + .../xmlhttprequest-ssl/tests/test-events.js | 50 + .../tests/test-exceptions.js | 59 + .../xmlhttprequest-ssl/tests/test-headers.js | 76 + .../tests/test-redirect-302.js | 41 + .../tests/test-redirect-303.js | 41 + .../tests/test-redirect-307.js | 43 + .../tests/test-request-methods.js | 62 + .../tests/test-request-protocols.js | 32 + .../xmlhttprequest-ssl/tests/testdata.txt | 1 + node_modules/yeast/LICENSE | 22 + node_modules/yeast/README.md | 82 + node_modules/yeast/index.js | 68 + node_modules/yeast/package.json | 67 + package-lock.json | 323 + package.json | 8 + 403 files changed, 52076 insertions(+) create mode 100644 README.txt create mode 100644 app.js create mode 100644 html/.DS_Store create mode 100644 html/assignment3.html create mode 100644 html/ding.mp3 create mode 100644 html/game.js create mode 100644 html/hit.mp3 create mode 100644 html/mute.png create mode 100644 html/rink.jpg create mode 100644 html/sound.png create mode 100644 html/style.css create mode 100644 node_modules/accepts/HISTORY.md create mode 100644 node_modules/accepts/LICENSE create mode 100644 node_modules/accepts/README.md create mode 100644 node_modules/accepts/index.js create mode 100644 node_modules/accepts/package.json create mode 100644 node_modules/after/.npmignore create mode 100644 node_modules/after/.travis.yml create mode 100644 node_modules/after/LICENCE create mode 100644 node_modules/after/README.md create mode 100644 node_modules/after/index.js create mode 100644 node_modules/after/package.json create mode 100644 node_modules/after/test/after-test.js create mode 100644 node_modules/arraybuffer.slice/.npmignore create mode 100644 node_modules/arraybuffer.slice/LICENCE create mode 100644 node_modules/arraybuffer.slice/Makefile create mode 100644 node_modules/arraybuffer.slice/README.md create mode 100644 node_modules/arraybuffer.slice/index.js create mode 100644 node_modules/arraybuffer.slice/package.json create mode 100644 node_modules/arraybuffer.slice/test/slice-buffer.js create mode 100644 node_modules/async-limiter/.travis.yml create mode 100644 node_modules/async-limiter/LICENSE create mode 100644 node_modules/async-limiter/coverage/coverage.json create mode 100644 node_modules/async-limiter/coverage/lcov-report/async-throttle/index.html create mode 100644 node_modules/async-limiter/coverage/lcov-report/async-throttle/index.js.html create mode 100644 node_modules/async-limiter/coverage/lcov-report/base.css create mode 100644 node_modules/async-limiter/coverage/lcov-report/index.html create mode 100644 node_modules/async-limiter/coverage/lcov-report/prettify.css create mode 100644 node_modules/async-limiter/coverage/lcov-report/prettify.js create mode 100644 node_modules/async-limiter/coverage/lcov-report/sort-arrow-sprite.png create mode 100644 node_modules/async-limiter/coverage/lcov-report/sorter.js create mode 100644 node_modules/async-limiter/coverage/lcov.info create mode 100644 node_modules/async-limiter/index.js create mode 100644 node_modules/async-limiter/package.json create mode 100644 node_modules/async-limiter/readme.md create mode 100644 node_modules/backo2/.npmignore create mode 100644 node_modules/backo2/History.md create mode 100644 node_modules/backo2/Makefile create mode 100644 node_modules/backo2/Readme.md create mode 100644 node_modules/backo2/component.json create mode 100644 node_modules/backo2/index.js create mode 100644 node_modules/backo2/package.json create mode 100644 node_modules/backo2/test/index.js create mode 100644 node_modules/base64-arraybuffer/.npmignore create mode 100644 node_modules/base64-arraybuffer/.travis.yml create mode 100644 node_modules/base64-arraybuffer/LICENSE-MIT create mode 100644 node_modules/base64-arraybuffer/README.md create mode 100644 node_modules/base64-arraybuffer/lib/base64-arraybuffer.js create mode 100644 node_modules/base64-arraybuffer/package.json create mode 100644 node_modules/base64id/.npmignore create mode 100644 node_modules/base64id/LICENSE create mode 100644 node_modules/base64id/README.md create mode 100644 node_modules/base64id/lib/base64id.js create mode 100644 node_modules/base64id/package.json create mode 100644 node_modules/better-assert/.npmignore create mode 100644 node_modules/better-assert/History.md create mode 100644 node_modules/better-assert/Makefile create mode 100644 node_modules/better-assert/Readme.md create mode 100644 node_modules/better-assert/example.js create mode 100644 node_modules/better-assert/index.js create mode 100644 node_modules/better-assert/package.json create mode 100644 node_modules/blob/.npmignore create mode 100644 node_modules/blob/.zuul.yml create mode 100644 node_modules/blob/Makefile create mode 100644 node_modules/blob/README.md create mode 100644 node_modules/blob/index.js create mode 100644 node_modules/blob/package.json create mode 100644 node_modules/blob/test/index.js create mode 100644 node_modules/callsite/.npmignore create mode 100644 node_modules/callsite/History.md create mode 100644 node_modules/callsite/Makefile create mode 100644 node_modules/callsite/Readme.md create mode 100644 node_modules/callsite/index.js create mode 100644 node_modules/callsite/package.json create mode 100644 node_modules/component-bind/.npmignore create mode 100644 node_modules/component-bind/History.md create mode 100644 node_modules/component-bind/Makefile create mode 100644 node_modules/component-bind/Readme.md create mode 100644 node_modules/component-bind/component.json create mode 100644 node_modules/component-bind/index.js create mode 100644 node_modules/component-bind/package.json create mode 100644 node_modules/component-emitter/History.md create mode 100644 node_modules/component-emitter/LICENSE create mode 100644 node_modules/component-emitter/Readme.md create mode 100644 node_modules/component-emitter/index.js create mode 100644 node_modules/component-emitter/package.json create mode 100644 node_modules/component-inherit/.npmignore create mode 100644 node_modules/component-inherit/History.md create mode 100644 node_modules/component-inherit/Makefile create mode 100644 node_modules/component-inherit/Readme.md create mode 100644 node_modules/component-inherit/component.json create mode 100644 node_modules/component-inherit/index.js create mode 100644 node_modules/component-inherit/package.json create mode 100644 node_modules/component-inherit/test/inherit.js create mode 100644 node_modules/cookie/HISTORY.md create mode 100644 node_modules/cookie/LICENSE create mode 100644 node_modules/cookie/README.md create mode 100644 node_modules/cookie/index.js create mode 100644 node_modules/cookie/package.json create mode 100644 node_modules/debug/.coveralls.yml create mode 100644 node_modules/debug/.eslintrc create mode 100644 node_modules/debug/.npmignore create mode 100644 node_modules/debug/.travis.yml create mode 100644 node_modules/debug/CHANGELOG.md create mode 100644 node_modules/debug/LICENSE create mode 100644 node_modules/debug/Makefile create mode 100644 node_modules/debug/README.md create mode 100644 node_modules/debug/component.json create mode 100644 node_modules/debug/karma.conf.js create mode 100644 node_modules/debug/node.js create mode 100644 node_modules/debug/package.json create mode 100644 node_modules/debug/src/browser.js create mode 100644 node_modules/debug/src/debug.js create mode 100644 node_modules/debug/src/index.js create mode 100644 node_modules/debug/src/inspector-log.js create mode 100644 node_modules/debug/src/node.js create mode 100644 node_modules/engine.io-client/LICENSE create mode 100644 node_modules/engine.io-client/README.md create mode 100644 node_modules/engine.io-client/engine.io.js create mode 100644 node_modules/engine.io-client/lib/index.js create mode 100644 node_modules/engine.io-client/lib/socket.js create mode 100644 node_modules/engine.io-client/lib/transport.js create mode 100755 node_modules/engine.io-client/lib/transports/index.js create mode 100644 node_modules/engine.io-client/lib/transports/polling-jsonp.js create mode 100755 node_modules/engine.io-client/lib/transports/polling-xhr.js create mode 100644 node_modules/engine.io-client/lib/transports/polling.js create mode 100644 node_modules/engine.io-client/lib/transports/websocket.js create mode 100644 node_modules/engine.io-client/lib/xmlhttprequest.js create mode 100644 node_modules/engine.io-client/node_modules/debug/.coveralls.yml create mode 100644 node_modules/engine.io-client/node_modules/debug/.eslintrc create mode 100644 node_modules/engine.io-client/node_modules/debug/.npmignore create mode 100644 node_modules/engine.io-client/node_modules/debug/.travis.yml create mode 100644 node_modules/engine.io-client/node_modules/debug/CHANGELOG.md create mode 100644 node_modules/engine.io-client/node_modules/debug/LICENSE create mode 100644 node_modules/engine.io-client/node_modules/debug/Makefile create mode 100644 node_modules/engine.io-client/node_modules/debug/README.md create mode 100644 node_modules/engine.io-client/node_modules/debug/karma.conf.js create mode 100644 node_modules/engine.io-client/node_modules/debug/node.js create mode 100644 node_modules/engine.io-client/node_modules/debug/package.json create mode 100644 node_modules/engine.io-client/node_modules/debug/src/browser.js create mode 100644 node_modules/engine.io-client/node_modules/debug/src/debug.js create mode 100644 node_modules/engine.io-client/node_modules/debug/src/index.js create mode 100644 node_modules/engine.io-client/node_modules/debug/src/node.js create mode 100644 node_modules/engine.io-client/package.json create mode 100644 node_modules/engine.io-parser/LICENSE create mode 100644 node_modules/engine.io-parser/Readme.md create mode 100644 node_modules/engine.io-parser/lib/browser.js create mode 100644 node_modules/engine.io-parser/lib/index.js create mode 100644 node_modules/engine.io-parser/lib/keys.js create mode 100644 node_modules/engine.io-parser/lib/utf8.js create mode 100644 node_modules/engine.io-parser/package.json create mode 100644 node_modules/engine.io/LICENSE create mode 100644 node_modules/engine.io/README.md create mode 100644 node_modules/engine.io/lib/engine.io.js create mode 100644 node_modules/engine.io/lib/server.js create mode 100644 node_modules/engine.io/lib/socket.js create mode 100644 node_modules/engine.io/lib/transport.js create mode 100644 node_modules/engine.io/lib/transports/index.js create mode 100644 node_modules/engine.io/lib/transports/polling-jsonp.js create mode 100644 node_modules/engine.io/lib/transports/polling-xhr.js create mode 100644 node_modules/engine.io/lib/transports/polling.js create mode 100644 node_modules/engine.io/lib/transports/websocket.js create mode 100644 node_modules/engine.io/node_modules/debug/.coveralls.yml create mode 100644 node_modules/engine.io/node_modules/debug/.eslintrc create mode 100644 node_modules/engine.io/node_modules/debug/.npmignore create mode 100644 node_modules/engine.io/node_modules/debug/.travis.yml create mode 100644 node_modules/engine.io/node_modules/debug/CHANGELOG.md create mode 100644 node_modules/engine.io/node_modules/debug/LICENSE create mode 100644 node_modules/engine.io/node_modules/debug/Makefile create mode 100644 node_modules/engine.io/node_modules/debug/README.md create mode 100644 node_modules/engine.io/node_modules/debug/karma.conf.js create mode 100644 node_modules/engine.io/node_modules/debug/node.js create mode 100644 node_modules/engine.io/node_modules/debug/package.json create mode 100644 node_modules/engine.io/node_modules/debug/src/browser.js create mode 100644 node_modules/engine.io/node_modules/debug/src/debug.js create mode 100644 node_modules/engine.io/node_modules/debug/src/index.js create mode 100644 node_modules/engine.io/node_modules/debug/src/node.js create mode 100644 node_modules/engine.io/package.json create mode 100644 node_modules/has-binary2/History.md create mode 100644 node_modules/has-binary2/LICENSE create mode 100644 node_modules/has-binary2/README.md create mode 100644 node_modules/has-binary2/index.js create mode 100644 node_modules/has-binary2/package.json create mode 100644 node_modules/has-cors/.npmignore create mode 100644 node_modules/has-cors/History.md create mode 100644 node_modules/has-cors/Makefile create mode 100644 node_modules/has-cors/Readme.md create mode 100644 node_modules/has-cors/component.json create mode 100644 node_modules/has-cors/index.js create mode 100644 node_modules/has-cors/package.json create mode 100644 node_modules/has-cors/test.js create mode 100644 node_modules/indexof/.npmignore create mode 100644 node_modules/indexof/Makefile create mode 100644 node_modules/indexof/Readme.md create mode 100644 node_modules/indexof/component.json create mode 100644 node_modules/indexof/index.js create mode 100644 node_modules/indexof/package.json create mode 100644 node_modules/isarray/README.md create mode 100644 node_modules/isarray/index.js create mode 100644 node_modules/isarray/package.json create mode 100644 node_modules/mime-db/HISTORY.md create mode 100644 node_modules/mime-db/LICENSE create mode 100644 node_modules/mime-db/README.md create mode 100644 node_modules/mime-db/db.json create mode 100644 node_modules/mime-db/index.js create mode 100644 node_modules/mime-db/package.json create mode 100644 node_modules/mime-types/HISTORY.md create mode 100644 node_modules/mime-types/LICENSE create mode 100644 node_modules/mime-types/README.md create mode 100644 node_modules/mime-types/index.js create mode 100644 node_modules/mime-types/package.json create mode 100644 node_modules/ms/index.js create mode 100644 node_modules/ms/license.md create mode 100644 node_modules/ms/package.json create mode 100644 node_modules/ms/readme.md create mode 100644 node_modules/negotiator/HISTORY.md create mode 100644 node_modules/negotiator/LICENSE create mode 100644 node_modules/negotiator/README.md create mode 100644 node_modules/negotiator/index.js create mode 100644 node_modules/negotiator/lib/charset.js create mode 100644 node_modules/negotiator/lib/encoding.js create mode 100644 node_modules/negotiator/lib/language.js create mode 100644 node_modules/negotiator/lib/mediaType.js create mode 100644 node_modules/negotiator/package.json create mode 100644 node_modules/object-component/.npmignore create mode 100644 node_modules/object-component/History.md create mode 100644 node_modules/object-component/Makefile create mode 100644 node_modules/object-component/Readme.md create mode 100644 node_modules/object-component/component.json create mode 100644 node_modules/object-component/index.js create mode 100644 node_modules/object-component/package.json create mode 100644 node_modules/object-component/test/object.js create mode 100644 node_modules/parseqs/.npmignore create mode 100644 node_modules/parseqs/LICENSE create mode 100644 node_modules/parseqs/Makefile create mode 100644 node_modules/parseqs/README.md create mode 100644 node_modules/parseqs/index.js create mode 100644 node_modules/parseqs/package.json create mode 100644 node_modules/parseqs/test.js create mode 100644 node_modules/parseuri/.npmignore create mode 100644 node_modules/parseuri/History.md create mode 100644 node_modules/parseuri/LICENSE create mode 100644 node_modules/parseuri/Makefile create mode 100644 node_modules/parseuri/README.md create mode 100644 node_modules/parseuri/index.js create mode 100644 node_modules/parseuri/package.json create mode 100644 node_modules/parseuri/test.js create mode 100644 node_modules/safe-buffer/.travis.yml create mode 100644 node_modules/safe-buffer/LICENSE create mode 100644 node_modules/safe-buffer/README.md create mode 100644 node_modules/safe-buffer/index.js create mode 100644 node_modules/safe-buffer/package.json create mode 100644 node_modules/safe-buffer/test.js create mode 100644 node_modules/socket.io-adapter/.npmignore create mode 100644 node_modules/socket.io-adapter/LICENSE create mode 100644 node_modules/socket.io-adapter/Readme.md create mode 100644 node_modules/socket.io-adapter/index.js create mode 100644 node_modules/socket.io-adapter/package.json create mode 100644 node_modules/socket.io-client/LICENSE create mode 100644 node_modules/socket.io-client/README.md create mode 100644 node_modules/socket.io-client/dist/socket.io.js create mode 100644 node_modules/socket.io-client/dist/socket.io.js.map create mode 100644 node_modules/socket.io-client/dist/socket.io.slim.js create mode 100644 node_modules/socket.io-client/dist/socket.io.slim.js.map create mode 100644 node_modules/socket.io-client/lib/index.js create mode 100644 node_modules/socket.io-client/lib/manager.js create mode 100644 node_modules/socket.io-client/lib/on.js create mode 100644 node_modules/socket.io-client/lib/socket.js create mode 100644 node_modules/socket.io-client/lib/url.js create mode 100644 node_modules/socket.io-client/package.json create mode 100644 node_modules/socket.io-parser/LICENSE create mode 100644 node_modules/socket.io-parser/Readme.md create mode 100644 node_modules/socket.io-parser/binary.js create mode 100644 node_modules/socket.io-parser/index.js create mode 100644 node_modules/socket.io-parser/is-buffer.js create mode 100644 node_modules/socket.io-parser/node_modules/debug/.coveralls.yml create mode 100644 node_modules/socket.io-parser/node_modules/debug/.eslintrc create mode 100644 node_modules/socket.io-parser/node_modules/debug/.npmignore create mode 100644 node_modules/socket.io-parser/node_modules/debug/.travis.yml create mode 100644 node_modules/socket.io-parser/node_modules/debug/CHANGELOG.md create mode 100644 node_modules/socket.io-parser/node_modules/debug/LICENSE create mode 100644 node_modules/socket.io-parser/node_modules/debug/Makefile create mode 100644 node_modules/socket.io-parser/node_modules/debug/README.md create mode 100644 node_modules/socket.io-parser/node_modules/debug/karma.conf.js create mode 100644 node_modules/socket.io-parser/node_modules/debug/node.js create mode 100644 node_modules/socket.io-parser/node_modules/debug/package.json create mode 100644 node_modules/socket.io-parser/node_modules/debug/src/browser.js create mode 100644 node_modules/socket.io-parser/node_modules/debug/src/debug.js create mode 100644 node_modules/socket.io-parser/node_modules/debug/src/index.js create mode 100644 node_modules/socket.io-parser/node_modules/debug/src/node.js create mode 100644 node_modules/socket.io-parser/package.json create mode 100644 node_modules/socket.io/LICENSE create mode 100644 node_modules/socket.io/Readme.md create mode 100644 node_modules/socket.io/lib/client.js create mode 100644 node_modules/socket.io/lib/index.js create mode 100644 node_modules/socket.io/lib/namespace.js create mode 100644 node_modules/socket.io/lib/socket.js create mode 100644 node_modules/socket.io/package.json create mode 100644 node_modules/to-array/.npmignore create mode 100644 node_modules/to-array/LICENCE create mode 100644 node_modules/to-array/README.md create mode 100644 node_modules/to-array/index.js create mode 100644 node_modules/to-array/package.json create mode 100644 node_modules/ultron/LICENSE create mode 100644 node_modules/ultron/README.md create mode 100644 node_modules/ultron/index.js create mode 100644 node_modules/ultron/package.json create mode 100644 node_modules/uws/LICENSE create mode 100644 node_modules/uws/README.md create mode 100644 node_modules/uws/binding.gyp create mode 100644 node_modules/uws/build_log.txt create mode 100644 node_modules/uws/package.json create mode 100644 node_modules/uws/src/Asio.h create mode 100644 node_modules/uws/src/Backend.h create mode 100644 node_modules/uws/src/Epoll.cpp create mode 100644 node_modules/uws/src/Epoll.h create mode 100644 node_modules/uws/src/Extensions.cpp create mode 100644 node_modules/uws/src/Extensions.h create mode 100644 node_modules/uws/src/Group.cpp create mode 100644 node_modules/uws/src/Group.h create mode 100644 node_modules/uws/src/HTTPSocket.cpp create mode 100644 node_modules/uws/src/HTTPSocket.h create mode 100644 node_modules/uws/src/Hub.cpp create mode 100644 node_modules/uws/src/Hub.h create mode 100644 node_modules/uws/src/Libuv.h create mode 100644 node_modules/uws/src/Networking.cpp create mode 100644 node_modules/uws/src/Networking.h create mode 100644 node_modules/uws/src/Node.cpp create mode 100644 node_modules/uws/src/Node.h create mode 100644 node_modules/uws/src/Socket.cpp create mode 100644 node_modules/uws/src/Socket.h create mode 100644 node_modules/uws/src/WebSocket.cpp create mode 100644 node_modules/uws/src/WebSocket.h create mode 100644 node_modules/uws/src/WebSocketProtocol.h create mode 100644 node_modules/uws/src/addon.cpp create mode 100644 node_modules/uws/src/addon.h create mode 100644 node_modules/uws/src/http.h create mode 100644 node_modules/uws/src/uWS.h create mode 100644 node_modules/uws/uws.js create mode 100755 node_modules/uws/uws_darwin_46.node create mode 100755 node_modules/uws/uws_darwin_47.node create mode 100755 node_modules/uws/uws_darwin_48.node create mode 100755 node_modules/uws/uws_darwin_51.node create mode 100755 node_modules/uws/uws_darwin_57.node create mode 100755 node_modules/uws/uws_darwin_59.node create mode 100755 node_modules/uws/uws_linux_46.node create mode 100755 node_modules/uws/uws_linux_47.node create mode 100755 node_modules/uws/uws_linux_48.node create mode 100755 node_modules/uws/uws_linux_51.node create mode 100755 node_modules/uws/uws_linux_57.node create mode 100755 node_modules/uws/uws_linux_59.node create mode 100755 node_modules/uws/uws_win32_48.node create mode 100755 node_modules/uws/uws_win32_51.node create mode 100755 node_modules/uws/uws_win32_57.node create mode 100755 node_modules/uws/uws_win32_59.node create mode 100644 node_modules/ws/LICENSE create mode 100644 node_modules/ws/README.md create mode 100644 node_modules/ws/index.js create mode 100644 node_modules/ws/lib/.DS_Store create mode 100644 node_modules/ws/lib/BufferUtil.js create mode 100644 node_modules/ws/lib/Constants.js create mode 100644 node_modules/ws/lib/ErrorCodes.js create mode 100644 node_modules/ws/lib/EventTarget.js create mode 100644 node_modules/ws/lib/Extensions.js create mode 100644 node_modules/ws/lib/PerMessageDeflate.js create mode 100644 node_modules/ws/lib/Receiver.js create mode 100644 node_modules/ws/lib/Sender.js create mode 100644 node_modules/ws/lib/Validation.js create mode 100644 node_modules/ws/lib/WebSocket.js create mode 100644 node_modules/ws/lib/WebSocketServer.js create mode 100644 node_modules/ws/package.json create mode 100644 node_modules/xmlhttprequest-ssl/LICENSE create mode 100644 node_modules/xmlhttprequest-ssl/README.md create mode 100644 node_modules/xmlhttprequest-ssl/autotest.watchr create mode 100644 node_modules/xmlhttprequest-ssl/example/demo.js create mode 100644 node_modules/xmlhttprequest-ssl/lib/XMLHttpRequest.js create mode 100644 node_modules/xmlhttprequest-ssl/package.json create mode 100644 node_modules/xmlhttprequest-ssl/tests/test-constants.js create mode 100644 node_modules/xmlhttprequest-ssl/tests/test-events.js create mode 100644 node_modules/xmlhttprequest-ssl/tests/test-exceptions.js create mode 100644 node_modules/xmlhttprequest-ssl/tests/test-headers.js create mode 100644 node_modules/xmlhttprequest-ssl/tests/test-redirect-302.js create mode 100644 node_modules/xmlhttprequest-ssl/tests/test-redirect-303.js create mode 100644 node_modules/xmlhttprequest-ssl/tests/test-redirect-307.js create mode 100644 node_modules/xmlhttprequest-ssl/tests/test-request-methods.js create mode 100644 node_modules/xmlhttprequest-ssl/tests/test-request-protocols.js create mode 100644 node_modules/xmlhttprequest-ssl/tests/testdata.txt create mode 100644 node_modules/yeast/LICENSE create mode 100644 node_modules/yeast/README.md create mode 100644 node_modules/yeast/index.js create mode 100644 node_modules/yeast/package.json create mode 100644 package-lock.json create mode 100644 package.json diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..c06ec41 --- /dev/null +++ b/README.txt @@ -0,0 +1,74 @@ +-------------------------------------------------------------------------------- + Air Hockey + + A simple browser-based air hockey game using + web sockets + +-------------------------------------------------------------------------------- +Developer: + Owen LeJeune + +Date: + March 8, 2018 + +-------------------------------------------------------------------------------- +Version: + node 8.9.4 + npm 5.7.1 + Tested on MacOS 10.13.2 + +-------------------------------------------------------------------------------- +Install + run "npm install" inside the root project directory + if that fails, run "npm install socket.io" + + Requires node.js installed + +-------------------------------------------------------------------------------- +Launch + "node app.js" from root project directory + +-------------------------------------------------------------------------------- +Testing + Visit http://localhost:3000/assignment3.html + To join the game, click "Join Game" and enter your name + Once another player has joined from another browser window, + the game will begin and puck will pick a random direction + to travel + Use the arrow keys on your keyboard to move your paddle + The paddle will not move until 2 players are present + When the puck enters one of the purple goals on either end, + the opposing player will score a point and the player's + positions will be reset, with the puck traveling in a new + random direction + If you attempt to join a game with 2 players, you will not be + allowed, but your name will appear in the Spectator box + below + You can toggle collision and goal sounds using the Toggle + Sounds button + +-------------------------------------------------------------------------------- +Organization: + app.js + html + assignment3.html + ding.mp3 + game.js + hit.mp3 + mute.png + rink.jpg + sound.png + style.css + node_modules + all modules required by node and socket.io + package-lock.json + package.json + README.txt + +-------------------------------------------------------------------------------- +Enhancements: + 1) Scoring + 2) Spectator list + 3) Puck collision sounds (toggle-able) + +-------------------------------------------------------------------------------- diff --git a/app.js b/app.js new file mode 100644 index 0000000..d6d5a27 --- /dev/null +++ b/app.js @@ -0,0 +1,309 @@ +const app = require("http").createServer(handler); +const fs = require("fs"); +const url = require("url"); +const io = require("socket.io")(app); +const PORT = process.env.PORT || 3000; +const ROOT_DIR = "html"; +const MIME_TYPES = { + css: "text/css", + gif: "image/gif", + htm: "text/html", + html: "text/html", + ico: "image/x-icon", + jpeg: "image/jpeg", + jpg: "image/jpeg", + js: "application/javascript", + json: "application/json", + png: "image/png", + txt: "text/plain" +}; +const timer = setInterval(handleTimer, 30); +const PLAYERS_AVAILABLE = { + p1: true, + p2: true +} +const PLAYER_ONE_STATE = 0; +const PLAYER_TWO_STATE = 1; +const SPECTATOR_STATE = 3; +const PLAYER_1_DEFAULT_X = 100; +const PLAYER_2_DEFAULT_X = 825; +const PLAYER_DEFAULT_Y = 200; +const PLAYER_DEFAULT_DIM = 75; +const PLAYER_DEFAULT_COLOUR = 'grey'; +const PUCK_DEFAULT_COLOUR = 'black' +const PLAYER_1_COLOUR = 'orange'; +const PLAYER_2_COLOUR = 'green'; +const PLAYER_DEFAULT_NAME = ""; +const PLAYER_DEFAULT_SCORE = 0; +const PUCK_DEFAULT_X = 500; +const PUCK_DEFAULT_Y = 235; +const PUCK_DEFAULT_RADIUS = 25; +const DIR_UP = -1; +const DIR_DOWN = 1; +const DIR_LEFT = -1; +const DIR_RIGHT = 1; +const DIR_NONE = 0; +const dXY = 5; + +var canvasWidth = 0; +var canvasHeight = 0; +var windowsID = 0; +var spectators = []; +var player1 = { + state: PLAYER_ONE_STATE, + x: PLAYER_1_DEFAULT_X, + y: PLAYER_DEFAULT_Y, + side: PLAYER_DEFAULT_DIM, + score: PLAYER_DEFAULT_SCORE, + colour: PLAYER_DEFAULT_COLOUR, + name: PLAYER_DEFAULT_NAME +}; +var player2 = { + state: PLAYER_TWO_STATE, + x: PLAYER_2_DEFAULT_X, + y: PLAYER_DEFAULT_Y, + side: PLAYER_DEFAULT_DIM, + score: PLAYER_DEFAULT_SCORE, + colour: PLAYER_DEFAULT_COLOUR, + name: PLAYER_DEFAULT_NAME +}; +var puck = { + x: PUCK_DEFAULT_X, + y: PUCK_DEFAULT_Y, + radius: PUCK_DEFAULT_RADIUS, + directionX: DIR_NONE, + directionY: DIR_NONE, + colour: PUCK_DEFAULT_COLOUR +} + +function get_mime(filename){ + let ext, type; + for(let ext in MIME_TYPES){ + type = MIME_TYPES[ext]; + if(filename.indexOf(ext, filename.length - ext.length) !== -1){ + return type; + } + } + return MIME_TYPES['txt']; +} + +app.listen(PORT); + +io.on("connection", (socket) => { + socket.on("newWindowLoad", (data) => { + var receivedData = JSON.parse(data); + canvasWidth = (receivedData.width > canvasWidth) ? receivedData.width : canvasWidth; + canvasHeight = (receivedData.height > canvasHeight) ? receivedData.height : canvasHeight; + var responseObj = {player1: player1, player2: player2, puck: puck, id: windowsID}; + windowsID++; + io.emit("newWindowLoadResponse", JSON.stringify(responseObj)); + }); + socket.on("keyPressed", (data) => { + var receivedData = JSON.parse(data); + if(receivedData.state === PLAYER_ONE_STATE){ + player1.x = receivedData.x; + player1.y = receivedData.y; + }else{ + player2.x = receivedData.x; + player2.y = receivedData.y; + } + io.emit("playerMove", data); + }); + socket.on("newPlayerRequest", (data) => { + var receivedData = JSON.parse(data); + var name = receivedData.name; + if(PLAYERS_AVAILABLE.p1){ + PLAYERS_AVAILABLE.p1 = false; + player1.colour = PLAYER_1_COLOUR; + player1.name = name; + var responseObj = {id: receivedData.id, player: player1}; + io.emit("newPlayerResponse", JSON.stringify(responseObj)); + }else if(PLAYERS_AVAILABLE.p2){ + PLAYERS_AVAILABLE.p2 = false; + player2.colour = PLAYER_2_COLOUR; + player2.name = name; + var responseObj = {id: receivedData.id, player:player2}; + io.emit("newPlayerResponse", JSON.stringify(responseObj)); + }else{ + spectators.push({id: receivedData.id, name: name}); + console.log(`Spectators ${spectators}`); + io.emit("newPlayerResponse", JSON.stringify({id: receivedData.id, player: SPECTATOR_STATE, names: spectators})); + } + startGame(); + }); + socket.on("playerLeaveGame", (data) => { + var receivedData = JSON.parse(data); + if(receivedData.state === PLAYER_ONE_STATE){ + PLAYERS_AVAILABLE.p1 = true; + resetPlayer(player1); + }else if(receivedData.state === PLAYER_TWO_STATE){ + PLAYERS_AVAILABLE.p2 = true; + resetPlayer(player2); + }else{ + var id = receivedData.id; + for(let spectator of spectators){ + if(id === spectator.id){ + spectators.splice(spectator, 1); + break; + } + } + io.emit("spectatorLeft", JSON.stringify({spectators: spectators})); + } + }); +}); + +function resetPlayer(player){ + player1.x = PLAYER_1_DEFAULT_X; + player1.y = PLAYER_DEFAULT_Y; + player2.x = PLAYER_2_DEFAULT_X; + player2.y = PLAYER_DEFAULT_Y; + player1.score = PLAYER_DEFAULT_SCORE; + player2.score = PLAYER_DEFAULT_SCORE; + player.colour = PLAYER_DEFAULT_COLOUR; + player.name = PLAYER_DEFAULT_NAME; + puck.x = PUCK_DEFAULT_X; + puck.y = PUCK_DEFAULT_Y; + puck.directionX = DIR_NONE; + puck.directionY = DIR_NONE; + var responseObj = {player1: player1, player2: player2, puck: puck}; + io.emit("playerReset", JSON.stringify(responseObj)); +} + +function startGame(){ + if(!PLAYERS_AVAILABLE.p1 && !PLAYERS_AVAILABLE.p2){ + puck.directionX = (Math.random() < 0.5) ? DIR_LEFT : DIR_RIGHT; + puck.directionY = (Math.random() < 0.5) ? DIR_UP : DIR_DOWN; + io.emit('startGame', JSON.stringify(puck)); + } +} + +function handler(request, response){ + let urlObj = url.parse(request.url, true, false); + + console.log("\n============================") + console.log("PATHNAME: " + urlObj.pathname) + console.log("REQUEST: " + ROOT_DIR + urlObj.pathname) + + let receivedData = "" + + request.on("data", (chunk) => { + receivedData += chunk; + }); + + request.on("end", () =>{ + console.log("REQUEST END: "); + + if(request.method == "GET"){ + console.log("METHOD: GET"); + fs.readFile(ROOT_DIR + urlObj.pathname, (err, data) => { + if(err){ + console.log("ERROR: " + JSON.stringify(err).red); + response.writeHead(404); + response.end(JSON.stringify(err)); + return; + } + response.writeHead(200, {"Content-Type": get_mime(urlObj.pathname)}); + response.end(data); + }); + } + }); +} + +function handleTimer(){ + if(!PLAYERS_AVAILABLE.p1 && !PLAYERS_AVAILABLE.p2){ + puck.x = puck.x + 5 * puck.directionX; + puck.y = puck.y + 5 * puck.directionY; + + var hit = false; + + if(puck.x + puck.radius >= canvasWidth){ + if(puck.y > canvasHeight/3 && puck.y < canvasHeight*(2/3)){ + puck.directionX = 0; + puck.directionY = 0; + player1.score += 1; + pointScored(); + }else{puck.directionX = DIR_LEFT;} + } + if(puck.x-puck.radius <= 0){ + if(puck.y > canvasHeight/3 && puck.y < canvasHeight*(2/3)){ + puck.directionX = 0; + puck.directionY = 0; + player2.score += 1; + pointScored(); + }else{puck.directionX = DIR_RIGHT;} + } + if(puck.y-puck.radius < 0){hit = true; puck.directionY = DIR_DOWN;} + if(puck.y + puck.radius > canvasHeight){hit = true; puck.directionY = DIR_UP;} + + if(hit){io.emit("collision", null);} + + detectCollision(); + } +} + +function detectCollision(){ + var collision = false; + //TOP + if(player1.x <= puck.x && player1.x+player1.side >= puck.x + && puck.y+puck.radius >= player1.y && puck.y < player1.y){ + collision = true; + puck.directionY = DIR_UP; + } + if(player2.x <= puck.x && player2.x+player2.side >= puck.x + && puck.y+puck.radius >= player2.y && puck.y < player2.y){ + collision = true; + puck.directionY = DIR_UP; + } + //BOTTOM + if(player1.x <= puck.x && player1.x+player1.side >= puck.x + && puck.y-puck.radius <= player1.y+player1.side && puck.y > player1.y+player1.side){ + collision = true; + puck.directionY = DIR_DOWN; + } + if(player2.x <= puck.x && player2.x+player2.side >= puck.x + && puck.y-puck.radius <= player2.y+player2.side && puck.y > player2.y+player2.side){ + collision = true; + puck.directionY = DIR_DOWN; + } + //RIGHT + if(puck.y >= player1.y && puck.y <= player1.y+player1.side + && puck.x-puck.radius <= player1.x+player1.side && puck.x > player1.x+player1.side){ + collision = true; + puck.directionX = DIR_RIGHT; + } + if(puck.y >= player2.y && puck.y <= player2.y+player2.side + && puck.x-puck.radius <= player2.x+player2.side && puck.x > player2.x+player2.side){ + collision = true; + puck.directionX = DIR_RIGHT; + } + //LEFT + if(puck.y >= player1.y && puck.y <= player1.y+player1.side + && puck.x+puck.radius >= player1.x && puck.x < player1.x){ + collision = true; + puck.directionX = DIR_LEFT; + } + if(puck.y >= player2.y && puck.y <= player2.y+player2.side + && puck.x+puck.radius >= player2.x && puck.x < player2.x){ + collision = true; + puck.directionX = DIR_LEFT; + } + io.emit('timerTick', JSON.stringify(puck)); + if(collision){io.emit("collision", null);} +} + +function pointScored(){ + puck.x = PUCK_DEFAULT_X; + puck.y = PUCK_DEFAULT_Y; + puck.directionX = (Math.random() < 0.5) ? DIR_LEFT : DIR_RIGHT; + puck.directionY = (Math.random() < 0.5) ? DIR_UP : DIR_DOWN; + player1.x = PLAYER_1_DEFAULT_X; + player1.y = PLAYER_DEFAULT_Y; + player2.x = PLAYER_2_DEFAULT_X; + player2.y = PLAYER_DEFAULT_Y; + var returnObj = {p1Score: player1.score, p2Score: player2.score, p1x: player1.x, + p1y: player1.y, p2x: player2.x, p2y: player2.y, puck: puck}; + io.emit("pointScored", JSON.stringify(returnObj)); +} + +console.log("Server Running at PORT: 3000 CNTL-C to quit"); +console.log("To Test: open several browsers at: http://localhost:3000/assignment3.html") diff --git a/html/.DS_Store b/html/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..bc35fad0e4bcd5cf84e998f4d9c83ef76cf50a6a GIT binary patch literal 6148 zcmeHKJx>EM41I=56tUa}V}8L&h>_(~m4TT*KwD60xweRwf$bK448Ibd?SQ!BSP??@ zDSr8|o#aWE!~kUUbaM(60ER4zqLm)e?%tujY&;-}#h7D_6>h0_J%RpWm#)3Q1Y3R! zd|m$;O5AZDE7X_uW;U%iQ?mumiRGJ#ZRvo16We!*CAJ;w*N*iNkDO_Zd&Xbl0rR%K z9Cz#wxw0LeQIppaGhJ!N{&GECnFyGuni8%_Y<)WvntbjvS$gyAs`1a*84D&i<6`s*H`JyF+sFA$jJH zfqicldjDVWm+4LN+b+=x27-Zq#()gQSK|>kmG9PX+ta%? vv0SsLs9mEK3hS*$02_LaoY9y<|he literal 0 HcmV?d00001 diff --git a/html/assignment3.html b/html/assignment3.html new file mode 100644 index 0000000..16d32a2 --- /dev/null +++ b/html/assignment3.html @@ -0,0 +1,72 @@ + + + + + Air Hockey + + + + + + +

Air Hockey

+ + + + + + + + + + + + +
+ +

Player 1

+

+

0

+ +
+
+ + + + + + +
+
+ +

Player 2

+

+

0

+ +
+

Spectators

+
+
+ + + + diff --git a/html/ding.mp3 b/html/ding.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..ba6f7ba040acd364f998240bca90e150dcc643f5 GIT binary patch literal 5605 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 { + if(id === -1){ + var receivedData = JSON.parse(data); + player1 = receivedData.player1; + player2 = receivedData.player2; + puck = receivedData.puck; + id = receivedData.id; + drawCanvas(); + } +}); + +socket.on("timerTick", (data) => { + puck = JSON.parse(data); + drawCanvas(); +}); + +socket.on("playerMove", (data) => { + var receivedData = JSON.parse(data); + if(receivedData.id !== id){ + if(receivedData.state === PLAYER_ONE_STATE){ + player1.x = receivedData.x; + player1.y = receivedData.y; + }else{ + player2.x = receivedData.x; + player2.y = receivedData.y; + } + } + drawCanvas(); +}); + +socket.on("newPlayerResponse", (data) => { + var receivedData = JSON.parse(data); + var playerData = receivedData.player; + if(receivedData.player !== SPECTATOR_STATE){ + if(playerData.state === PLAYER_ONE_STATE){ + player1 = playerData; + if(receivedData.id === id){player = player1;} + }else{ + player2 = playerData; + if(receivedData.id === id){player = player2;} + } + }else{ + printSpectators(receivedData.names); + } + drawCanvas(); +}); + +socket.on("playerReset", (data) => { + var receivedData = JSON.parse(data); + player1 = receivedData.player1; + player2 = receivedData.player2; + puck = receivedData.puck; + if(player !== null){ + player = (player.state === PLAYER_ONE_STATE) ? player1 : player2; + document.removeEventListener('keydown', handleKeyDown); + document.removeEventListener('keyup', handleKeyUp); + } + drawCanvas(); +}); + +socket.on("pointScored", (data) => { + if(goalSound){GOAL_SOUND.play()}; + var receivedData = JSON.parse(data); + puck = receivedData.puck; + player1.score = receivedData.p1Score; + player2.score = receivedData.p2Score; + if(player !== null){ + if(player.state === PLAYER_ONE_STATE){ + player.x = receivedData.p1x; + player.y = receivedData.p1y; + player2.x = receivedData.p2x; + player2.y = receivedData.p2y; + }else{ + player.x = receivedData.p2x; + player.y = receivedData.p2y; + player1.x = receivedData.p1x; + player1.y = receivedData.p1y; + } + } + drawCanvas(); +}); + +socket.on("spectatorLeft", (data) => { + var receivedData = JSON.parse(data); + printSpectators(receivedData.spectators); +}); + +socket.on("startGame", (data) => { + if(player !== null){ + document.addEventListener('keydown', handleKeyDown); + document.addEventListener('keyup', handleKeyUp); + } + puck = JSON.parse(data); +}); + +socket.on("collision", (data) => { + if(collisionSound){HIT_SOUND.play();} +}) + +document.addEventListener("DOMContentLoaded", () => { + socket.emit("newWindowLoad", JSON.stringify({width: canvas.width, height: canvas.height})); +}); + +window.addEventListener("beforeunload", (e) => { + leaveGame(); +}); + +function printSpectators(names){ + var spectators = names; + console.log(spectators); + SPECTATORS.innerHTML = "

"; + for(let spectator of spectators){ + SPECTATORS.innerHTML = SPECTATORS.innerHTML + `${spectator.name} `; + } + SPECTATORS.innerHTML = SPECTATORS.innerHTML + `

`; +} + +function handleKeyUp(e){ + console.log("key UP: " + e.which); + if(e.which == RIGHT_ARROW | e.which == LEFT_ARROW | e.which == UP_ARROW | e.which == DOWN_ARROW){ + socket.emit("keyPressed", JSON.stringify({id: id, state: player.state, x: player.x, y: player.y})); + drawCanvas(); + } +} + +function handleKeyDown(e) { + console.log("keydown code = " + e.which); + + if(player.state === PLAYER_ONE_STATE){ + if(e.which == UP_ARROW && player.y >= dXY) player.y -= dXY; + if(e.which == RIGHT_ARROW && player.x + player.side + dXY <= canvas.width/2) player.x += dXY; + if(e.which == LEFT_ARROW && player.x >= dXY) player.x -= dXY; + if(e.which == DOWN_ARROW && player.y + player.side + dXY <= canvas.height) player.y += dXY; + }else{ + if(e.which == UP_ARROW && player.y >= dXY) player.y -= dXY; + if(e.which == RIGHT_ARROW && player.x + player.side + dXY <= canvas.width) player.x += dXY; + if(e.which == LEFT_ARROW && player.x >= dXY + canvas.width/2) player.x -= dXY; + if(e.which == DOWN_ARROW && player.y + player.side + dXY <= canvas.height) player.y += dXY; + } + + socket.emit("keyPressed", JSON.stringify({id: id, state: player.state, x: player.x, y: player.y})); +} + +var drawCanvas = function(){ + + document.getElementById('player1Name').innerHTML = player1.name; + document.getElementById('player1Score').innerHTML = player1.score; + document.getElementById('player2Name').innerHTML = player2.name; + document.getElementById('player2Score').innerHTML = player2.score; + + var context = canvas.getContext("2d"); + + var rinkBackground = new Image(); + rinkBackground.src = "rink.jpg"; + rinkBackground.onload = function(){ + var pattern = context.createPattern(this, "no-repeat"); + context.fillStyle = pattern; + context.fillRect(0, 0, canvas.width, canvas.height); + + context.fillStyle = "black"; + context.fillRect(0, 0, GOAL_WIDTH, canvas.height); + context.fillRect(0, 0, canvas.width, GOAL_WIDTH); + context.fillRect(canvas.width-GOAL_WIDTH, 0, GOAL_WIDTH, canvas.height); + context.fillRect(0, canvas.height-GOAL_WIDTH, canvas.width, GOAL_WIDTH); + + context.fillStyle = "#9370db"; + context.fillRect(0, GOAL_HEIGHT, GOAL_WIDTH, GOAL_HEIGHT); + context.fillRect(canvas.width-GOAL_WIDTH, GOAL_HEIGHT, GOAL_WIDTH, GOAL_HEIGHT); + + context.fillStyle = puck.colour; + context.beginPath(); + context.arc(puck.x, puck.y, puck.radius, 0, 2*Math.PI, false); + context.fill(); + + context.fillStyle = player1.colour; + context.fillRect(player1.x, player1.y, player1.side, player1.side); + + context.fillStyle = player2.colour; + context.fillRect(player2.x, player2.y, player2.side, player2.side); + + //draw player numbers on paddle if in use + context.fillStyle = "black" + if(player1.colour !== 'grey'){ + let x = player1.x + (player1.side/2) - 5; + context.fillRect(x, player1.y+15, 10, player1.side-30); + } + if(player2.colour !== 'grey'){ + let x = player2.x+15; + let y = player2.y+10; + context.fillRect(x, y, player2.side-30, 10); + y = player2.y+30; + context.fillRect(x, y, player2.side-30, 10); + context.fillRect(x, y, 10, 20); + y = player2.y+50; + context.fillRect(x, y, player2.side-30, 10); + x = player2.x+player2.side-25; + y = player2.y+10; + context.fillRect(x, y, 10, 20); + } + } +} + +function joinGame(){ + if(!joined){ + var name = prompt("Please enter your name", ""); + socket.emit("newPlayerRequest", JSON.stringify({id: id, name: name})); + joined = true; + } +} + +function leaveGame(){ + var state = (player !== null) ? player.state : SPECTATOR_STATE; + socket.emit("playerLeaveGame", JSON.stringify({id: id, state: state})); + player = null; + joined = false; + document.removeEventListener('keydown', handleKeyDown); + document.removeEventListener('keyup', handleKeyUp); +} + +function toggleSound(){ + collisionSound = (collisionSound) ? false : true; + goalSound = (goalSound) ? false : true; + document.getElementById('soundstate').src = (collisionSound) ? SOUND_ICON : MUTE_ICON; +} diff --git a/html/hit.mp3 b/html/hit.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..370769d4afeedd8ca2f983b4468675a42a677273 GIT binary patch literal 3599 zcmds3c{r4N8~)9LF)_v%8jdv9EJM>+j^;$RBwGjxb%uuQTPP8)AqUCUkhLtsK`2X( zR9`cwWI5T}kwi(Bs8hB%j% z6BQ7WRsc4(k;h~pEa3Z#|Jx^bh0PNPwgdDzAOVV}!h8{cNtk`LJyMX#D|&C+M&*M5 z`Rf=UZ5Qa_@Wp)``*POci@q*a`Q#e}A0|c_6{GylOcqH53c?3H&zl2)f8t*5ix+@6 zDMNk-7V+eZY&fIKv~}T9(476S))PormXVy8zyHQkfhH^PGIK=kKcZ^XL^Ca%iaD*l zRQPLj)jW}%(95wPD1gQ(w+EjtHVcM+{K?v)*#=joi-|IfC@s+axM#lHdC9#;g8EzO za$5G;)fff*hk)&;UOt`;L7&?08{Xi0oNk9C_xgHak37dGZryuTJ^g zs{V*7UILF}0}u>advGQ>x1Xj8nV=rGGv4qc;Z(eIs0TVhpGn1{u+kEI#|nT~{VNa) zW#*9G%8evHW}L${Fe*#*Zrq!ugARxyC(N%I4=slF|&uBn^w1IkiAC9Im~ z4JHt>h(Ag3$pox$Rxbx1X8O#`t=AYk?8UwXHNCFKyjLC5iN;hhs@J%RRod@hyt^12{cFthoX z3mN&orNnC26%u8{f}tZs@iUd#*9PL=+(@LxJ~W`R|uA z$oo{Y=vzUE)5YZhwgJ>Tl#|*ko!|nDoN;1`brc(XtN&1O4^2qewG1D&e)jSy^XDsI zlvV6FRhzL}N{qm4xzOOsO6}Yx7{y)BwM4)U>QYpreeP{Jc1T%q{Cp6?i5DMWK#NMi zEp)#z_Nr1{$$>mMIiGGA+_OX-HO|i|w`X~zw`wN}7imVfZ}Z}$kmFct;`+t@bR_6T z`%N+{&nsxLoTRqa)5x$`3yg{Se1N}mwkVv69X}8+5;*ise6O|q`=eZ@-qtyv#xuHW zw*sSTcZxFapKwck)b)w`)$y8YXUOFj6Frf753X=u1ebM|Jxr>J)_wD3w&s>W$`B zx0NZYBMQLIk9Sj@_pj2Upt}bfnI&)C00r;)mJ5w#?RY}#dvG8B^ zdn58wTFgJ_yf*4K(AFj`_;oc(@MpYgy=3dbIyfQcGaR6KEbVUH+vV}Sa8fk*keOjb%=jJ3g9bT(*l?%XW-=C`@duI&S;$3?a+KlR*JQeEvM@ z$%_Z!D6+Q4fFstX?|@)hTsS>ZrYpBT?M@sdjm9B7Wnz8I4vC`!nV9IkicYnod85m|0m+YwLjKSS4I5o{W1Ky3E9Zab{@0swjykCa{2P&5czV_Q@qBaQtpn z(l7Q(ief4|$v)>tP6Jul@I>sI5^jsS(s(EB>aOWIb$Q0QfKsIU&X3WtP{lK*%*@Gm z)dh@-plsTY`r7*Xv8SGSo(;RK`ecGNyGDuAZ(6EwtIe@yS`kV5F>l)O!UV<1ll5ox z`K7cRc+HM*oJW=Nqu{QbJ}f>$Fg*#~N)+=){QA5WdUu@F-+!d@=uB(amx#RNv?N5c zj;ZbiIB@4{6MG%@Kquc{p(8Tshn6JNl>}e!nB4nXgA#f2`3-&8z$Y(FQ3`2R_BXr- z)(EatFN`XQ{kx%qnMpXWVnj#~-1~$l$y15DLZi<@ixE`ENFj@sZ^Q}HMvu=YF&ks~M~uaRv?QzR@MRJh#_o)q;B zJhjWJs_7BTKb?{ivYk8k>4K17n}UWRq4VyF?ND#k;JMT)3lw*CT2BwDv)gD2`9In=%DbQ1_ zNzCx`kh|F6U~8M#9Z$egzF0y)pfYBZzQ-}d_CpUP~Lz#0jXxI(4d|p8veJN z8hMUdh;_eMy^S0Uns>!RgfW#s3t);2a&ymkjS|@f>kZm*|jrU+1W?&*^m@$?Y!^@q?M`FyDsXTqQ%dS`K7n zd9mQ4)lJHeZT#0>s;m1heAkq-4lx^y1f+iFiNm zqrZ>R)pav}sDD34YiK+CgV=D-3ba_d$2L;PlKPD}5yFb`r}Dp+Lo07N{Da~CoxkF) l*w8-#zVIKrX9Ib5_QDZ=hi3o) literal 0 HcmV?d00001 diff --git a/html/mute.png b/html/mute.png new file mode 100644 index 0000000000000000000000000000000000000000..b16905ae78c0e2e1abca2c5d9bcdde7fa81df079 GIT binary patch literal 1225 zcmeAS@N?(olHy`uVBq!ia0vp^av;pX1|+Qw)-3{3jKx9jP7LeL$-D$|6p}rHd>I(3 z)EF2VS{N990fib~Fff!FFfhDIU|_JC!N4G1FlSew4N!u!z$3Dlfr0M`2s2LA=92~* z7MU3mQ4-h?X&sHg;q@=(~U%$M( zT(8_%FTW^V-_X+1Qs2Nx-^fT8s6w~6GOr}DLN~8i8Da>`9GBGMv-yz4m7Mv!3;@j!0}@Z5`YD?pSBhTaODSftPpO@{LXZ z#yLl0(X}fsw`Z0-*ZO9=V`)eK{vB)Ogtkn4+5bVlhPB)wQF`~oSs_)zw@r(rx>lLK zow+W1(wt-aIeb5{g@wk6?TtP1Pvh9{P%Ja_NJ-GaZ{)!D>?)i4_YmMDu=XCjIq;|b;I-jUD|FGXv=FV`=$(xx|KTh1b z*UMt9-fH(6q4f3Jr02g{{mCl6bIvR2Gg|*-Z#}!Pq*A^9fZqJFWke~|rB z{!bvUVc+e)N9vlw-pz`dVtz@sLa6<1d2!hEQ>SzHci6xG_DOwf;BC?EuBp$uOS%3l zy%E#jUOVk4Fkr)TtPQtz{3u+s?@->y%9`qhA69Q;>D~B=Q$s5B9^czNX%9u->2HXx zStj!CyUo<;xAWB5osRTx{AC71E#uUYd| x-L|(KY}Z4=#c!!B%d0(asU4xY^YdxL|BMn2rz3x4^ap~<3{O`-mvv4FO#sND`9uH! literal 0 HcmV?d00001 diff --git a/html/rink.jpg b/html/rink.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8664a052c503cc1556fd4db3d06560a9465cab69 GIT binary patch literal 189678 zcmeEvdt6NU|NkMhuCrKTQ-hXR%gC*z%USEvT5Rqink5Ozpi-)t!-fzB?Fy+uh{7yM z=yD{Lq(&;K)HIEn?laTOG&5(;IrDqZbeqDi@Avz={PFwb@z|NEGv~ZtulMWnd_7;U zb5{FKTLFFj>%v6~p&mUT=oj!0(h8t!3;eckg`lNNq3jZV+dpf-t_?gpdQ~s zz4h-Q=+_>m9q(84n9z1iPY4R$4)tm~W<7Y-{eUy;zTNiP`!oa@gHOGtPP3YNx&6J> z)Tx(ybYAIl&-Swz)m%1ef8Rq6z6Vy>cg!|#@7;4~v|V0PHf>>ScAMhL@TB=|+D)^X zGL;6|!hX9qxq7&HkKXL&zI~V7SaBjccJ%fwc4M7pE}gn`_dK_4+kf%j>$cMWw^gqG z9KYCZQ8WS z;E2gy`*(S7@|(QN%cA`Z^WD5$_io?qy`8aZwC;?XHZy#@?Z%F!fh*A3E}?tdu~z%h z|M~fk2L7Xg|7hSp8u*U}{-c5a|1{8vcHDLWh~o>e45V#@eq6SV;mz>c#@Ic2`jn~A zk3TP3+Diw_z>og@IQ`qN3(QUwv!VOFY7g{1-=O-LrF{ks{;G%EsK%(rV5sNd9!7(E zXrDt=0N{G}(EsSa20=zWd-doI^)ddcZ@>QFfV8in9!B7IM!ov4M(nP%Twv`Mx7z30UulP%^B3+rAaq!>^+Df$Bfp(6 z@%tZV&-rE1uTE>%t#{wHeTT2#e*YuEM~@vpeJE9UR`hY61!KY98* zJtOl)*2~ugg>Q@A6_-?esHzs#)Yi%5iWa3xjp?KW0JK#|@L#>0Iw5-X?vxU!q$iNm zsHaiyp1pha>J{7r=*Z~nA!B-twwgP%_tde|mVfh8pXnBxejc`G#f*c?zB_Ye-o4?* zn`f?+S-ZzCSasI&>KmZE5qdeSfglSVfGDfi=!DtgwpAyOm$%P8 zolFOU4jpclEA-F5T1AVx)+XHjxCd?WJxgnsFuz^IN@1Ij%^gyfLh}IL|DXM6!AbsS zX8_;UmOulH^y(W7jEguS#L!nY42`0JrH)9hYye9&T*!VtN1=sYS<7I}VWOWF`UyGBS;ce^%;~y} zv&OPw-D){kz`^`H{$+j+lGyc3pZK)ug17WMlNP-%@RXtGu})dAC1IrCzD3|yGrNDU z8E()*7g^J_kT)_ESxB!^VpajE#V2PPE_;Uzh3mD@c}6v&?2ip24``t=_BS#1GoP-f z8;?fv0sTs!c}5 zb)MH{wvaq2Q9jo~j<~vl^xLAHSV)l;n#zBrg_=y{lZYPV&&=ft>Y=)>YFdieacbSw z3XF>Lh%wkeVD@*rXb4>T>Qy+0CkxZq5Efc!p%yx^a-e~9F=6JB(`nb`<>;A?Q@;%4 zCgW%EXrgBg7D#&>>4hhv* z!3kzrU_t3P@@84_eoj~md8RhdC-M@qoPY(Kz08DWE#y%w^Y1u2u+I=+pEjNL8F;Lj z{+ja_^&H~IddcFEo&gE*YOez&SFhfMFoidwdITvM;>DVltarp%w!+bw*s^A(*42E)82bjuchok`HudpTFZ=xeb z3f3GoT!ZqsJoGM6T8d{Y7z(%|G9)Uq{WOci97nR>U<~?;HkAhE$&h%`p0$8H%4%jc zlFRnl*_#Kv#L>qJwxeL{ocQq7oi3UlD=G2I4$Yfc%WUrhc$2q%K$eW?)QUnb(Ry&^(85 z5M9vJLV2IC0D3!X1^m`i?RK)fm+BSv&Z>A*1|jonHIv-L@$(j}zQ+Cpl^+@T|{w;HWprJsnY-Eqjx@5faJ-I|HFAlFe5 zzXp+6%aIyu8NKOA$JLJG0=!-`{eS>t6e5Li(0~E?^J~Ze1kyqqwa^t_4XxQ|&5=_k z6_g6J-bpMLBOmS`2wEx3$BVVlY%LT|ea#hXp%2zK{Sk_OT`OGkGpgh%;YH1Jz*S-< zImyz2e?4V2u|(u*-!lHhY8Rwf?RW+==Vnn~!mk}`Rw}hnv&mDO`WBvv{74oMg9u}l z7OHi;hA&pv>-P|KM_jegtPQj5KyZERIlU*OPpbe=o55v0LjJ?JEZkeOtC>lwiLZgNu{pCN_( zx4gG7kGfxp(q{O~{EaP2kWdtSY!vy278-5bbh1Nsy;F!H^$-R%fG~s( z!gQRb_3(d$FjvuVzR0n~1G69xYa#O~Eizjqi!gqf#D4vBCVmx<)$lPhGDr(i$t`Mb zDLNamAzu(v2uoFT4SX37P!o86Vh?eG2*RsJ*#A|F!_Gy(-Oh6^BD?oqqB~$^Sf*Ot zs$O85uJV+KV!ds~uHj}-GC)9N#HEy~gBs8~q_5SScm#$IYN5N-*EA6Ak-n)4It6!< zi%Y2Pcu_5joq^bDAs)Y8Bp<2~tIak=kH66Xk3dFgp$}(Ngvq7 z=yW|4v?NcU010l^1l=2d{Mos`^jqBO(O;m)Yi|!_?C6by+T%L^bIwfeg(I|3F|Eb{ zGr|wmBsAM^RCCJgUDQa~{28h^A$%PMnY9L%YNY+8j&h|eQziyQ!5ca-fDm+>7TT(X zX2KkbNDC>1a!cUYr$6vlFkylD;|9`4y$TOYrmLx;nF4uR@^`{gb@JfCDB z5l9KOCJq~l`-(NBV@J5tLkx}{V!(1YJ;X41Z+E^Vev@mbsX2X7rEvV>aT4T%H+-2` zUn;=eO9k8pUrhW&3?nR533Z%n_)pL4wnb2Rj0$Q!DxXdCCV$#5*1_44fxhzK68?6a z_r3+s1ObxM9w4vWN~8(UO1O?vM)$xomDZ(NXo`NFs~&^;j-cI8;H~xDtViPAE(j!nga!0>miFMomTa}9+7avVcN5`H zFmPGBwE>F;Np>rq4U%lMDyk#N4tngdYSr6Li1J@52IFuH6oc;M>F&i~$}AA2Yxu`l zHrV18MhjK8|9QzpkY7tx#+aBGgv>=w4+VS8g2=vPJjlcVO)XwB_K`XD3h50;BE^ha zON@qZuJsSp7iuw~=8@K2suTd@r#B(}kgv7S3S=j|0~AYkX+?PB58t{KyG8#11WF2i zK~M_q5Z-96h?@!wlf`2B5aD{{wy4x2wKG})3(8jOEXYaPVL?e|XAPAC>d`NJ?`Gu$yyjyT~2e zjQor*#XX20h#|yKRelqiKyD0N`0Ix4_wQOdS+Jwk3)FOF!k;Ssb+U|=Pj2zq=rY{E z1oUJFqRW!#F{Cw1g2L@wX9m#e?#oc>aypNWIe#umg0qBxcrJ;PQWX|TlNONdGmDvy zL5q8c5))o}thwW|yoxD~#`w@2JOk%z7FV%PlP8EuKnlcoziZX$&E{I66mwi+z~aQ* z7vnj2sm8U6a)C$#`*EN2!Z>wE&lZYAWREo(k+RhGT&D$J~k5ojTf*# zv#9y(%eqdVx$~*$^0941?$_}U&wx$-GZFERcnjFrF+cPMIfZ3Io?)FL&)`l z;(+1j|DmLd1-SU=$~MZslx-pE2H+2%_SE}BEv1_~fUB)iVekd|MJ?os$H|Zfgii}S zm%ogFE6URW+}ylZxUxXv7(s*!9seXxND*U&V?Hep4oP{Vfvaz|TdmFu_5*gzr!9KM zu9)bfm*i(Pt%jlJ1X_?5N0~d2u8S1iWd)&hA>+{#Y1f02Wcp&=ybWQZ@kKf|urM;M?|bYGnz*$R%$9?v0uM9)Gf_ zZF6JSfa-LIL-ad_z|c6?-;&CAOq2VQXhhd5fKRQ_o~MuYoVI8m(lqGR+b;5dX;k}X za8Y<`MvQI&^x=W-@`P;ubWK=&bUiFeF}zkx*c8rrdsijfQBGREvqN$tX3goUN)_y!JtWLJjLbWOb=NYLQC@Z2enXBjG}HN`l$ z(V3ior87T+QMxLp?bFr>bNB=6SXH@u39(;+@=6|2;Cfa+6}?XUit-A5MBV@58Zk$%2o#@FI?a{|W}QUNF%g(J|pGiI14@e=gJw zHQ1`C6>|Zs_<&r6XQQ^{3w1~}vb%-jA#+?Hx3^JFY7sZrueq}UwSKHhQ1LJ)nfM?k zlACIj>Y+9E!C4?6er}UMybF`jLA>Ku(m}k_#{fV7D#P6Y)oO&A56EUMGz0l3viV

c5&+K<)%ZIa)$}%P2$-AU}~B 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�J&|bih09I_-S_VOclN=e&e>s4&bE4z1RTGd=0mn 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ðe);ne*Pq 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⪻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 literal 0 HcmV?d00001 diff --git a/html/sound.png b/html/sound.png new file mode 100644 index 0000000000000000000000000000000000000000..a21883d0c6d7d18b3f008fa0050bdf8f545130a1 GIT binary patch literal 1621 zcmY*Z2{hDO9RAxiLXjow7+b<@ij1+0ZS2iVh#c95F^@6R%wUqrR*s_%D%l3{6bhB4 z#p5Z_WJy`dc7&HKWlKVc_aF6o@7;6my}$e2@ArN8ch9*uh2VylgeXA(0FZQauqA=B z8o!H+f}!B`7igYk`iwIAnXQ$zlBieUXL3oH=9-$9_@NW?E~Fcr&3F-Muy zV9=SbZ-K(@F#m`B^uZ$d=Knd&k4kq?uv7~O7V+!aEFdn;y50aFOm(!yxjRVCWjcp) zJ@)aYa@w*Tdm6YhN}rk&=AIiEz$$%fQ>}-roL*n{-_z<&dun$l`+{@P9-Lm%^@#AS z_*)%4x@SwMavGtLngT=(Wf;*T<*d99+VHQQ(s&YzsWsL7PjnFAqT#d_3E0yI=?oNxX^s)y-B)W z0(yDkYkW8X@n~VJ_rBMxIs=~xUDkd>$N!cWYkaSSdzW{jBY-Wg+pkEsyAA7&BBP)| z9;zYV0grRGnRuC$7Rkx3qK7EUcCU%L_{=M4@2s{ho9Y6x`ELEPL7S31NOx%Mg%ln; zuygPtg8f8%&Cp<$;q2_ZFQ+EiU#wm1#HkDghG?V0H#jL%@BY$_TYhR!g$zk zwk0FFLTZLXKdZ#cl}5{wg^sg#-`iV%lrZksjhAySoy${@mtSVKj*GKs#`hS?xU>mj z-ee|hQFbOACkyLnkh-Hj(o__`tK<&MY1-z7r{lEWk(PCd&YRQ?S>=IQRO*$$e8E-4 zI@lns$9o`!B~Uk7Y%#Ow7ak@ZqukKb*LMvW-)5a7Ue@oxB5BPH=sb7V8}D0t@);L9 z-Lj>Y##<(gjxM<$_eD zHtdZIii}ip{Wx`Q=;2F+#6>}FBtfhs@$uwzod|8X{pzY_#Wr2(df(`6z)x=#*wX)= z?7e{t^A}Sc_HG=>HEQezdN}4%J>{0CmsYNRwmV2{T_+B7ArF}yh?k{AMwPGQotwusgUiQG9{iT; zG#XTqhy0}YSSU~EMH&t*Fe#ioj}00e?m80kRYC-bD_hr|nnHv{j}_2Sq;7`bq&M}tE^TD{Quk0&ds*U+CSlMNlUd> literal 0 HcmV?d00001 diff --git a/html/style.css b/html/style.css new file mode 100644 index 0000000..aa9e245 --- /dev/null +++ b/html/style.css @@ -0,0 +1,70 @@ +body { + background: #86c5da; +} + +canvas { + padding: 0px; +} + +h1 { + text-align: center; +} + +h2 { + text-align: center; +} + +h3 { + text-align: center; + overflow-wrap: break-word; +} + +img{ + padding-top: 15px; + margin-left: 200px; +} + +/* table, th, td{ + border: 1px solid black; +} */ + +.canvas { + background-image: url("rink.jpg"); + border: thin inset #aaaaaa; +} + +.player{ + align-items: center; + margin-left: 10; + font-family: Arial; +} + +/* .firstplayer{ +} + +.secondplayer{ +} */ + +.button{ + outline: none; + position: absolute; + /* position: relative; */ + margin: 5px; + -webkit-border-radius: 28; + -moz-border-radius: 28; + border-radius: 28px; + font-family: Arial; + color: #000000; + font-size: 20px; + background: #FFFFFF; + padding: 10px 20px 10px 20px; + border: solid #1f628d 2px; +} + +.joinbutton{ + right: 50%; +} + +.leavebutton{ + left: 50%; +} diff --git a/node_modules/accepts/HISTORY.md b/node_modules/accepts/HISTORY.md new file mode 100644 index 0000000..f16c17a --- /dev/null +++ b/node_modules/accepts/HISTORY.md @@ -0,0 +1,224 @@ +1.3.5 / 2018-02-28 +================== + + * deps: mime-types@~2.1.18 + - deps: mime-db@~1.33.0 + +1.3.4 / 2017-08-22 +================== + + * deps: mime-types@~2.1.16 + - deps: mime-db@~1.29.0 + +1.3.3 / 2016-05-02 +================== + + * deps: mime-types@~2.1.11 + - deps: mime-db@~1.23.0 + * deps: negotiator@0.6.1 + - perf: improve `Accept` parsing speed + - perf: improve `Accept-Charset` parsing speed + - perf: improve `Accept-Encoding` parsing speed + - perf: improve `Accept-Language` parsing speed + +1.3.2 / 2016-03-08 +================== + + * deps: mime-types@~2.1.10 + - Fix extension of `application/dash+xml` + - Update primary extension for `audio/mp4` + - deps: mime-db@~1.22.0 + +1.3.1 / 2016-01-19 +================== + + * deps: mime-types@~2.1.9 + - deps: mime-db@~1.21.0 + +1.3.0 / 2015-09-29 +================== + + * deps: mime-types@~2.1.7 + - deps: mime-db@~1.19.0 + * deps: negotiator@0.6.0 + - Fix including type extensions in parameters in `Accept` parsing + - Fix parsing `Accept` parameters with quoted equals + - Fix parsing `Accept` parameters with quoted semicolons + - Lazy-load modules from main entry point + - perf: delay type concatenation until needed + - perf: enable strict mode + - perf: hoist regular expressions + - perf: remove closures getting spec properties + - perf: remove a closure from media type parsing + - perf: remove property delete from media type parsing + +1.2.13 / 2015-09-06 +=================== + + * deps: mime-types@~2.1.6 + - deps: mime-db@~1.18.0 + +1.2.12 / 2015-07-30 +=================== + + * deps: mime-types@~2.1.4 + - deps: mime-db@~1.16.0 + +1.2.11 / 2015-07-16 +=================== + + * deps: mime-types@~2.1.3 + - deps: mime-db@~1.15.0 + +1.2.10 / 2015-07-01 +=================== + + * deps: mime-types@~2.1.2 + - deps: mime-db@~1.14.0 + +1.2.9 / 2015-06-08 +================== + + * deps: mime-types@~2.1.1 + - perf: fix deopt during mapping + +1.2.8 / 2015-06-07 +================== + + * deps: mime-types@~2.1.0 + - deps: mime-db@~1.13.0 + * perf: avoid argument reassignment & argument slice + * perf: avoid negotiator recursive construction + * perf: enable strict mode + * perf: remove unnecessary bitwise operator + +1.2.7 / 2015-05-10 +================== + + * deps: negotiator@0.5.3 + - Fix media type parameter matching to be case-insensitive + +1.2.6 / 2015-05-07 +================== + + * deps: mime-types@~2.0.11 + - deps: mime-db@~1.9.1 + * deps: negotiator@0.5.2 + - Fix comparing media types with quoted values + - Fix splitting media types with quoted commas + +1.2.5 / 2015-03-13 +================== + + * deps: mime-types@~2.0.10 + - deps: mime-db@~1.8.0 + +1.2.4 / 2015-02-14 +================== + + * Support Node.js 0.6 + * deps: mime-types@~2.0.9 + - deps: mime-db@~1.7.0 + * deps: negotiator@0.5.1 + - Fix preference sorting to be stable for long acceptable lists + +1.2.3 / 2015-01-31 +================== + + * deps: mime-types@~2.0.8 + - deps: mime-db@~1.6.0 + +1.2.2 / 2014-12-30 +================== + + * deps: mime-types@~2.0.7 + - deps: mime-db@~1.5.0 + +1.2.1 / 2014-12-30 +================== + + * deps: mime-types@~2.0.5 + - deps: mime-db@~1.3.1 + +1.2.0 / 2014-12-19 +================== + + * deps: negotiator@0.5.0 + - Fix list return order when large accepted list + - Fix missing identity encoding when q=0 exists + - Remove dynamic building of Negotiator class + +1.1.4 / 2014-12-10 +================== + + * deps: mime-types@~2.0.4 + - deps: mime-db@~1.3.0 + +1.1.3 / 2014-11-09 +================== + + * deps: mime-types@~2.0.3 + - deps: mime-db@~1.2.0 + +1.1.2 / 2014-10-14 +================== + + * deps: negotiator@0.4.9 + - Fix error when media type has invalid parameter + +1.1.1 / 2014-09-28 +================== + + * deps: mime-types@~2.0.2 + - deps: mime-db@~1.1.0 + * deps: negotiator@0.4.8 + - Fix all negotiations to be case-insensitive + - Stable sort preferences of same quality according to client order + +1.1.0 / 2014-09-02 +================== + + * update `mime-types` + +1.0.7 / 2014-07-04 +================== + + * Fix wrong type returned from `type` when match after unknown extension + +1.0.6 / 2014-06-24 +================== + + * deps: negotiator@0.4.7 + +1.0.5 / 2014-06-20 +================== + + * fix crash when unknown extension given + +1.0.4 / 2014-06-19 +================== + + * use `mime-types` + +1.0.3 / 2014-06-11 +================== + + * deps: negotiator@0.4.6 + - Order by specificity when quality is the same + +1.0.2 / 2014-05-29 +================== + + * Fix interpretation when header not in request + * deps: pin negotiator@0.4.5 + +1.0.1 / 2014-01-18 +================== + + * Identity encoding isn't always acceptable + * deps: negotiator@~0.4.0 + +1.0.0 / 2013-12-27 +================== + + * Genesis diff --git a/node_modules/accepts/LICENSE b/node_modules/accepts/LICENSE new file mode 100644 index 0000000..0616607 --- /dev/null +++ b/node_modules/accepts/LICENSE @@ -0,0 +1,23 @@ +(The MIT License) + +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2015 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/accepts/README.md b/node_modules/accepts/README.md new file mode 100644 index 0000000..6a2749a --- /dev/null +++ b/node_modules/accepts/README.md @@ -0,0 +1,143 @@ +# accepts + +[![NPM Version][npm-image]][npm-url] +[![NPM Downloads][downloads-image]][downloads-url] +[![Node.js Version][node-version-image]][node-version-url] +[![Build Status][travis-image]][travis-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +Higher level content negotiation based on [negotiator](https://www.npmjs.com/package/negotiator). +Extracted from [koa](https://www.npmjs.com/package/koa) for general use. + +In addition to negotiator, it allows: + +- Allows types as an array or arguments list, ie `(['text/html', 'application/json'])` + as well as `('text/html', 'application/json')`. +- Allows type shorthands such as `json`. +- Returns `false` when no types match +- Treats non-existent headers as `*` + +## Installation + +This is a [Node.js](https://nodejs.org/en/) module available through the +[npm registry](https://www.npmjs.com/). Installation is done using the +[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): + +```sh +$ npm install accepts +``` + +## API + + + +```js +var accepts = require('accepts') +``` + +### accepts(req) + +Create a new `Accepts` object for the given `req`. + +#### .charset(charsets) + +Return the first accepted charset. If nothing in `charsets` is accepted, +then `false` is returned. + +#### .charsets() + +Return the charsets that the request accepts, in the order of the client's +preference (most preferred first). + +#### .encoding(encodings) + +Return the first accepted encoding. If nothing in `encodings` is accepted, +then `false` is returned. + +#### .encodings() + +Return the encodings that the request accepts, in the order of the client's +preference (most preferred first). + +#### .language(languages) + +Return the first accepted language. If nothing in `languages` is accepted, +then `false` is returned. + +#### .languages() + +Return the languages that the request accepts, in the order of the client's +preference (most preferred first). + +#### .type(types) + +Return the first accepted type (and it is returned as the same text as what +appears in the `types` array). If nothing in `types` is accepted, then `false` +is returned. + +The `types` array can contain full MIME types or file extensions. Any value +that is not a full MIME types is passed to `require('mime-types').lookup`. + +#### .types() + +Return the types that the request accepts, in the order of the client's +preference (most preferred first). + +## Examples + +### Simple type negotiation + +This simple example shows how to use `accepts` to return a different typed +respond body based on what the client wants to accept. The server lists it's +preferences in order and will get back the best match between the client and +server. + +```js +var accepts = require('accepts') +var http = require('http') + +function app (req, res) { + var accept = accepts(req) + + // the order of this list is significant; should be server preferred order + switch (accept.type(['json', 'html'])) { + case 'json': + res.setHeader('Content-Type', 'application/json') + res.write('{"hello":"world!"}') + break + case 'html': + res.setHeader('Content-Type', 'text/html') + res.write('hello, world!') + break + default: + // the fallback is text/plain, so no need to specify it above + res.setHeader('Content-Type', 'text/plain') + res.write('hello, world!') + break + } + + res.end() +} + +http.createServer(app).listen(3000) +``` + +You can test this out with the cURL program: +```sh +curl -I -H'Accept: text/html' http://localhost:3000/ +``` + +## License + +[MIT](LICENSE) + +[npm-image]: https://img.shields.io/npm/v/accepts.svg +[npm-url]: https://npmjs.org/package/accepts +[node-version-image]: https://img.shields.io/node/v/accepts.svg +[node-version-url]: https://nodejs.org/en/download/ +[travis-image]: https://img.shields.io/travis/jshttp/accepts/master.svg +[travis-url]: https://travis-ci.org/jshttp/accepts +[coveralls-image]: https://img.shields.io/coveralls/jshttp/accepts/master.svg +[coveralls-url]: https://coveralls.io/r/jshttp/accepts +[downloads-image]: https://img.shields.io/npm/dm/accepts.svg +[downloads-url]: https://npmjs.org/package/accepts diff --git a/node_modules/accepts/index.js b/node_modules/accepts/index.js new file mode 100644 index 0000000..e9b2f63 --- /dev/null +++ b/node_modules/accepts/index.js @@ -0,0 +1,238 @@ +/*! + * accepts + * Copyright(c) 2014 Jonathan Ong + * Copyright(c) 2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module dependencies. + * @private + */ + +var Negotiator = require('negotiator') +var mime = require('mime-types') + +/** + * Module exports. + * @public + */ + +module.exports = Accepts + +/** + * Create a new Accepts object for the given req. + * + * @param {object} req + * @public + */ + +function Accepts (req) { + if (!(this instanceof Accepts)) { + return new Accepts(req) + } + + this.headers = req.headers + this.negotiator = new Negotiator(req) +} + +/** + * Check if the given `type(s)` is acceptable, returning + * the best match when true, otherwise `undefined`, in which + * case you should respond with 406 "Not Acceptable". + * + * The `type` value may be a single mime type string + * such as "application/json", the extension name + * such as "json" or an array `["json", "html", "text/plain"]`. When a list + * or array is given the _best_ match, if any is returned. + * + * Examples: + * + * // Accept: text/html + * this.types('html'); + * // => "html" + * + * // Accept: text/*, application/json + * this.types('html'); + * // => "html" + * this.types('text/html'); + * // => "text/html" + * this.types('json', 'text'); + * // => "json" + * this.types('application/json'); + * // => "application/json" + * + * // Accept: text/*, application/json + * this.types('image/png'); + * this.types('png'); + * // => undefined + * + * // Accept: text/*;q=.5, application/json + * this.types(['html', 'json']); + * this.types('html', 'json'); + * // => "json" + * + * @param {String|Array} types... + * @return {String|Array|Boolean} + * @public + */ + +Accepts.prototype.type = +Accepts.prototype.types = function (types_) { + var types = types_ + + // support flattened arguments + if (types && !Array.isArray(types)) { + types = new Array(arguments.length) + for (var i = 0; i < types.length; i++) { + types[i] = arguments[i] + } + } + + // no types, return all requested types + if (!types || types.length === 0) { + return this.negotiator.mediaTypes() + } + + // no accept header, return first given type + if (!this.headers.accept) { + return types[0] + } + + var mimes = types.map(extToMime) + var accepts = this.negotiator.mediaTypes(mimes.filter(validMime)) + var first = accepts[0] + + return first + ? types[mimes.indexOf(first)] + : false +} + +/** + * Return accepted encodings or best fit based on `encodings`. + * + * Given `Accept-Encoding: gzip, deflate` + * an array sorted by quality is returned: + * + * ['gzip', 'deflate'] + * + * @param {String|Array} encodings... + * @return {String|Array} + * @public + */ + +Accepts.prototype.encoding = +Accepts.prototype.encodings = function (encodings_) { + var encodings = encodings_ + + // support flattened arguments + if (encodings && !Array.isArray(encodings)) { + encodings = new Array(arguments.length) + for (var i = 0; i < encodings.length; i++) { + encodings[i] = arguments[i] + } + } + + // no encodings, return all requested encodings + if (!encodings || encodings.length === 0) { + return this.negotiator.encodings() + } + + return this.negotiator.encodings(encodings)[0] || false +} + +/** + * Return accepted charsets or best fit based on `charsets`. + * + * Given `Accept-Charset: utf-8, iso-8859-1;q=0.2, utf-7;q=0.5` + * an array sorted by quality is returned: + * + * ['utf-8', 'utf-7', 'iso-8859-1'] + * + * @param {String|Array} charsets... + * @return {String|Array} + * @public + */ + +Accepts.prototype.charset = +Accepts.prototype.charsets = function (charsets_) { + var charsets = charsets_ + + // support flattened arguments + if (charsets && !Array.isArray(charsets)) { + charsets = new Array(arguments.length) + for (var i = 0; i < charsets.length; i++) { + charsets[i] = arguments[i] + } + } + + // no charsets, return all requested charsets + if (!charsets || charsets.length === 0) { + return this.negotiator.charsets() + } + + return this.negotiator.charsets(charsets)[0] || false +} + +/** + * Return accepted languages or best fit based on `langs`. + * + * Given `Accept-Language: en;q=0.8, es, pt` + * an array sorted by quality is returned: + * + * ['es', 'pt', 'en'] + * + * @param {String|Array} langs... + * @return {Array|String} + * @public + */ + +Accepts.prototype.lang = +Accepts.prototype.langs = +Accepts.prototype.language = +Accepts.prototype.languages = function (languages_) { + var languages = languages_ + + // support flattened arguments + if (languages && !Array.isArray(languages)) { + languages = new Array(arguments.length) + for (var i = 0; i < languages.length; i++) { + languages[i] = arguments[i] + } + } + + // no languages, return all requested languages + if (!languages || languages.length === 0) { + return this.negotiator.languages() + } + + return this.negotiator.languages(languages)[0] || false +} + +/** + * Convert extnames to mime. + * + * @param {String} type + * @return {String} + * @private + */ + +function extToMime (type) { + return type.indexOf('/') === -1 + ? mime.lookup(type) + : type +} + +/** + * Check if mime is valid. + * + * @param {String} type + * @return {String} + * @private + */ + +function validMime (type) { + return typeof type === 'string' +} diff --git a/node_modules/accepts/package.json b/node_modules/accepts/package.json new file mode 100644 index 0000000..67ba512 --- /dev/null +++ b/node_modules/accepts/package.json @@ -0,0 +1,88 @@ +{ + "_args": [ + [ + "accepts@1.3.5", + "/Volumes/Clear Drive/Code/2406 Web Apps/Assignments/Assignment 3/project" + ] + ], + "_from": "accepts@1.3.5", + "_id": "accepts@1.3.5", + "_inBundle": false, + "_integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "_location": "/accepts", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "accepts@1.3.5", + "name": "accepts", + "escapedName": "accepts", + "rawSpec": "1.3.5", + "saveSpec": null, + "fetchSpec": "1.3.5" + }, + "_requiredBy": [ + "/engine.io" + ], + "_resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "_spec": "1.3.5", + "_where": "/Volumes/Clear Drive/Code/2406 Web Apps/Assignments/Assignment 3/project", + "bugs": { + "url": "https://github.com/jshttp/accepts/issues" + }, + "contributors": [ + { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + }, + { + "name": "Jonathan Ong", + "email": "me@jongleberry.com", + "url": "http://jongleberry.com" + } + ], + "dependencies": { + "mime-types": "~2.1.18", + "negotiator": "0.6.1" + }, + "description": "Higher-level content negotiation", + "devDependencies": { + "eslint": "4.18.1", + "eslint-config-standard": "11.0.0", + "eslint-plugin-import": "2.9.0", + "eslint-plugin-markdown": "1.0.0-beta.6", + "eslint-plugin-node": "6.0.1", + "eslint-plugin-promise": "3.6.0", + "eslint-plugin-standard": "3.0.1", + "istanbul": "0.4.5", + "mocha": "~1.21.5" + }, + "engines": { + "node": ">= 0.6" + }, + "files": [ + "LICENSE", + "HISTORY.md", + "index.js" + ], + "homepage": "https://github.com/jshttp/accepts#readme", + "keywords": [ + "content", + "negotiation", + "accept", + "accepts" + ], + "license": "MIT", + "name": "accepts", + "repository": { + "type": "git", + "url": "git+https://github.com/jshttp/accepts.git" + }, + "scripts": { + "lint": "eslint --plugin markdown --ext js,md .", + "test": "mocha --reporter spec --check-leaks --bail test/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", + "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/" + }, + "version": "1.3.5" +} diff --git a/node_modules/after/.npmignore b/node_modules/after/.npmignore new file mode 100644 index 0000000..6c78602 --- /dev/null +++ b/node_modules/after/.npmignore @@ -0,0 +1,2 @@ +node_modules +.monitor diff --git a/node_modules/after/.travis.yml b/node_modules/after/.travis.yml new file mode 100644 index 0000000..afd72d0 --- /dev/null +++ b/node_modules/after/.travis.yml @@ -0,0 +1,12 @@ +language: node_js +node_js: + - 0.6 + - 0.8 + - 0.9 + - 0.10 + - 0.12 + - 4.2.4 + - 5.4.1 + - iojs-1 + - iojs-2 + - iojs-3 diff --git a/node_modules/after/LICENCE b/node_modules/after/LICENCE new file mode 100644 index 0000000..7c35130 --- /dev/null +++ b/node_modules/after/LICENCE @@ -0,0 +1,19 @@ +Copyright (c) 2011 Raynos. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/node_modules/after/README.md b/node_modules/after/README.md new file mode 100644 index 0000000..fc69096 --- /dev/null +++ b/node_modules/after/README.md @@ -0,0 +1,115 @@ +# After [![Build Status][1]][2] + +Invoke callback after n calls + +## Status: production ready + +## Example + +```js +var after = require("after") +var db = require("./db") // some db. + +var updateUser = function (req, res) { + // use after to run two tasks in parallel, + // namely get request body and get session + // then run updateUser with the results + var next = after(2, updateUser) + var results = {} + + getJSONBody(req, res, function (err, body) { + if (err) return next(err) + + results.body = body + next(null, results) + }) + + getSessionUser(req, res, function (err, user) { + if (err) return next(err) + + results.user = user + next(null, results) + }) + + // now do the thing! + function updateUser(err, result) { + if (err) { + res.statusCode = 500 + return res.end("Unexpected Error") + } + + if (!result.user || result.user.role !== "admin") { + res.statusCode = 403 + return res.end("Permission Denied") + } + + db.put("users:" + req.params.userId, result.body, function (err) { + if (err) { + res.statusCode = 500 + return res.end("Unexpected Error") + } + + res.statusCode = 200 + res.end("Ok") + }) + } +} +``` + +## Naive Example + +```js +var after = require("after") + , next = after(3, logItWorks) + +next() +next() +next() // it works + +function logItWorks() { + console.log("it works!") +} +``` + +## Example with error handling + +```js +var after = require("after") + , next = after(3, logError) + +next() +next(new Error("oops")) // logs oops +next() // does nothing + +// This callback is only called once. +// If there is an error the callback gets called immediately +// this avoids the situation where errors get lost. +function logError(err) { + console.log(err) +} +``` + +## Installation + +`npm install after` + +## Tests + +`npm test` + +## Contributors + + - Raynos + - defunctzombie + +## MIT Licenced + + [1]: https://secure.travis-ci.org/Raynos/after.png + [2]: http://travis-ci.org/Raynos/after + [3]: http://raynos.org/blog/2/Flow-control-in-node.js + [4]: http://stackoverflow.com/questions/6852059/determining-the-end-of-asynchronous-operations-javascript/6852307#6852307 + [5]: http://stackoverflow.com/questions/6869872/in-javascript-what-are-best-practices-for-executing-multiple-asynchronous-functi/6870031#6870031 + [6]: http://stackoverflow.com/questions/6864397/javascript-performance-long-running-tasks/6889419#6889419 + [7]: http://stackoverflow.com/questions/6597493/synchronous-database-queries-with-node-js/6620091#6620091 + [8]: http://github.com/Raynos/iterators + [9]: http://github.com/Raynos/composite diff --git a/node_modules/after/index.js b/node_modules/after/index.js new file mode 100644 index 0000000..ec24879 --- /dev/null +++ b/node_modules/after/index.js @@ -0,0 +1,28 @@ +module.exports = after + +function after(count, callback, err_cb) { + var bail = false + err_cb = err_cb || noop + proxy.count = count + + return (count === 0) ? callback() : proxy + + function proxy(err, result) { + if (proxy.count <= 0) { + throw new Error('after called too many times') + } + --proxy.count + + // after first error, rest are passed to err_cb + if (err) { + bail = true + callback(err) + // future error callbacks will go to error handler + callback = err_cb + } else if (proxy.count === 0 && !bail) { + callback(null, result) + } + } +} + +function noop() {} diff --git a/node_modules/after/package.json b/node_modules/after/package.json new file mode 100644 index 0000000..ffa342a --- /dev/null +++ b/node_modules/after/package.json @@ -0,0 +1,66 @@ +{ + "_args": [ + [ + "after@0.8.2", + "/Volumes/Clear Drive/Code/2406 Web Apps/Assignments/Assignment 3/project" + ] + ], + "_from": "after@0.8.2", + "_id": "after@0.8.2", + "_inBundle": false, + "_integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", + "_location": "/after", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "after@0.8.2", + "name": "after", + "escapedName": "after", + "rawSpec": "0.8.2", + "saveSpec": null, + "fetchSpec": "0.8.2" + }, + "_requiredBy": [ + "/engine.io-parser" + ], + "_resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", + "_spec": "0.8.2", + "_where": "/Volumes/Clear Drive/Code/2406 Web Apps/Assignments/Assignment 3/project", + "author": { + "name": "Raynos", + "email": "raynos2@gmail.com" + }, + "bugs": { + "url": "https://github.com/Raynos/after/issues" + }, + "contributors": [ + { + "name": "Raynos", + "email": "raynos2@gmail.com", + "url": "http://raynos.org" + } + ], + "description": "after - tiny flow control", + "devDependencies": { + "mocha": "~1.8.1" + }, + "homepage": "https://github.com/Raynos/after#readme", + "keywords": [ + "flowcontrol", + "after", + "flow", + "control", + "arch" + ], + "license": "MIT", + "name": "after", + "repository": { + "type": "git", + "url": "git://github.com/Raynos/after.git" + }, + "scripts": { + "test": "mocha --ui tdd --reporter spec test/*.js" + }, + "version": "0.8.2" +} diff --git a/node_modules/after/test/after-test.js b/node_modules/after/test/after-test.js new file mode 100644 index 0000000..0d63f4c --- /dev/null +++ b/node_modules/after/test/after-test.js @@ -0,0 +1,120 @@ +/*global suite, test*/ + +var assert = require("assert") + , after = require("../") + +test("exists", function () { + assert(typeof after === "function", "after is not a function") +}) + +test("after when called with 0 invokes", function (done) { + after(0, done) +}); + +test("after 1", function (done) { + var next = after(1, done) + next() +}) + +test("after 5", function (done) { + var next = after(5, done) + , i = 5 + + while (i--) { + next() + } +}) + +test("manipulate count", function (done) { + var next = after(1, done) + , i = 5 + + next.count = i + while (i--) { + next() + } +}) + +test("after terminates on error", function (done) { + var next = after(2, function(err) { + assert.equal(err.message, 'test'); + done(); + }) + next(new Error('test')) + next(new Error('test2')) +}) + +test('gee', function(done) { + done = after(2, done) + + function cb(err) { + assert.equal(err.message, 1); + done() + } + + var next = after(3, cb, function(err) { + assert.equal(err.message, 2) + done() + }); + + next() + next(new Error(1)) + next(new Error(2)) +}) + +test('eee', function(done) { + done = after(3, done) + + function cb(err) { + assert.equal(err.message, 1); + done() + } + + var next = after(3, cb, function(err) { + assert.equal(err.message, 2) + done() + }); + + next(new Error(1)) + next(new Error(2)) + next(new Error(2)) +}) + +test('gge', function(done) { + function cb(err) { + assert.equal(err.message, 1); + done() + } + + var next = after(3, cb, function(err) { + // should not happen + assert.ok(false); + }); + + next() + next() + next(new Error(1)) +}) + +test('egg', function(done) { + function cb(err) { + assert.equal(err.message, 1); + done() + } + + var next = after(3, cb, function(err) { + // should not happen + assert.ok(false); + }); + + next(new Error(1)) + next() + next() +}) + +test('throws on too many calls', function(done) { + var next = after(1, done); + next() + assert.throws(next, /after called too many times/); +}); + diff --git a/node_modules/arraybuffer.slice/.npmignore b/node_modules/arraybuffer.slice/.npmignore new file mode 100644 index 0000000..cfbee8d --- /dev/null +++ b/node_modules/arraybuffer.slice/.npmignore @@ -0,0 +1,17 @@ +lib-cov +lcov.info +*.seed +*.log +*.csv +*.dat +*.out +*.pid +*.gz + +pids +logs +results +build +.grunt + +node_modules diff --git a/node_modules/arraybuffer.slice/LICENCE b/node_modules/arraybuffer.slice/LICENCE new file mode 100644 index 0000000..35fa375 --- /dev/null +++ b/node_modules/arraybuffer.slice/LICENCE @@ -0,0 +1,18 @@ +Copyright (C) 2013 Rase- + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/arraybuffer.slice/Makefile b/node_modules/arraybuffer.slice/Makefile new file mode 100644 index 0000000..849887f --- /dev/null +++ b/node_modules/arraybuffer.slice/Makefile @@ -0,0 +1,8 @@ + +REPORTER = dot + +test: + @./node_modules/.bin/mocha \ + --reporter $(REPORTER) + +.PHONY: test diff --git a/node_modules/arraybuffer.slice/README.md b/node_modules/arraybuffer.slice/README.md new file mode 100644 index 0000000..15e465e --- /dev/null +++ b/node_modules/arraybuffer.slice/README.md @@ -0,0 +1,17 @@ +# How to +```javascript +var sliceBuffer = require('arraybuffer.slice'); +var ab = (new Int8Array(5)).buffer; +var sliced = sliceBuffer(ab, 1, 3); +sliced = sliceBuffer(ab, 1); +``` + +# Licence (MIT) +Copyright (C) 2013 Rase- + + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/arraybuffer.slice/index.js b/node_modules/arraybuffer.slice/index.js new file mode 100644 index 0000000..11ac556 --- /dev/null +++ b/node_modules/arraybuffer.slice/index.js @@ -0,0 +1,29 @@ +/** + * An abstraction for slicing an arraybuffer even when + * ArrayBuffer.prototype.slice is not supported + * + * @api public + */ + +module.exports = function(arraybuffer, start, end) { + var bytes = arraybuffer.byteLength; + start = start || 0; + end = end || bytes; + + if (arraybuffer.slice) { return arraybuffer.slice(start, end); } + + if (start < 0) { start += bytes; } + if (end < 0) { end += bytes; } + if (end > bytes) { end = bytes; } + + if (start >= bytes || start >= end || bytes === 0) { + return new ArrayBuffer(0); + } + + var abv = new Uint8Array(arraybuffer); + var result = new Uint8Array(end - start); + for (var i = start, ii = 0; i < end; i++, ii++) { + result[ii] = abv[i]; + } + return result.buffer; +}; diff --git a/node_modules/arraybuffer.slice/package.json b/node_modules/arraybuffer.slice/package.json new file mode 100644 index 0000000..cfbd551 --- /dev/null +++ b/node_modules/arraybuffer.slice/package.json @@ -0,0 +1,47 @@ +{ + "_args": [ + [ + "arraybuffer.slice@0.0.7", + "/Volumes/Clear Drive/Code/2406 Web Apps/Assignments/Assignment 3/project" + ] + ], + "_from": "arraybuffer.slice@0.0.7", + "_id": "arraybuffer.slice@0.0.7", + "_inBundle": false, + "_integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", + "_location": "/arraybuffer.slice", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "arraybuffer.slice@0.0.7", + "name": "arraybuffer.slice", + "escapedName": "arraybuffer.slice", + "rawSpec": "0.0.7", + "saveSpec": null, + "fetchSpec": "0.0.7" + }, + "_requiredBy": [ + "/engine.io-parser" + ], + "_resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "_spec": "0.0.7", + "_where": "/Volumes/Clear Drive/Code/2406 Web Apps/Assignments/Assignment 3/project", + "bugs": { + "url": "https://github.com/rase-/arraybuffer.slice/issues" + }, + "dependencies": {}, + "description": "Exports a function for slicing ArrayBuffers (no polyfilling)", + "devDependencies": { + "expect.js": "0.2.0", + "mocha": "1.17.1" + }, + "homepage": "https://github.com/rase-/arraybuffer.slice", + "license": "MIT", + "name": "arraybuffer.slice", + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/rase-/arraybuffer.slice.git" + }, + "version": "0.0.7" +} diff --git a/node_modules/arraybuffer.slice/test/slice-buffer.js b/node_modules/arraybuffer.slice/test/slice-buffer.js new file mode 100644 index 0000000..4778da6 --- /dev/null +++ b/node_modules/arraybuffer.slice/test/slice-buffer.js @@ -0,0 +1,227 @@ +/* + * Test dependencies + */ + +var sliceBuffer = require('../index.js'); +var expect = require('expect.js'); + +/** + * Tests + */ + +describe('sliceBuffer', function() { + describe('using standard slice', function() { + it('should slice correctly with only start provided', function() { + var abv = new Uint8Array(10); + for (var i = 0; i < abv.length; i++) { + abv[i] = i; + } + + var sliced = sliceBuffer(abv.buffer, 3); + var sabv = new Uint8Array(sliced); + for (var i = 3, ii = 0; i < abv.length; i++, ii++) { + expect(abv[i]).to.equal(sabv[ii]); + } + }); + + it('should slice correctly with start and end provided', function() { + var abv = new Uint8Array(10); + for (var i = 0; i < abv.length; i++) { + abv[i] = i; + } + + var sliced = sliceBuffer(abv.buffer, 3, 8); + var sabv = new Uint8Array(sliced); + for (var i = 3, ii = 0; i < 8; i++, ii++) { + expect(abv[i]).to.equal(sabv[ii]); + } + }); + + it('should slice correctly with negative start', function() { + var abv = new Uint8Array(10); + for (var i = 0; i < abv.length; i++) { + abv[i] = i; + } + + var sliced = sliceBuffer(abv.buffer, -3); + var sabv = new Uint8Array(sliced); + for (var i = abv.length - 3, ii = 0; i < abv.length; i++, ii++) { + expect(abv[i]).to.equal(sabv[ii]); + } + }); + + it('should slice correctly with negative end', function() { + var abv = new Uint8Array(10); + for (var i = 0; i < abv.length; i++) { + abv[i] = i; + } + + var sliced = sliceBuffer(abv.buffer, 0, -3); + var sabv = new Uint8Array(sliced); + for (var i = 0, ii = 0; i < abv.length - 3; i++, ii++) { + expect(abv[i]).to.equal(sabv[ii]); + } + }); + + it('should slice correctly with negative start and end', function() { + var abv = new Uint8Array(10); + for (var i = 0; i < abv.length; i++) { + abv[i] = i; + } + + var sliced = sliceBuffer(abv.buffer, -6, -3); + var sabv = new Uint8Array(sliced); + for (var i = abv.length - 6, ii = 0; i < abv.length - 3; i++, ii++) { + expect(abv[i]).to.equal(sabv[ii]); + } + }); + + it('should slice correctly with equal start and end', function() { + var abv = new Uint8Array(10); + for (var i = 0; i < abv.length; i++) { + abv[i] = i; + } + + var sliced = sliceBuffer(abv.buffer, 1, 1); + expect(sliced.byteLength).to.equal(0); + }); + + it('should slice correctly when end larger than buffer', function() { + var abv = new Uint8Array(10); + for (var i = 0; i < abv.length; i++) { + abv[i] = i; + } + + var sliced = sliceBuffer(abv.buffer, 0, 100); + expect(new Uint8Array(sliced)).to.eql(abv); + }); + + it('shoud slice correctly when start larger than end', function() { + var abv = new Uint8Array(10); + for (var i = 0; i < abv.length; i++) { + abv[i] = i; + } + + var sliced = sliceBuffer(abv.buffer, 6, 5); + expect(sliced.byteLength).to.equal(0); + }); + }); + + describe('using fallback', function() { + it('should slice correctly with only start provided', function() { + var abv = new Uint8Array(10); + for (var i = 0; i < abv.length; i++) { + abv[i] = i; + } + var ab = abv.buffer; + ab.slice = undefined; + + var sliced = sliceBuffer(ab, 3); + var sabv = new Uint8Array(sliced); + for (var i = 3, ii = 0; i < abv.length; i++, ii++) { + expect(abv[i]).to.equal(sabv[ii]); + } + }); + + it('should slice correctly with start and end provided', function() { + var abv = new Uint8Array(10); + for (var i = 0; i < abv.length; i++) { + abv[i] = i; + } + var ab = abv.buffer; + ab.slice = undefined; + + + var sliced = sliceBuffer(ab, 3, 8); + var sabv = new Uint8Array(sliced); + for (var i = 3, ii = 0; i < 8; i++, ii++) { + expect(abv[i]).to.equal(sabv[ii]); + } + }); + + it('should slice correctly with negative start', function() { + var abv = new Uint8Array(10); + for (var i = 0; i < abv.length; i++) { + abv[i] = i; + } + var ab = abv.buffer; + ab.slice = undefined; + + + var sliced = sliceBuffer(ab, -3); + var sabv = new Uint8Array(sliced); + for (var i = abv.length - 3, ii = 0; i < abv.length; i++, ii++) { + expect(abv[i]).to.equal(sabv[ii]); + } + }); + + it('should slice correctly with negative end', function() { + var abv = new Uint8Array(10); + for (var i = 0; i < abv.length; i++) { + abv[i] = i; + } + var ab = abv.buffer; + ab.slice = undefined; + + var sliced = sliceBuffer(ab, 0, -3); + var sabv = new Uint8Array(sliced); + for (var i = 0, ii = 0; i < abv.length - 3; i++, ii++) { + expect(abv[i]).to.equal(sabv[ii]); + } + }); + + it('should slice correctly with negative start and end', function() { + var abv = new Uint8Array(10); + for (var i = 0; i < abv.length; i++) { + abv[i] = i; + } + var ab = abv.buffer; + ab.slice = undefined; + + var sliced = sliceBuffer(ab, -6, -3); + var sabv = new Uint8Array(sliced); + for (var i = abv.length - 6, ii = 0; i < abv.length - 3; i++, ii++) { + expect(abv[i]).to.equal(sabv[ii]); + } + }); + + it('should slice correctly with equal start and end', function() { + var abv = new Uint8Array(10); + for (var i = 0; i < abv.length; i++) { + abv[i] = i; + } + var ab = abv.buffer; + ab.slice = undefined; + + var sliced = sliceBuffer(ab, 1, 1); + expect(sliced.byteLength).to.equal(0); + }); + + it('should slice correctly when end larger than buffer', function() { + var abv = new Uint8Array(10); + for (var i = 0; i < abv.length; i++) { + abv[i] = i; + } + var ab = abv.buffer; + ab.slice = undefined; + + var sliced = sliceBuffer(ab, 0, 100); + var sabv = new Uint8Array(sliced); + for (var i = 0; i < abv.length; i++) { + expect(abv[i]).to.equal(sabv[i]); + } + }); + + it('shoud slice correctly when start larger than end', function() { + var abv = new Uint8Array(10); + for (var i = 0; i < abv.length; i++) { + abv[i] = i; + } + var ab = abv.buffer; + ab.slice = undefined; + + var sliced = sliceBuffer(ab, 6, 5); + expect(sliced.byteLength).to.equal(0); + }); + }); +}); diff --git a/node_modules/async-limiter/.travis.yml b/node_modules/async-limiter/.travis.yml new file mode 100644 index 0000000..6cf4a7a --- /dev/null +++ b/node_modules/async-limiter/.travis.yml @@ -0,0 +1,7 @@ +language: node_js +node_js: + - "6" + - "node" +script: npm run travis +cache: + yarn: true diff --git a/node_modules/async-limiter/LICENSE b/node_modules/async-limiter/LICENSE new file mode 100644 index 0000000..9c91fb2 --- /dev/null +++ b/node_modules/async-limiter/LICENSE @@ -0,0 +1,8 @@ +The MIT License (MIT) +Copyright (c) 2017 Samuel Reed + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/async-limiter/coverage/coverage.json b/node_modules/async-limiter/coverage/coverage.json new file mode 100644 index 0000000..5b4a358 --- /dev/null +++ b/node_modules/async-limiter/coverage/coverage.json @@ -0,0 +1 @@ +{"/Users/samuelreed/git/forks/async-throttle/index.js":{"path":"/Users/samuelreed/git/forks/async-throttle/index.js","s":{"1":1,"2":7,"3":1,"4":6,"5":6,"6":6,"7":6,"8":6,"9":6,"10":1,"11":1,"12":3,"13":13,"14":13,"15":13,"16":1,"17":19,"18":1,"19":45,"20":6,"21":39,"22":13,"23":13,"24":13,"25":13,"26":39,"27":18,"28":6,"29":6,"30":1,"31":6,"32":6,"33":6,"34":1,"35":13,"36":13,"37":1},"b":{"1":[1,6],"2":[6,5],"3":[6,5],"4":[6,39],"5":[13,26],"6":[18,21],"7":[6,0]},"f":{"1":7,"2":3,"3":13,"4":19,"5":45,"6":6,"7":13},"fnMap":{"1":{"name":"Queue","line":3,"loc":{"start":{"line":3,"column":0},"end":{"line":3,"column":24}}},"2":{"name":"(anonymous_2)","line":22,"loc":{"start":{"line":22,"column":24},"end":{"line":22,"column":41}}},"3":{"name":"(anonymous_3)","line":23,"loc":{"start":{"line":23,"column":28},"end":{"line":23,"column":39}}},"4":{"name":"(anonymous_4)","line":31,"loc":{"start":{"line":31,"column":7},"end":{"line":31,"column":18}}},"5":{"name":"(anonymous_5)","line":36,"loc":{"start":{"line":36,"column":23},"end":{"line":36,"column":34}}},"6":{"name":"(anonymous_6)","line":55,"loc":{"start":{"line":55,"column":25},"end":{"line":55,"column":38}}},"7":{"name":"done","line":62,"loc":{"start":{"line":62,"column":0},"end":{"line":62,"column":16}}}},"statementMap":{"1":{"start":{"line":3,"column":0},"end":{"line":14,"column":1}},"2":{"start":{"line":4,"column":2},"end":{"line":6,"column":3}},"3":{"start":{"line":5,"column":4},"end":{"line":5,"column":30}},"4":{"start":{"line":8,"column":2},"end":{"line":8,"column":26}},"5":{"start":{"line":9,"column":2},"end":{"line":9,"column":53}},"6":{"start":{"line":10,"column":2},"end":{"line":10,"column":19}},"7":{"start":{"line":11,"column":2},"end":{"line":11,"column":17}},"8":{"start":{"line":12,"column":2},"end":{"line":12,"column":16}},"9":{"start":{"line":13,"column":2},"end":{"line":13,"column":31}},"10":{"start":{"line":16,"column":0},"end":{"line":20,"column":2}},"11":{"start":{"line":22,"column":0},"end":{"line":28,"column":3}},"12":{"start":{"line":23,"column":2},"end":{"line":27,"column":4}},"13":{"start":{"line":24,"column":4},"end":{"line":24,"column":75}},"14":{"start":{"line":25,"column":4},"end":{"line":25,"column":16}},"15":{"start":{"line":26,"column":4},"end":{"line":26,"column":24}},"16":{"start":{"line":30,"column":0},"end":{"line":34,"column":3}},"17":{"start":{"line":32,"column":4},"end":{"line":32,"column":43}},"18":{"start":{"line":36,"column":0},"end":{"line":53,"column":2}},"19":{"start":{"line":37,"column":2},"end":{"line":39,"column":3}},"20":{"start":{"line":38,"column":4},"end":{"line":38,"column":11}},"21":{"start":{"line":40,"column":2},"end":{"line":45,"column":3}},"22":{"start":{"line":41,"column":4},"end":{"line":41,"column":32}},"23":{"start":{"line":42,"column":4},"end":{"line":42,"column":19}},"24":{"start":{"line":43,"column":4},"end":{"line":43,"column":20}},"25":{"start":{"line":44,"column":4},"end":{"line":44,"column":16}},"26":{"start":{"line":47,"column":2},"end":{"line":52,"column":3}},"27":{"start":{"line":48,"column":4},"end":{"line":51,"column":5}},"28":{"start":{"line":49,"column":6},"end":{"line":49,"column":30}},"29":{"start":{"line":50,"column":6},"end":{"line":50,"column":27}},"30":{"start":{"line":55,"column":0},"end":{"line":60,"column":2}},"31":{"start":{"line":56,"column":2},"end":{"line":59,"column":3}},"32":{"start":{"line":57,"column":4},"end":{"line":57,"column":22}},"33":{"start":{"line":58,"column":4},"end":{"line":58,"column":16}},"34":{"start":{"line":62,"column":0},"end":{"line":65,"column":1}},"35":{"start":{"line":63,"column":2},"end":{"line":63,"column":17}},"36":{"start":{"line":64,"column":2},"end":{"line":64,"column":14}},"37":{"start":{"line":67,"column":0},"end":{"line":67,"column":23}}},"branchMap":{"1":{"line":4,"type":"if","locations":[{"start":{"line":4,"column":2},"end":{"line":4,"column":2}},{"start":{"line":4,"column":2},"end":{"line":4,"column":2}}]},"2":{"line":8,"type":"binary-expr","locations":[{"start":{"line":8,"column":12},"end":{"line":8,"column":19}},{"start":{"line":8,"column":23},"end":{"line":8,"column":25}}]},"3":{"line":9,"type":"binary-expr","locations":[{"start":{"line":9,"column":21},"end":{"line":9,"column":40}},{"start":{"line":9,"column":44},"end":{"line":9,"column":52}}]},"4":{"line":37,"type":"if","locations":[{"start":{"line":37,"column":2},"end":{"line":37,"column":2}},{"start":{"line":37,"column":2},"end":{"line":37,"column":2}}]},"5":{"line":40,"type":"if","locations":[{"start":{"line":40,"column":2},"end":{"line":40,"column":2}},{"start":{"line":40,"column":2},"end":{"line":40,"column":2}}]},"6":{"line":47,"type":"if","locations":[{"start":{"line":47,"column":2},"end":{"line":47,"column":2}},{"start":{"line":47,"column":2},"end":{"line":47,"column":2}}]},"7":{"line":56,"type":"if","locations":[{"start":{"line":56,"column":2},"end":{"line":56,"column":2}},{"start":{"line":56,"column":2},"end":{"line":56,"column":2}}]}}}} \ No newline at end of file diff --git a/node_modules/async-limiter/coverage/lcov-report/async-throttle/index.html b/node_modules/async-limiter/coverage/lcov-report/async-throttle/index.html new file mode 100644 index 0000000..198882b --- /dev/null +++ b/node_modules/async-limiter/coverage/lcov-report/async-throttle/index.html @@ -0,0 +1,73 @@ + + + + Code coverage report for async-throttle/ + + + + + + +

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.js100%(37 / 37)92.86%(13 / 14)100%(7 / 7)100%(37 / 37)
+
+
+ + + + + + diff --git a/node_modules/async-limiter/coverage/lcov-report/async-throttle/index.js.html b/node_modules/async-limiter/coverage/lcov-report/async-throttle/index.js.html new file mode 100644 index 0000000..adc030f --- /dev/null +++ b/node_modules/async-limiter/coverage/lcov-report/async-throttle/index.js.html @@ -0,0 +1,246 @@ + + + + Code coverage report for async-throttle/index.js + + + + + + +
+

Code coverage report for async-throttle/index.js

+

+ Statements: 100% (37 / 37)      + Branches: 92.86% (13 / 14)      + Functions: 100% (7 / 7)      + Lines: 100% (37 / 37)      + Ignored: none      +

+
All files » async-throttle/ » index.js
+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68  +  +1 +7 +1 +  +  +6 +6 +6 +6 +6 +6 +  +  +1 +  +  +  +  +  +1 +3 +13 +13 +13 +  +  +  +1 +  +19 +  +  +  +1 +45 +6 +  +39 +13 +13 +13 +13 +  +  +39 +18 +6 +6 +  +  +  +  +1 +6 +6 +6 +  +  +  +1 +13 +13 +  +  +1 + 
'use strict';
+ 
+function Queue(options) {
+  if (!(this instanceof Queue)) {
+    return new Queue(options);
+  }
+ 
+  options = options || {};
+  this.concurrency = options.concurrency || Infinity;
+  this.pending = 0;
+  this.jobs = [];
+  this.cbs = [];
+  this._done = done.bind(this);
+}
+ 
+var arrayAddMethods = [
+  'push',
+  'unshift',
+  'splice'
+];
+ 
+arrayAddMethods.forEach(function(method) {
+  Queue.prototype[method] = function() {
+    var methodResult = Array.prototype[method].apply(this.jobs, arguments);
+    this._run();
+    return methodResult;
+  };
+});
+ 
+Object.defineProperty(Queue.prototype, 'length', {
+  get: function() {
+    return this.pending + this.jobs.length;
+  }
+});
+ 
+Queue.prototype._run = function() {
+  if (this.pending === this.concurrency) {
+    return;
+  }
+  if (this.jobs.length) {
+    var job = this.jobs.shift();
+    this.pending++;
+    job(this._done);
+    this._run();
+  }
+ 
+  if (this.pending === 0) {
+    while (this.cbs.length !== 0) {
+      var cb = this.cbs.pop();
+      process.nextTick(cb);
+    }
+  }
+};
+ 
+Queue.prototype.onDone = function(cb) {
+  Eif (typeof cb === 'function') {
+    this.cbs.push(cb);
+    this._run();
+  }
+};
+ 
+function done() {
+  this.pending--;
+  this._run();
+}
+ 
+module.exports = Queue;
+ 
+ +
+ + + + + + diff --git a/node_modules/async-limiter/coverage/lcov-report/base.css b/node_modules/async-limiter/coverage/lcov-report/base.css new file mode 100644 index 0000000..a6a2f32 --- /dev/null +++ b/node_modules/async-limiter/coverage/lcov-report/base.css @@ -0,0 +1,182 @@ +body, html { + margin:0; padding: 0; +} +body { + font-family: Helvetica Neue, Helvetica,Arial; + font-size: 10pt; +} +div.header, div.footer { + background: #eee; + padding: 1em; +} +div.header { + z-index: 100; + position: fixed; + top: 0; + border-bottom: 1px solid #666; + width: 100%; +} +div.footer { + border-top: 1px solid #666; +} +div.body { + margin-top: 10em; +} +div.meta { + font-size: 90%; + text-align: center; +} +h1, h2, h3 { + font-weight: normal; +} +h1 { + font-size: 12pt; +} +h2 { + font-size: 10pt; +} +pre { + font-family: Consolas, Menlo, Monaco, monospace; + margin: 0; + padding: 0; + line-height: 1.3; + font-size: 14px; + -moz-tab-size: 2; + -o-tab-size: 2; + tab-size: 2; +} + +div.path { font-size: 110%; } +div.path a:link, div.path a:visited { color: #000; } +table.coverage { border-collapse: collapse; margin:0; padding: 0 } + +table.coverage td { + margin: 0; + padding: 0; + color: #111; + vertical-align: top; +} +table.coverage td.line-count { + width: 50px; + text-align: right; + padding-right: 5px; +} +table.coverage td.line-coverage { + color: #777 !important; + text-align: right; + border-left: 1px solid #666; + border-right: 1px solid #666; +} + +table.coverage td.text { +} + +table.coverage td span.cline-any { + display: inline-block; + padding: 0 5px; + width: 40px; +} +table.coverage td span.cline-neutral { + background: #eee; +} +table.coverage td span.cline-yes { + background: #b5d592; + color: #999; +} +table.coverage td span.cline-no { + background: #fc8c84; +} + +.cstat-yes { color: #111; } +.cstat-no { background: #fc8c84; color: #111; } +.fstat-no { background: #ffc520; color: #111 !important; } +.cbranch-no { background: yellow !important; color: #111; } + +.cstat-skip { background: #ddd; color: #111; } +.fstat-skip { background: #ddd; color: #111 !important; } +.cbranch-skip { background: #ddd !important; color: #111; } + +.missing-if-branch { + display: inline-block; + margin-right: 10px; + position: relative; + padding: 0 4px; + background: black; + color: yellow; +} + +.skip-if-branch { + display: none; + margin-right: 10px; + position: relative; + padding: 0 4px; + background: #ccc; + color: white; +} + +.missing-if-branch .typ, .skip-if-branch .typ { + color: inherit !important; +} + +.entity, .metric { font-weight: bold; } +.metric { display: inline-block; border: 1px solid #333; padding: 0.3em; background: white; } +.metric small { font-size: 80%; font-weight: normal; color: #666; } + +div.coverage-summary table { border-collapse: collapse; margin: 3em; font-size: 110%; } +div.coverage-summary td, div.coverage-summary table th { margin: 0; padding: 0.25em 1em; border-top: 1px solid #666; border-bottom: 1px solid #666; } +div.coverage-summary th { text-align: left; border: 1px solid #666; background: #eee; font-weight: normal; } +div.coverage-summary th.file { border-right: none !important; } +div.coverage-summary th.pic { border-left: none !important; text-align: right; } +div.coverage-summary th.pct { border-right: none !important; } +div.coverage-summary th.abs { border-left: none !important; text-align: right; } +div.coverage-summary td.pct { text-align: right; border-left: 1px solid #666; } +div.coverage-summary td.abs { text-align: right; font-size: 90%; color: #444; border-right: 1px solid #666; } +div.coverage-summary td.file { border-left: 1px solid #666; white-space: nowrap; } +div.coverage-summary td.pic { min-width: 120px !important; } +div.coverage-summary a:link { text-decoration: none; color: #000; } +div.coverage-summary a:visited { text-decoration: none; color: #777; } +div.coverage-summary a:hover { text-decoration: underline; } +div.coverage-summary tfoot td { border-top: 1px solid #666; } + +div.coverage-summary .sorter { + height: 10px; + width: 7px; + display: inline-block; + margin-left: 0.5em; + background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent; +} +div.coverage-summary .sorted .sorter { + background-position: 0 -20px; +} +div.coverage-summary .sorted-desc .sorter { + background-position: 0 -10px; +} + +.high { background: #b5d592 !important; } +.medium { background: #ffe87c !important; } +.low { background: #fc8c84 !important; } + +span.cover-fill, span.cover-empty { + display:inline-block; + border:1px solid #444; + background: white; + height: 12px; +} +span.cover-fill { + background: #ccc; + border-right: 1px solid #444; +} +span.cover-empty { + background: white; + border-left: none; +} +span.cover-full { + border-right: none !important; +} +pre.prettyprint { + border: none !important; + padding: 0 !important; + margin: 0 !important; +} +.com { color: #999 !important; } +.ignore-none { color: #999; font-weight: normal; } diff --git a/node_modules/async-limiter/coverage/lcov-report/index.html b/node_modules/async-limiter/coverage/lcov-report/index.html new file mode 100644 index 0000000..782a1cf --- /dev/null +++ b/node_modules/async-limiter/coverage/lcov-report/index.html @@ -0,0 +1,73 @@ + + + + Code coverage report for All files + + + + + + +
+

Code coverage report for All files

+

+ Statements: 100% (37 / 37)      + Branches: 92.86% (13 / 14)      + Functions: 100% (7 / 7)      + Lines: 100% (37 / 37)      + Ignored: none      +

+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
async-throttle/100%(37 / 37)92.86%(13 / 14)100%(7 / 7)100%(37 / 37)
+
+
+ + + + + + diff --git a/node_modules/async-limiter/coverage/lcov-report/prettify.css b/node_modules/async-limiter/coverage/lcov-report/prettify.css new file mode 100644 index 0000000..b317a7c --- /dev/null +++ b/node_modules/async-limiter/coverage/lcov-report/prettify.css @@ -0,0 +1 @@ +.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} diff --git a/node_modules/async-limiter/coverage/lcov-report/prettify.js b/node_modules/async-limiter/coverage/lcov-report/prettify.js new file mode 100644 index 0000000..ef51e03 --- /dev/null +++ b/node_modules/async-limiter/coverage/lcov-report/prettify.js @@ -0,0 +1 @@ +window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;arat[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]); diff --git a/node_modules/async-limiter/coverage/lcov-report/sort-arrow-sprite.png b/node_modules/async-limiter/coverage/lcov-report/sort-arrow-sprite.png new file mode 100644 index 0000000000000000000000000000000000000000..03f704a609c6fd0dbfdac63466a7d7c958b5cbf3 GIT binary patch literal 209 zcmeAS@N?(olHy`uVBq!ia0vp^>_9Bd!3HEZxJ@+%Qj#UE5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS>Jii$m5978H@?Fn+^JD|Y9yzj{W`447Gxa{7*dM7nnnD-Lb z6^}Hx2)'; + } + } + return cols; + } + // attaches a data attribute to every tr element with an object + // of data values keyed by column name + function loadRowData(tableRow) { + var tableCols = tableRow.querySelectorAll('td'), + colNode, + col, + data = {}, + i, + val; + for (i = 0; i < tableCols.length; i += 1) { + colNode = tableCols[i]; + col = cols[i]; + val = colNode.getAttribute('data-value'); + if (col.type === 'number') { + val = Number(val); + } + data[col.key] = val; + } + return data; + } + // loads all row data + function loadData() { + var rows = getTableBody().querySelectorAll('tr'), + i; + + for (i = 0; i < rows.length; i += 1) { + rows[i].data = loadRowData(rows[i]); + } + } + // sorts the table using the data for the ith column + function sortByIndex(index, desc) { + var key = cols[index].key, + sorter = function (a, b) { + a = a.data[key]; + b = b.data[key]; + return a < b ? -1 : a > b ? 1 : 0; + }, + finalSorter = sorter, + tableBody = document.querySelector('.coverage-summary tbody'), + rowNodes = tableBody.querySelectorAll('tr'), + rows = [], + i; + + if (desc) { + finalSorter = function (a, b) { + return -1 * sorter(a, b); + }; + } + + for (i = 0; i < rowNodes.length; i += 1) { + rows.push(rowNodes[i]); + tableBody.removeChild(rowNodes[i]); + } + + rows.sort(finalSorter); + + for (i = 0; i < rows.length; i += 1) { + tableBody.appendChild(rows[i]); + } + } + // removes sort indicators for current column being sorted + function removeSortIndicators() { + var col = getNthColumn(currentSort.index), + cls = col.className; + + cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, ''); + col.className = cls; + } + // adds sort indicators for current column being sorted + function addSortIndicators() { + getNthColumn(currentSort.index).className += currentSort.desc ? ' sorted-desc' : ' sorted'; + } + // adds event listeners for all sorter widgets + function enableUI() { + var i, + el, + ithSorter = function ithSorter(i) { + var col = cols[i]; + + return function () { + var desc = col.defaultDescSort; + + if (currentSort.index === i) { + desc = !currentSort.desc; + } + sortByIndex(i, desc); + removeSortIndicators(); + currentSort.index = i; + currentSort.desc = desc; + addSortIndicators(); + }; + }; + for (i =0 ; i < cols.length; i += 1) { + if (cols[i].sortable) { + el = getNthColumn(i).querySelector('.sorter'); + if (el.addEventListener) { + el.addEventListener('click', ithSorter(i)); + } else { + el.attachEvent('onclick', ithSorter(i)); + } + } + } + } + // adds sorting functionality to the UI + return function () { + if (!getTable()) { + return; + } + cols = loadColumns(); + loadData(cols); + addSortIndicators(); + enableUI(); + }; +})(); + +window.addEventListener('load', addSorting); diff --git a/node_modules/async-limiter/coverage/lcov.info b/node_modules/async-limiter/coverage/lcov.info new file mode 100644 index 0000000..fbf36aa --- /dev/null +++ b/node_modules/async-limiter/coverage/lcov.info @@ -0,0 +1,74 @@ +TN: +SF:/Users/samuelreed/git/forks/async-throttle/index.js +FN:3,Queue +FN:22,(anonymous_2) +FN:23,(anonymous_3) +FN:31,(anonymous_4) +FN:36,(anonymous_5) +FN:55,(anonymous_6) +FN:62,done +FNF:7 +FNH:7 +FNDA:7,Queue +FNDA:3,(anonymous_2) +FNDA:13,(anonymous_3) +FNDA:19,(anonymous_4) +FNDA:45,(anonymous_5) +FNDA:6,(anonymous_6) +FNDA:13,done +DA:3,1 +DA:4,7 +DA:5,1 +DA:8,6 +DA:9,6 +DA:10,6 +DA:11,6 +DA:12,6 +DA:13,6 +DA:16,1 +DA:22,1 +DA:23,3 +DA:24,13 +DA:25,13 +DA:26,13 +DA:30,1 +DA:32,19 +DA:36,1 +DA:37,45 +DA:38,6 +DA:40,39 +DA:41,13 +DA:42,13 +DA:43,13 +DA:44,13 +DA:47,39 +DA:48,18 +DA:49,6 +DA:50,6 +DA:55,1 +DA:56,6 +DA:57,6 +DA:58,6 +DA:62,1 +DA:63,13 +DA:64,13 +DA:67,1 +LF:37 +LH:37 +BRDA:4,1,0,1 +BRDA:4,1,1,6 +BRDA:8,2,0,6 +BRDA:8,2,1,5 +BRDA:9,3,0,6 +BRDA:9,3,1,5 +BRDA:37,4,0,6 +BRDA:37,4,1,39 +BRDA:40,5,0,13 +BRDA:40,5,1,26 +BRDA:47,6,0,18 +BRDA:47,6,1,21 +BRDA:56,7,0,6 +BRDA:56,7,1,0 +BRF:14 +BRH:13 +end_of_record diff --git a/node_modules/async-limiter/index.js b/node_modules/async-limiter/index.js new file mode 100644 index 0000000..c9bd2f9 --- /dev/null +++ b/node_modules/async-limiter/index.js @@ -0,0 +1,67 @@ +'use strict'; + +function Queue(options) { + if (!(this instanceof Queue)) { + return new Queue(options); + } + + options = options || {}; + this.concurrency = options.concurrency || Infinity; + this.pending = 0; + this.jobs = []; + this.cbs = []; + this._done = done.bind(this); +} + +var arrayAddMethods = [ + 'push', + 'unshift', + 'splice' +]; + +arrayAddMethods.forEach(function(method) { + Queue.prototype[method] = function() { + var methodResult = Array.prototype[method].apply(this.jobs, arguments); + this._run(); + return methodResult; + }; +}); + +Object.defineProperty(Queue.prototype, 'length', { + get: function() { + return this.pending + this.jobs.length; + } +}); + +Queue.prototype._run = function() { + if (this.pending === this.concurrency) { + return; + } + if (this.jobs.length) { + var job = this.jobs.shift(); + this.pending++; + job(this._done); + this._run(); + } + + if (this.pending === 0) { + while (this.cbs.length !== 0) { + var cb = this.cbs.pop(); + process.nextTick(cb); + } + } +}; + +Queue.prototype.onDone = function(cb) { + if (typeof cb === 'function') { + this.cbs.push(cb); + this._run(); + } +}; + +function done() { + this.pending--; + this._run(); +} + +module.exports = Queue; diff --git a/node_modules/async-limiter/package.json b/node_modules/async-limiter/package.json new file mode 100644 index 0000000..6542f8f --- /dev/null +++ b/node_modules/async-limiter/package.json @@ -0,0 +1,72 @@ +{ + "_args": [ + [ + "async-limiter@1.0.0", + "/Volumes/Clear Drive/Code/2406 Web Apps/Assignments/Assignment 3/project" + ] + ], + "_from": "async-limiter@1.0.0", + "_id": "async-limiter@1.0.0", + "_inBundle": false, + "_integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", + "_location": "/async-limiter", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "async-limiter@1.0.0", + "name": "async-limiter", + "escapedName": "async-limiter", + "rawSpec": "1.0.0", + "saveSpec": null, + "fetchSpec": "1.0.0" + }, + "_requiredBy": [ + "/ws" + ], + "_resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "_spec": "1.0.0", + "_where": "/Volumes/Clear Drive/Code/2406 Web Apps/Assignments/Assignment 3/project", + "author": { + "name": "Samuel Reed" + }, + "bugs": { + "url": "https://github.com/strml/async-limiter/issues" + }, + "dependencies": {}, + "description": "asynchronous function queue with adjustable concurrency", + "devDependencies": { + "coveralls": "^2.11.2", + "eslint": "^4.6.1", + "eslint-plugin-mocha": "^4.11.0", + "intelli-espower-loader": "^1.0.1", + "istanbul": "^0.3.2", + "mocha": "^3.5.2", + "power-assert": "^1.4.4" + }, + "homepage": "https://github.com/strml/async-limiter#readme", + "keywords": [ + "throttle", + "async", + "limiter", + "asynchronous", + "job", + "task", + "concurrency", + "concurrent" + ], + "license": "MIT", + "name": "async-limiter", + "repository": { + "type": "git", + "url": "git+https://github.com/strml/async-limiter.git" + }, + "scripts": { + "coverage": "istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | coveralls", + "example": "node example", + "lint": "eslint .", + "test": "mocha --R intelli-espower-loader test/", + "travis": "npm run lint && npm run coverage" + }, + "version": "1.0.0" +} diff --git a/node_modules/async-limiter/readme.md b/node_modules/async-limiter/readme.md new file mode 100644 index 0000000..dcf4932 --- /dev/null +++ b/node_modules/async-limiter/readme.md @@ -0,0 +1,132 @@ +# Async-Limiter + +A module for limiting concurrent asynchronous actions in flight. Forked from [queue](https://github.com/jessetane/queue). + +[![npm](http://img.shields.io/npm/v/async-limiter.svg?style=flat-square)](http://www.npmjs.org/async-limiter) +[![tests](https://img.shields.io/travis/STRML/async-limiter.svg?style=flat-square&branch=master)](https://travis-ci.org/STRML/async-limiter) +[![coverage](https://img.shields.io/coveralls/STRML/async-limiter.svg?style=flat-square&branch=master)](https://coveralls.io/r/STRML/async-limiter) + +This module exports a class `Limiter` that implements some of the `Array` API. +Pass async functions (ones that accept a callback or return a promise) to an instance's additive array methods. + +## Motivation + +Certain functions, like `zlib`, have [undesirable behavior](https://github.com/nodejs/node/issues/8871#issuecomment-250915913) when +run at infinite concurrency. + +In this case, it is actually faster, and takes far less memory, to limit concurrency. + +This module should do the absolute minimum work necessary to queue up functions. PRs are welcome that would +make this module faster or lighter, but new functionality is not desired. + +Style should confirm to nodejs/node style. + +## Example + +``` javascript +var Limiter = require('async-limiter') + +var t = new Limiter({concurrency: 2}); +var results = [] + +// add jobs using the familiar Array API +t.push(function (cb) { + results.push('two') + cb() +}) + +t.push( + function (cb) { + results.push('four') + cb() + }, + function (cb) { + results.push('five') + cb() + } +) + +t.unshift(function (cb) { + results.push('one') + cb() +}) + +t.splice(2, 0, function (cb) { + results.push('three') + cb() +}) + +// Jobs run automatically. If you want a callback when all are done, +// call 'onDone()'. +t.onDone(function () { + console.log('all done:', results) +}) +``` + +## Zlib Example + +```js +const zlib = require('zlib'); +const Limiter = require('async-limiter'); + +const message = {some: "data"}; +const payload = new Buffer(JSON.stringify(message)); + +// Try with different concurrency values to see how this actually +// slows significantly with higher concurrency! +// +// 5: 1398.607ms +// 10: 1375.668ms +// Infinity: 4423.300ms +// +const t = new Limiter({concurrency: 5}); +function deflate(payload, cb) { + t.push(function(done) { + zlib.deflate(payload, function(err, buffer) { + done(); + cb(err, buffer); + }); + }); +} + +console.time('deflate'); +for(let i = 0; i < 30000; ++i) { + deflate(payload, function (err, buffer) {}); +} +q.onDone(function() { + console.timeEnd('deflate'); +}); +``` + +## Install + +`npm install async-limiter` + +## Test + +`npm test` + +## API + +### `var t = new Limiter([opts])` +Constructor. `opts` may contain inital values for: +* `q.concurrency` + +## Instance methods + +### `q.onDone(fn)` +`fn` will be called once and only once, when the queue is empty. + +## Instance methods mixed in from `Array` +Mozilla has docs on how these methods work [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array). +### `q.push(element1, ..., elementN)` +### `q.unshift(element1, ..., elementN)` +### `q.splice(index , howMany[, element1[, ...[, elementN]]])` + +## Properties +### `q.concurrency` +Max number of jobs the queue should process concurrently, defaults to `Infinity`. + +### `q.length` +Jobs pending + jobs to process (readonly). + diff --git a/node_modules/backo2/.npmignore b/node_modules/backo2/.npmignore new file mode 100644 index 0000000..c2658d7 --- /dev/null +++ b/node_modules/backo2/.npmignore @@ -0,0 +1 @@ +node_modules/ diff --git a/node_modules/backo2/History.md b/node_modules/backo2/History.md new file mode 100644 index 0000000..8eb28b8 --- /dev/null +++ b/node_modules/backo2/History.md @@ -0,0 +1,12 @@ + +1.0.1 / 2014-02-17 +================== + + * go away decimal point + * history + +1.0.0 / 2014-02-17 +================== + + * add jitter option + * Initial commit diff --git a/node_modules/backo2/Makefile b/node_modules/backo2/Makefile new file mode 100644 index 0000000..9987df8 --- /dev/null +++ b/node_modules/backo2/Makefile @@ -0,0 +1,8 @@ + +test: + @./node_modules/.bin/mocha \ + --require should \ + --reporter dot \ + --bail + +.PHONY: test \ No newline at end of file diff --git a/node_modules/backo2/Readme.md b/node_modules/backo2/Readme.md new file mode 100644 index 0000000..0df2a39 --- /dev/null +++ b/node_modules/backo2/Readme.md @@ -0,0 +1,34 @@ +# backo + + Simple exponential backoff because the others seem to have weird abstractions. + +## Installation + +``` +$ npm install backo +``` + +## Options + + - `min` initial timeout in milliseconds [100] + - `max` max timeout [10000] + - `jitter` [0] + - `factor` [2] + +## Example + +```js +var Backoff = require('backo'); +var backoff = new Backoff({ min: 100, max: 20000 }); + +setTimeout(function(){ + something.reconnect(); +}, backoff.duration()); + +// later when something works +backoff.reset() +``` + +# License + + MIT diff --git a/node_modules/backo2/component.json b/node_modules/backo2/component.json new file mode 100644 index 0000000..994845a --- /dev/null +++ b/node_modules/backo2/component.json @@ -0,0 +1,11 @@ +{ + "name": "backo", + "repo": "segmentio/backo", + "dependencies": {}, + "version": "1.0.1", + "description": "simple backoff without the weird abstractions", + "keywords": ["backoff"], + "license": "MIT", + "scripts": ["index.js"], + "main": "index.js" +} diff --git a/node_modules/backo2/index.js b/node_modules/backo2/index.js new file mode 100644 index 0000000..fac4429 --- /dev/null +++ b/node_modules/backo2/index.js @@ -0,0 +1,85 @@ + +/** + * Expose `Backoff`. + */ + +module.exports = Backoff; + +/** + * Initialize backoff timer with `opts`. + * + * - `min` initial timeout in milliseconds [100] + * - `max` max timeout [10000] + * - `jitter` [0] + * - `factor` [2] + * + * @param {Object} opts + * @api public + */ + +function Backoff(opts) { + opts = opts || {}; + this.ms = opts.min || 100; + this.max = opts.max || 10000; + this.factor = opts.factor || 2; + this.jitter = opts.jitter > 0 && opts.jitter <= 1 ? opts.jitter : 0; + this.attempts = 0; +} + +/** + * Return the backoff duration. + * + * @return {Number} + * @api public + */ + +Backoff.prototype.duration = function(){ + var ms = this.ms * Math.pow(this.factor, this.attempts++); + if (this.jitter) { + var rand = Math.random(); + var deviation = Math.floor(rand * this.jitter * ms); + ms = (Math.floor(rand * 10) & 1) == 0 ? ms - deviation : ms + deviation; + } + return Math.min(ms, this.max) | 0; +}; + +/** + * Reset the number of attempts. + * + * @api public + */ + +Backoff.prototype.reset = function(){ + this.attempts = 0; +}; + +/** + * Set the minimum duration + * + * @api public + */ + +Backoff.prototype.setMin = function(min){ + this.ms = min; +}; + +/** + * Set the maximum duration + * + * @api public + */ + +Backoff.prototype.setMax = function(max){ + this.max = max; +}; + +/** + * Set the jitter + * + * @api public + */ + +Backoff.prototype.setJitter = function(jitter){ + this.jitter = jitter; +}; + diff --git a/node_modules/backo2/package.json b/node_modules/backo2/package.json new file mode 100644 index 0000000..9da1f35 --- /dev/null +++ b/node_modules/backo2/package.json @@ -0,0 +1,50 @@ +{ + "_args": [ + [ + "backo2@1.0.2", + "/Volumes/Clear Drive/Code/2406 Web Apps/Assignments/Assignment 3/project" + ] + ], + "_from": "backo2@1.0.2", + "_id": "backo2@1.0.2", + "_inBundle": false, + "_integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", + "_location": "/backo2", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "backo2@1.0.2", + "name": "backo2", + "escapedName": "backo2", + "rawSpec": "1.0.2", + "saveSpec": null, + "fetchSpec": "1.0.2" + }, + "_requiredBy": [ + "/socket.io-client" + ], + "_resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "_spec": "1.0.2", + "_where": "/Volumes/Clear Drive/Code/2406 Web Apps/Assignments/Assignment 3/project", + "bugs": { + "url": "https://github.com/mokesmokes/backo/issues" + }, + "dependencies": {}, + "description": "simple backoff based on segmentio/backo", + "devDependencies": { + "mocha": "*", + "should": "*" + }, + "homepage": "https://github.com/mokesmokes/backo#readme", + "keywords": [ + "backoff" + ], + "license": "MIT", + "name": "backo2", + "repository": { + "type": "git", + "url": "git+https://github.com/mokesmokes/backo.git" + }, + "version": "1.0.2" +} diff --git a/node_modules/backo2/test/index.js b/node_modules/backo2/test/index.js new file mode 100644 index 0000000..ea1f6de --- /dev/null +++ b/node_modules/backo2/test/index.js @@ -0,0 +1,18 @@ + +var Backoff = require('..'); +var assert = require('assert'); + +describe('.duration()', function(){ + it('should increase the backoff', function(){ + var b = new Backoff; + + assert(100 == b.duration()); + assert(200 == b.duration()); + assert(400 == b.duration()); + assert(800 == b.duration()); + + b.reset(); + assert(100 == b.duration()); + assert(200 == b.duration()); + }) +}) \ No newline at end of file diff --git a/node_modules/base64-arraybuffer/.npmignore b/node_modules/base64-arraybuffer/.npmignore new file mode 100644 index 0000000..332ee5a --- /dev/null +++ b/node_modules/base64-arraybuffer/.npmignore @@ -0,0 +1,3 @@ +/node_modules/ +Gruntfile.js +/test/ diff --git a/node_modules/base64-arraybuffer/.travis.yml b/node_modules/base64-arraybuffer/.travis.yml new file mode 100644 index 0000000..19259a5 --- /dev/null +++ b/node_modules/base64-arraybuffer/.travis.yml @@ -0,0 +1,19 @@ +language: node_js +node_js: +- '0.12' +- iojs-1 +- iojs-2 +- iojs-3 +- '4.1' +before_script: +- npm install +before_install: npm install -g npm@'>=2.13.5' +deploy: + provider: npm + email: niklasvh@gmail.com + api_key: + secure: oHV9ArprTj5WOk7MP1UF7QMJ70huXw+y7xXb5wF4+V2H8Hyfa5TfE0DiOmqrube1WXTeH1FLgq54shp/sJWi47Hkg/GyeoB5NnsPhYEaJkaON9UG5blML+ODiNVsEnq/1kNBQ8e0+0JItMPLGySKyFmuZ3yflulXKS8O88mfINo= + on: + tags: true + branch: master + repo: niklasvh/base64-arraybuffer diff --git a/node_modules/base64-arraybuffer/LICENSE-MIT b/node_modules/base64-arraybuffer/LICENSE-MIT new file mode 100644 index 0000000..ed27b41 --- /dev/null +++ b/node_modules/base64-arraybuffer/LICENSE-MIT @@ -0,0 +1,22 @@ +Copyright (c) 2012 Niklas von Hertzen + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/base64-arraybuffer/README.md b/node_modules/base64-arraybuffer/README.md new file mode 100644 index 0000000..50009e4 --- /dev/null +++ b/node_modules/base64-arraybuffer/README.md @@ -0,0 +1,20 @@ +# base64-arraybuffer + +[![Build Status](https://travis-ci.org/niklasvh/base64-arraybuffer.png)](https://travis-ci.org/niklasvh/base64-arraybuffer) +[![NPM Downloads](https://img.shields.io/npm/dm/base64-arraybuffer.svg)](https://www.npmjs.org/package/base64-arraybuffer) +[![NPM Version](https://img.shields.io/npm/v/base64-arraybuffer.svg)](https://www.npmjs.org/package/base64-arraybuffer) + +Encode/decode base64 data into ArrayBuffers + +## Getting Started +Install the module with: `npm install base64-arraybuffer` + +## API +The library encodes and decodes base64 to and from ArrayBuffers + + - __encode(buffer)__ - Encodes `ArrayBuffer` into base64 string + - __decode(str)__ - Decodes base64 string to `ArrayBuffer` + +## License +Copyright (c) 2012 Niklas von Hertzen +Licensed under the MIT license. diff --git a/node_modules/base64-arraybuffer/lib/base64-arraybuffer.js b/node_modules/base64-arraybuffer/lib/base64-arraybuffer.js new file mode 100644 index 0000000..e6b6306 --- /dev/null +++ b/node_modules/base64-arraybuffer/lib/base64-arraybuffer.js @@ -0,0 +1,67 @@ +/* + * base64-arraybuffer + * https://github.com/niklasvh/base64-arraybuffer + * + * Copyright (c) 2012 Niklas von Hertzen + * Licensed under the MIT license. + */ +(function(){ + "use strict"; + + var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + // Use a lookup table to find the index. + var lookup = new Uint8Array(256); + for (var i = 0; i < chars.length; i++) { + lookup[chars.charCodeAt(i)] = i; + } + + exports.encode = function(arraybuffer) { + var bytes = new Uint8Array(arraybuffer), + i, len = bytes.length, base64 = ""; + + for (i = 0; i < len; i+=3) { + base64 += chars[bytes[i] >> 2]; + base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)]; + base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)]; + base64 += chars[bytes[i + 2] & 63]; + } + + if ((len % 3) === 2) { + base64 = base64.substring(0, base64.length - 1) + "="; + } else if (len % 3 === 1) { + base64 = base64.substring(0, base64.length - 2) + "=="; + } + + return base64; + }; + + exports.decode = function(base64) { + var bufferLength = base64.length * 0.75, + len = base64.length, i, p = 0, + encoded1, encoded2, encoded3, encoded4; + + if (base64[base64.length - 1] === "=") { + bufferLength--; + if (base64[base64.length - 2] === "=") { + bufferLength--; + } + } + + var arraybuffer = new ArrayBuffer(bufferLength), + bytes = new Uint8Array(arraybuffer); + + for (i = 0; i < len; i+=4) { + encoded1 = lookup[base64.charCodeAt(i)]; + encoded2 = lookup[base64.charCodeAt(i+1)]; + encoded3 = lookup[base64.charCodeAt(i+2)]; + encoded4 = lookup[base64.charCodeAt(i+3)]; + + bytes[p++] = (encoded1 << 2) | (encoded2 >> 4); + bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2); + bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63); + } + + return arraybuffer; + }; +})(); diff --git a/node_modules/base64-arraybuffer/package.json b/node_modules/base64-arraybuffer/package.json new file mode 100644 index 0000000..bca9400 --- /dev/null +++ b/node_modules/base64-arraybuffer/package.json @@ -0,0 +1,68 @@ +{ + "_args": [ + [ + "base64-arraybuffer@0.1.5", + "/Volumes/Clear Drive/Code/2406 Web Apps/Assignments/Assignment 3/project" + ] + ], + "_from": "base64-arraybuffer@0.1.5", + "_id": "base64-arraybuffer@0.1.5", + "_inBundle": false, + "_integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", + "_location": "/base64-arraybuffer", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "base64-arraybuffer@0.1.5", + "name": "base64-arraybuffer", + "escapedName": "base64-arraybuffer", + "rawSpec": "0.1.5", + "saveSpec": null, + "fetchSpec": "0.1.5" + }, + "_requiredBy": [ + "/engine.io-parser", + "/socket.io-client" + ], + "_resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "_spec": "0.1.5", + "_where": "/Volumes/Clear Drive/Code/2406 Web Apps/Assignments/Assignment 3/project", + "author": { + "name": "Niklas von Hertzen", + "email": "niklasvh@gmail.com", + "url": "http://hertzen.com" + }, + "bugs": { + "url": "https://github.com/niklasvh/base64-arraybuffer/issues" + }, + "description": "Encode/decode base64 data into ArrayBuffers", + "devDependencies": { + "grunt": "^0.4.5", + "grunt-cli": "^0.1.13", + "grunt-contrib-jshint": "^0.11.2", + "grunt-contrib-nodeunit": "^0.4.1", + "grunt-contrib-watch": "^0.6.1" + }, + "engines": { + "node": ">= 0.6.0" + }, + "homepage": "https://github.com/niklasvh/base64-arraybuffer", + "keywords": [], + "licenses": [ + { + "type": "MIT", + "url": "https://github.com/niklasvh/base64-arraybuffer/blob/master/LICENSE-MIT" + } + ], + "main": "lib/base64-arraybuffer", + "name": "base64-arraybuffer", + "repository": { + "type": "git", + "url": "git+https://github.com/niklasvh/base64-arraybuffer.git" + }, + "scripts": { + "test": "grunt nodeunit" + }, + "version": "0.1.5" +} diff --git a/node_modules/base64id/.npmignore b/node_modules/base64id/.npmignore new file mode 100644 index 0000000..39e9864 --- /dev/null +++ b/node_modules/base64id/.npmignore @@ -0,0 +1,3 @@ +support +test +examples diff --git a/node_modules/base64id/LICENSE b/node_modules/base64id/LICENSE new file mode 100644 index 0000000..0d03c83 --- /dev/null +++ b/node_modules/base64id/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2012-2016 Kristian Faeldt + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/base64id/README.md b/node_modules/base64id/README.md new file mode 100644 index 0000000..17689e6 --- /dev/null +++ b/node_modules/base64id/README.md @@ -0,0 +1,18 @@ +base64id +======== + +Node.js module that generates a base64 id. + +Uses crypto.randomBytes when available, falls back to unsafe methods for node.js <= 0.4. + +To increase performance, random bytes are buffered to minimize the number of synchronous calls to crypto.randomBytes. + +## Installation + + $ npm install base64id + +## Usage + + var base64id = require('base64id'); + + var id = base64id.generateId(); diff --git a/node_modules/base64id/lib/base64id.js b/node_modules/base64id/lib/base64id.js new file mode 100644 index 0000000..f688159 --- /dev/null +++ b/node_modules/base64id/lib/base64id.js @@ -0,0 +1,103 @@ +/*! + * base64id v0.1.0 + */ + +/** + * Module dependencies + */ + +var crypto = require('crypto'); + +/** + * Constructor + */ + +var Base64Id = function() { }; + +/** + * Get random bytes + * + * Uses a buffer if available, falls back to crypto.randomBytes + */ + +Base64Id.prototype.getRandomBytes = function(bytes) { + + var BUFFER_SIZE = 4096 + var self = this; + + bytes = bytes || 12; + + if (bytes > BUFFER_SIZE) { + return crypto.randomBytes(bytes); + } + + var bytesInBuffer = parseInt(BUFFER_SIZE/bytes); + var threshold = parseInt(bytesInBuffer*0.85); + + if (!threshold) { + return crypto.randomBytes(bytes); + } + + if (this.bytesBufferIndex == null) { + this.bytesBufferIndex = -1; + } + + if (this.bytesBufferIndex == bytesInBuffer) { + this.bytesBuffer = null; + this.bytesBufferIndex = -1; + } + + // No buffered bytes available or index above threshold + if (this.bytesBufferIndex == -1 || this.bytesBufferIndex > threshold) { + + if (!this.isGeneratingBytes) { + this.isGeneratingBytes = true; + crypto.randomBytes(BUFFER_SIZE, function(err, bytes) { + self.bytesBuffer = bytes; + self.bytesBufferIndex = 0; + self.isGeneratingBytes = false; + }); + } + + // Fall back to sync call when no buffered bytes are available + if (this.bytesBufferIndex == -1) { + return crypto.randomBytes(bytes); + } + } + + var result = this.bytesBuffer.slice(bytes*this.bytesBufferIndex, bytes*(this.bytesBufferIndex+1)); + this.bytesBufferIndex++; + + return result; +} + +/** + * Generates a base64 id + * + * (Original version from socket.io ) + */ + +Base64Id.prototype.generateId = function () { + var rand = new Buffer(15); // multiple of 3 for base64 + if (!rand.writeInt32BE) { + return Math.abs(Math.random() * Math.random() * Date.now() | 0).toString() + + Math.abs(Math.random() * Math.random() * Date.now() | 0).toString(); + } + this.sequenceNumber = (this.sequenceNumber + 1) | 0; + rand.writeInt32BE(this.sequenceNumber, 11); + if (crypto.randomBytes) { + this.getRandomBytes(12).copy(rand); + } else { + // not secure for node 0.4 + [0, 4, 8].forEach(function(i) { + rand.writeInt32BE(Math.random() * Math.pow(2, 32) | 0, i); + }); + } + return rand.toString('base64').replace(/\//g, '_').replace(/\+/g, '-'); +}; + +/** + * Export + */ + +exports = module.exports = new Base64Id(); diff --git a/node_modules/base64id/package.json b/node_modules/base64id/package.json new file mode 100644 index 0000000..d157290 --- /dev/null +++ b/node_modules/base64id/package.json @@ -0,0 +1,50 @@ +{ + "_args": [ + [ + "base64id@1.0.0", + "/Volumes/Clear Drive/Code/2406 Web Apps/Assignments/Assignment 3/project" + ] + ], + "_from": "base64id@1.0.0", + "_id": "base64id@1.0.0", + "_inBundle": false, + "_integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=", + "_location": "/base64id", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "base64id@1.0.0", + "name": "base64id", + "escapedName": "base64id", + "rawSpec": "1.0.0", + "saveSpec": null, + "fetchSpec": "1.0.0" + }, + "_requiredBy": [ + "/engine.io" + ], + "_resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", + "_spec": "1.0.0", + "_where": "/Volumes/Clear Drive/Code/2406 Web Apps/Assignments/Assignment 3/project", + "author": { + "name": "Kristian Faeldt", + "email": "faeldt_kristian@cyberagent.co.jp" + }, + "bugs": { + "url": "https://github.com/faeldt/base64id/issues" + }, + "description": "Generates a base64 id", + "engines": { + "node": ">= 0.4.0" + }, + "homepage": "https://github.com/faeldt/base64id#readme", + "license": "MIT", + "main": "./lib/base64id.js", + "name": "base64id", + "repository": { + "type": "git", + "url": "git+https://github.com/faeldt/base64id.git" + }, + "version": "1.0.0" +} diff --git a/node_modules/better-assert/.npmignore b/node_modules/better-assert/.npmignore new file mode 100644 index 0000000..f1250e5 --- /dev/null +++ b/node_modules/better-assert/.npmignore @@ -0,0 +1,4 @@ +support +test +examples +*.sock diff --git a/node_modules/better-assert/History.md b/node_modules/better-assert/History.md new file mode 100644 index 0000000..cbb579b --- /dev/null +++ b/node_modules/better-assert/History.md @@ -0,0 +1,15 @@ + +1.0.0 / 2013-02-03 +================== + + * Stop using the removed magic __stack global getter + +0.1.0 / 2012-10-04 +================== + + * add throwing of AssertionError for test frameworks etc + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/better-assert/Makefile b/node_modules/better-assert/Makefile new file mode 100644 index 0000000..36a3ed7 --- /dev/null +++ b/node_modules/better-assert/Makefile @@ -0,0 +1,5 @@ + +test: + @echo "populate me" + +.PHONY: test \ No newline at end of file diff --git a/node_modules/better-assert/Readme.md b/node_modules/better-assert/Readme.md new file mode 100644 index 0000000..d8d3a63 --- /dev/null +++ b/node_modules/better-assert/Readme.md @@ -0,0 +1,61 @@ + +# better-assert + + Better c-style assertions using [callsite](https://github.com/visionmedia/callsite) for + self-documenting failure messages. + +## Installation + + $ npm install better-assert + +## Example + + By default assertions are enabled, however the __NO_ASSERT__ environment variable + will deactivate them when truthy. + +```js +var assert = require('better-assert'); + +test(); + +function test() { + var user = { name: 'tobi' }; + assert('tobi' == user.name); + assert('number' == typeof user.age); +} + +AssertionError: 'number' == typeof user.age + at test (/Users/tj/projects/better-assert/example.js:9:3) + at Object. (/Users/tj/projects/better-assert/example.js:4:1) + at Module._compile (module.js:449:26) + at Object.Module._extensions..js (module.js:467:10) + at Module.load (module.js:356:32) + at Function.Module._load (module.js:312:12) + at Module.runMain (module.js:492:10) + at process.startup.processNextTick.process._tickCallback (node.js:244:9) +``` + +## License + +(The MIT License) + +Copyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/node_modules/better-assert/example.js b/node_modules/better-assert/example.js new file mode 100644 index 0000000..688c29e --- /dev/null +++ b/node_modules/better-assert/example.js @@ -0,0 +1,10 @@ + +var assert = require('./'); + +test(); + +function test() { + var user = { name: 'tobi' }; + assert('tobi' == user.name); + assert('number' == typeof user.age); +} \ No newline at end of file diff --git a/node_modules/better-assert/index.js b/node_modules/better-assert/index.js new file mode 100644 index 0000000..fd1c9b7 --- /dev/null +++ b/node_modules/better-assert/index.js @@ -0,0 +1,38 @@ +/** + * Module dependencies. + */ + +var AssertionError = require('assert').AssertionError + , callsite = require('callsite') + , fs = require('fs') + +/** + * Expose `assert`. + */ + +module.exports = process.env.NO_ASSERT + ? function(){} + : assert; + +/** + * Assert the given `expr`. + */ + +function assert(expr) { + if (expr) return; + + var stack = callsite(); + var call = stack[1]; + var file = call.getFileName(); + var lineno = call.getLineNumber(); + var src = fs.readFileSync(file, 'utf8'); + var line = src.split('\n')[lineno-1]; + var src = line.match(/assert\((.*)\)/)[1]; + + var err = new AssertionError({ + message: src, + stackStartFunction: stack[0].getFunction() + }); + + throw err; +} diff --git a/node_modules/better-assert/package.json b/node_modules/better-assert/package.json new file mode 100644 index 0000000..7e8ff24 --- /dev/null +++ b/node_modules/better-assert/package.json @@ -0,0 +1,68 @@ +{ + "_args": [ + [ + "better-assert@1.0.2", + "/Volumes/Clear Drive/Code/2406 Web Apps/Assignments/Assignment 3/project" + ] + ], + "_from": "better-assert@1.0.2", + "_id": "better-assert@1.0.2", + "_inBundle": false, + "_integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", + "_location": "/better-assert", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "better-assert@1.0.2", + "name": "better-assert", + "escapedName": "better-assert", + "rawSpec": "1.0.2", + "saveSpec": null, + "fetchSpec": "1.0.2" + }, + "_requiredBy": [ + "/parseqs", + "/parseuri" + ], + "_resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", + "_spec": "1.0.2", + "_where": "/Volumes/Clear Drive/Code/2406 Web Apps/Assignments/Assignment 3/project", + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "bugs": { + "url": "https://github.com/visionmedia/better-assert/issues" + }, + "contributors": [ + { + "name": "TonyHe", + "email": "coolhzb@163.com" + }, + { + "name": "ForbesLindesay" + } + ], + "dependencies": { + "callsite": "1.0.0" + }, + "description": "Better assertions for node, reporting the expr, filename, lineno etc", + "engines": { + "node": "*" + }, + "homepage": "https://github.com/visionmedia/better-assert#readme", + "keywords": [ + "assert", + "stack", + "trace", + "debug" + ], + "main": "index", + "name": "better-assert", + "repository": { + "type": "git", + "url": "git+https://github.com/visionmedia/better-assert.git" + }, + "version": "1.0.2" +} diff --git a/node_modules/blob/.npmignore b/node_modules/blob/.npmignore new file mode 100644 index 0000000..548a368 --- /dev/null +++ b/node_modules/blob/.npmignore @@ -0,0 +1,2 @@ +node_modules +blob.js diff --git a/node_modules/blob/.zuul.yml b/node_modules/blob/.zuul.yml new file mode 100644 index 0000000..380c395 --- /dev/null +++ b/node_modules/blob/.zuul.yml @@ -0,0 +1,14 @@ +ui: mocha-bdd +browsers: + - name: chrome + version: 8..latest + - name: firefox + version: 7..latest + - name: safari + version: 6..latest + - name: opera + version: 12.1..latest + - name: ie + version: 10..latest + - name: android + version: latest diff --git a/node_modules/blob/Makefile b/node_modules/blob/Makefile new file mode 100644 index 0000000..7d9601a --- /dev/null +++ b/node_modules/blob/Makefile @@ -0,0 +1,14 @@ +REPORTER = dot + +build: blob.js + +blob.js: + @./node_modules/.bin/browserify --standalone blob index.js > blob.js + +test: + @./node_modules/.bin/zuul -- test/index.js + +clean: + rm blob.js + +.PHONY: test blob.js diff --git a/node_modules/blob/README.md b/node_modules/blob/README.md new file mode 100644 index 0000000..6915955 --- /dev/null +++ b/node_modules/blob/README.md @@ -0,0 +1,14 @@ +Blob +==== + +A module that exports a constructor that uses window.Blob when available, and a BlobBuilder with any vendor prefix in other cases. If neither is available, it exports undefined. + +Usage: + +```javascript +var Blob = require('blob'); +var b = new Blob(['hi', 'constructing', 'a', 'blob']); +``` + +## Licence +MIT diff --git a/node_modules/blob/index.js b/node_modules/blob/index.js new file mode 100644 index 0000000..cad3f84 --- /dev/null +++ b/node_modules/blob/index.js @@ -0,0 +1,96 @@ +/** + * Create a blob builder even when vendor prefixes exist + */ + +var BlobBuilder = global.BlobBuilder + || global.WebKitBlobBuilder + || global.MSBlobBuilder + || global.MozBlobBuilder; + +/** + * Check if Blob constructor is supported + */ + +var blobSupported = (function() { + try { + var a = new Blob(['hi']); + return a.size === 2; + } catch(e) { + return false; + } +})(); + +/** + * Check if Blob constructor supports ArrayBufferViews + * Fails in Safari 6, so we need to map to ArrayBuffers there. + */ + +var blobSupportsArrayBufferView = blobSupported && (function() { + try { + var b = new Blob([new Uint8Array([1,2])]); + return b.size === 2; + } catch(e) { + return false; + } +})(); + +/** + * Check if BlobBuilder is supported + */ + +var blobBuilderSupported = BlobBuilder + && BlobBuilder.prototype.append + && BlobBuilder.prototype.getBlob; + +/** + * Helper function that maps ArrayBufferViews to ArrayBuffers + * Used by BlobBuilder constructor and old browsers that didn't + * support it in the Blob constructor. + */ + +function mapArrayBufferViews(ary) { + for (var i = 0; i < ary.length; i++) { + var chunk = ary[i]; + if (chunk.buffer instanceof ArrayBuffer) { + var buf = chunk.buffer; + + // if this is a subarray, make a copy so we only + // include the subarray region from the underlying buffer + if (chunk.byteLength !== buf.byteLength) { + var copy = new Uint8Array(chunk.byteLength); + copy.set(new Uint8Array(buf, chunk.byteOffset, chunk.byteLength)); + buf = copy.buffer; + } + + ary[i] = buf; + } + } +} + +function BlobBuilderConstructor(ary, options) { + options = options || {}; + + var bb = new BlobBuilder(); + mapArrayBufferViews(ary); + + for (var i = 0; i < ary.length; i++) { + bb.append(ary[i]); + } + + return (options.type) ? bb.getBlob(options.type) : bb.getBlob(); +}; + +function BlobConstructor(ary, options) { + mapArrayBufferViews(ary); + return new Blob(ary, options || {}); +}; + +module.exports = (function() { + if (blobSupported) { + return blobSupportsArrayBufferView ? global.Blob : BlobConstructor; + } else if (blobBuilderSupported) { + return BlobBuilderConstructor; + } else { + return undefined; + } +})(); diff --git a/node_modules/blob/package.json b/node_modules/blob/package.json new file mode 100644 index 0000000..6c04c7c --- /dev/null +++ b/node_modules/blob/package.json @@ -0,0 +1,51 @@ +{ + "_args": [ + [ + "blob@0.0.4", + "/Volumes/Clear Drive/Code/2406 Web Apps/Assignments/Assignment 3/project" + ] + ], + "_from": "blob@0.0.4", + "_id": "blob@0.0.4", + "_inBundle": false, + "_integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=", + "_location": "/blob", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "blob@0.0.4", + "name": "blob", + "escapedName": "blob", + "rawSpec": "0.0.4", + "saveSpec": null, + "fetchSpec": "0.0.4" + }, + "_requiredBy": [ + "/engine.io-parser" + ], + "_resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", + "_spec": "0.0.4", + "_where": "/Volumes/Clear Drive/Code/2406 Web Apps/Assignments/Assignment 3/project", + "bugs": { + "url": "https://github.com/rase-/blob/issues" + }, + "dependencies": {}, + "description": "Abstracts out Blob and uses BlobBulder in cases where it is supported with any vendor prefix.", + "devDependencies": { + "browserify": "3.30.1", + "expect.js": "0.2.0", + "mocha": "1.17.1", + "zuul": "1.5.4" + }, + "homepage": "https://github.com/rase-/blob", + "name": "blob", + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/rase-/blob.git" + }, + "scripts": { + "test": "make test" + }, + "version": "0.0.4" +} diff --git a/node_modules/blob/test/index.js b/node_modules/blob/test/index.js new file mode 100644 index 0000000..df9303f --- /dev/null +++ b/node_modules/blob/test/index.js @@ -0,0 +1,94 @@ +var Blob = require('../'); +var expect = require('expect.js'); + +describe('blob', function() { + if (!Blob) { + it('should not have a blob or a blob builder in the global namespace, or blob should not be a constructor function if the module exports false', function() { + try { + var ab = (new Uint8Array(5)).buffer; + global.Blob([ab]); + expect().fail('Blob shouldn\'t be constructable'); + } catch (e) {} + + var BlobBuilder = global.BlobBuilder + || global.WebKitBlobBuilder + || global.MSBlobBuilder + || global.MozBlobBuilder; + expect(BlobBuilder).to.be(undefined); + }); + } else { + it('should encode a proper sized blob when given a string argument', function() { + var b = new Blob(['hi']); + expect(b.size).to.be(2); + }); + + it('should encode a blob with proper size when given two strings as arguments', function() { + var b = new Blob(['hi', 'hello']); + expect(b.size).to.be(7); + }); + + it('should encode arraybuffers with right content', function(done) { + var ary = new Uint8Array(5); + for (var i = 0; i < 5; i++) ary[i] = i; + var b = new Blob([ary.buffer]); + var fr = new FileReader(); + fr.onload = function() { + var newAry = new Uint8Array(this.result); + for (var i = 0; i < 5; i++) expect(newAry[i]).to.be(i); + done(); + }; + fr.readAsArrayBuffer(b); + }); + + it('should encode typed arrays with right content', function(done) { + var ary = new Uint8Array(5); + for (var i = 0; i < 5; i++) ary[i] = i; + var b = new Blob([ary]); + var fr = new FileReader(); + fr.onload = function() { + var newAry = new Uint8Array(this.result); + for (var i = 0; i < 5; i++) expect(newAry[i]).to.be(i); + done(); + }; + fr.readAsArrayBuffer(b); + }); + + it('should encode sliced typed arrays with right content', function(done) { + var ary = new Uint8Array(5); + for (var i = 0; i < 5; i++) ary[i] = i; + var b = new Blob([ary.subarray(2)]); + var fr = new FileReader(); + fr.onload = function() { + var newAry = new Uint8Array(this.result); + for (var i = 0; i < 3; i++) expect(newAry[i]).to.be(i + 2); + done(); + }; + fr.readAsArrayBuffer(b); + }); + + it('should encode with blobs', function(done) { + var ary = new Uint8Array(5); + for (var i = 0; i < 5; i++) ary[i] = i; + var b = new Blob([new Blob([ary.buffer])]); + var fr = new FileReader(); + fr.onload = function() { + var newAry = new Uint8Array(this.result); + for (var i = 0; i < 5; i++) expect(newAry[i]).to.be(i); + done(); + }; + fr.readAsArrayBuffer(b); + }); + + it('should enode mixed contents to right size', function() { + var ary = new Uint8Array(5); + for (var i = 0; i < 5; i++) ary[i] = i; + var b = new Blob([ary.buffer, 'hello']); + expect(b.size).to.be(10); + }); + + it('should accept mime type', function() { + var b = new Blob(['hi', 'hello'], { type: 'text/html' }); + expect(b.type).to.be('text/html'); + }); + } +}); diff --git a/node_modules/callsite/.npmignore b/node_modules/callsite/.npmignore new file mode 100644 index 0000000..f1250e5 --- /dev/null +++ b/node_modules/callsite/.npmignore @@ -0,0 +1,4 @@ +support +test +examples +*.sock diff --git a/node_modules/callsite/History.md b/node_modules/callsite/History.md new file mode 100644 index 0000000..4994198 --- /dev/null +++ b/node_modules/callsite/History.md @@ -0,0 +1,10 @@ + +1.0.0 / 2013-01-24 +================== + + * remove lame magical getters + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/callsite/Makefile b/node_modules/callsite/Makefile new file mode 100644 index 0000000..634e372 --- /dev/null +++ b/node_modules/callsite/Makefile @@ -0,0 +1,6 @@ + +test: + @./node_modules/.bin/mocha \ + --require should + +.PHONY: test \ No newline at end of file diff --git a/node_modules/callsite/Readme.md b/node_modules/callsite/Readme.md new file mode 100644 index 0000000..0dbd16a --- /dev/null +++ b/node_modules/callsite/Readme.md @@ -0,0 +1,44 @@ +# callstack + + Access to v8's "raw" `CallSite`s. + +## Installation + + $ npm install callsite + +## Example + +```js +var stack = require('callsite'); + +foo(); + +function foo() { + bar(); +} + +function bar() { + baz(); +} + +function baz() { + console.log(); + stack().forEach(function(site){ + console.log(' \033[36m%s\033[90m in %s:%d\033[0m' + , site.getFunctionName() || 'anonymous' + , site.getFileName() + , site.getLineNumber()); + }); + console.log(); +} +``` + +## Why? + + Because you can do weird, stupid, clever, wacky things such as: + + - [better-assert](https://github.com/visionmedia/better-assert) + +## License + + MIT diff --git a/node_modules/callsite/index.js b/node_modules/callsite/index.js new file mode 100644 index 0000000..d3ee6f8 --- /dev/null +++ b/node_modules/callsite/index.js @@ -0,0 +1,10 @@ + +module.exports = function(){ + var orig = Error.prepareStackTrace; + Error.prepareStackTrace = function(_, stack){ return stack; }; + var err = new Error; + Error.captureStackTrace(err, arguments.callee); + var stack = err.stack; + Error.prepareStackTrace = orig; + return stack; +}; diff --git a/node_modules/callsite/package.json b/node_modules/callsite/package.json new file mode 100644 index 0000000..4e99099 --- /dev/null +++ b/node_modules/callsite/package.json @@ -0,0 +1,51 @@ +{ + "_args": [ + [ + "callsite@1.0.0", + "/Volumes/Clear Drive/Code/2406 Web Apps/Assignments/Assignment 3/project" + ] + ], + "_from": "callsite@1.0.0", + "_id": "callsite@1.0.0", + "_inBundle": false, + "_integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", + "_location": "/callsite", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "callsite@1.0.0", + "name": "callsite", + "escapedName": "callsite", + "rawSpec": "1.0.0", + "saveSpec": null, + "fetchSpec": "1.0.0" + }, + "_requiredBy": [ + "/better-assert" + ], + "_resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "_spec": "1.0.0", + "_where": "/Volumes/Clear Drive/Code/2406 Web Apps/Assignments/Assignment 3/project", + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "dependencies": {}, + "description": "access to v8's CallSites", + "devDependencies": { + "mocha": "*", + "should": "*" + }, + "engines": { + "node": "*" + }, + "keywords": [ + "stack", + "trace", + "line" + ], + "main": "index", + "name": "callsite", + "version": "1.0.0" +} diff --git a/node_modules/component-bind/.npmignore b/node_modules/component-bind/.npmignore new file mode 100644 index 0000000..f1250e5 --- /dev/null +++ b/node_modules/component-bind/.npmignore @@ -0,0 +1,4 @@ +support +test +examples +*.sock diff --git a/node_modules/component-bind/History.md b/node_modules/component-bind/History.md new file mode 100644 index 0000000..2795fdb --- /dev/null +++ b/node_modules/component-bind/History.md @@ -0,0 +1,13 @@ + +1.0.0 / 2014-05-27 +================== + + * index: use slice ref (#7, @viatropos) + * package: rename package to "component-bind" + * package: add "repository" field (#6, @repoify) + * package: add "component" section + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/component-bind/Makefile b/node_modules/component-bind/Makefile new file mode 100644 index 0000000..4e9c8d3 --- /dev/null +++ b/node_modules/component-bind/Makefile @@ -0,0 +1,7 @@ + +test: + @./node_modules/.bin/mocha \ + --require should \ + --reporter spec + +.PHONY: test \ No newline at end of file diff --git a/node_modules/component-bind/Readme.md b/node_modules/component-bind/Readme.md new file mode 100644 index 0000000..6a8febc --- /dev/null +++ b/node_modules/component-bind/Readme.md @@ -0,0 +1,64 @@ +# bind + + Function binding utility. + +## Installation + +``` +$ component install component/bind +``` + +## API + + - [bind(obj, fn)](#bindobj-fn) + - [bind(obj, fn, ...)](#bindobj-fn-) + - [bind(obj, name)](#bindobj-name) + + + +### bind(obj, fn) +should bind the function to the given object. + +```js +var tobi = { name: 'tobi' }; + +function name() { + return this.name; +} + +var fn = bind(tobi, name); +fn().should.equal('tobi'); +``` + + +### bind(obj, fn, ...) +should curry the remaining arguments. + +```js +function add(a, b) { + return a + b; +} + +bind(null, add)(1, 2).should.equal(3); +bind(null, add, 1)(2).should.equal(3); +bind(null, add, 1, 2)().should.equal(3); +``` + + +### bind(obj, name) +should bind the method of the given name. + +```js +var tobi = { name: 'tobi' }; + +tobi.getName = function() { + return this.name; +}; + +var fn = bind(tobi, 'getName'); +fn().should.equal('tobi'); +``` + +## License + + MIT \ No newline at end of file diff --git a/node_modules/component-bind/component.json b/node_modules/component-bind/component.json new file mode 100644 index 0000000..4e1e93f --- /dev/null +++ b/node_modules/component-bind/component.json @@ -0,0 +1,13 @@ +{ + "name": "bind", + "version": "1.0.0", + "description": "function binding utility", + "keywords": [ + "bind", + "utility" + ], + "dependencies": {}, + "scripts": [ + "index.js" + ] +} diff --git a/node_modules/component-bind/index.js b/node_modules/component-bind/index.js new file mode 100644 index 0000000..4eeb2c0 --- /dev/null +++ b/node_modules/component-bind/index.js @@ -0,0 +1,23 @@ +/** + * Slice reference. + */ + +var slice = [].slice; + +/** + * Bind `obj` to `fn`. + * + * @param {Object} obj + * @param {Function|String} fn or string + * @return {Function} + * @api public + */ + +module.exports = function(obj, fn){ + if ('string' == typeof fn) fn = obj[fn]; + if ('function' != typeof fn) throw new Error('bind() requires a function'); + var args = slice.call(arguments, 2); + return function(){ + return fn.apply(obj, args.concat(slice.call(arguments))); + } +}; diff --git a/node_modules/component-bind/package.json b/node_modules/component-bind/package.json new file mode 100644 index 0000000..d803024 --- /dev/null +++ b/node_modules/component-bind/package.json @@ -0,0 +1,54 @@ +{ + "_args": [ + [ + "component-bind@1.0.0", + "/Volumes/Clear Drive/Code/2406 Web Apps/Assignments/Assignment 3/project" + ] + ], + "_from": "component-bind@1.0.0", + "_id": "component-bind@1.0.0", + "_inBundle": false, + "_integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=", + "_location": "/component-bind", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "component-bind@1.0.0", + "name": "component-bind", + "escapedName": "component-bind", + "rawSpec": "1.0.0", + "saveSpec": null, + "fetchSpec": "1.0.0" + }, + "_requiredBy": [ + "/socket.io-client" + ], + "_resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", + "_spec": "1.0.0", + "_where": "/Volumes/Clear Drive/Code/2406 Web Apps/Assignments/Assignment 3/project", + "bugs": { + "url": "https://github.com/component/bind/issues" + }, + "component": { + "scripts": { + "bind/index.js": "index.js" + } + }, + "description": "function binding utility", + "devDependencies": { + "mocha": "*", + "should": "*" + }, + "homepage": "https://github.com/component/bind#readme", + "keywords": [ + "bind", + "utility" + ], + "name": "component-bind", + "repository": { + "type": "git", + "url": "git+https://github.com/component/bind.git" + }, + "version": "1.0.0" +} diff --git a/node_modules/component-emitter/History.md b/node_modules/component-emitter/History.md new file mode 100644 index 0000000..9189c60 --- /dev/null +++ b/node_modules/component-emitter/History.md @@ -0,0 +1,68 @@ + +1.2.1 / 2016-04-18 +================== + + * enable client side use + +1.2.0 / 2014-02-12 +================== + + * prefix events with `$` to support object prototype method names + +1.1.3 / 2014-06-20 +================== + + * republish for npm + * add LICENSE file + +1.1.2 / 2014-02-10 +================== + + * package: rename to "component-emitter" + * package: update "main" and "component" fields + * Add license to Readme (same format as the other components) + * created .npmignore + * travis stuff + +1.1.1 / 2013-12-01 +================== + + * fix .once adding .on to the listener + * docs: Emitter#off() + * component: add `.repo` prop + +1.1.0 / 2013-10-20 +================== + + * add `.addEventListener()` and `.removeEventListener()` aliases + +1.0.1 / 2013-06-27 +================== + + * add support for legacy ie + +1.0.0 / 2013-02-26 +================== + + * add `.off()` support for removing all listeners + +0.0.6 / 2012-10-08 +================== + + * add `this._callbacks` initialization to prevent funky gotcha + +0.0.5 / 2012-09-07 +================== + + * fix `Emitter.call(this)` usage + +0.0.3 / 2012-07-11 +================== + + * add `.listeners()` + * rename `.has()` to `.hasListeners()` + +0.0.2 / 2012-06-28 +================== + + * fix `.off()` with `.once()`-registered callbacks diff --git a/node_modules/component-emitter/LICENSE b/node_modules/component-emitter/LICENSE new file mode 100644 index 0000000..d6e43f2 --- /dev/null +++ b/node_modules/component-emitter/LICENSE @@ -0,0 +1,24 @@ +(The MIT License) + +Copyright (c) 2014 Component contributors + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/component-emitter/Readme.md b/node_modules/component-emitter/Readme.md new file mode 100644 index 0000000..0466411 --- /dev/null +++ b/node_modules/component-emitter/Readme.md @@ -0,0 +1,74 @@ +# Emitter [![Build Status](https://travis-ci.org/component/emitter.png)](https://travis-ci.org/component/emitter) + + Event emitter component. + +## Installation + +``` +$ component install component/emitter +``` + +## API + +### Emitter(obj) + + The `Emitter` may also be used as a mixin. For example + a "plain" object may become an emitter, or you may + extend an existing prototype. + + As an `Emitter` instance: + +```js +var Emitter = require('emitter'); +var emitter = new Emitter; +emitter.emit('something'); +``` + + As a mixin: + +```js +var Emitter = require('emitter'); +var user = { name: 'tobi' }; +Emitter(user); + +user.emit('im a user'); +``` + + As a prototype mixin: + +```js +var Emitter = require('emitter'); +Emitter(User.prototype); +``` + +### Emitter#on(event, fn) + + Register an `event` handler `fn`. + +### Emitter#once(event, fn) + + Register a single-shot `event` handler `fn`, + removed immediately after it is invoked the + first time. + +### Emitter#off(event, fn) + + * Pass `event` and `fn` to remove a listener. + * Pass `event` to remove all listeners on that event. + * Pass nothing to remove all listeners on all events. + +### Emitter#emit(event, ...) + + Emit an `event` with variable option args. + +### Emitter#listeners(event) + + Return an array of callbacks, or an empty array. + +### Emitter#hasListeners(event) + + Check if this emitter has `event` handlers. + +## License + +MIT diff --git a/node_modules/component-emitter/index.js b/node_modules/component-emitter/index.js new file mode 100644 index 0000000..df94c78 --- /dev/null +++ b/node_modules/component-emitter/index.js @@ -0,0 +1,163 @@ + +/** + * Expose `Emitter`. + */ + +if (typeof module !== 'undefined') { + module.exports = Emitter; +} + +/** + * Initialize a new `Emitter`. + * + * @api public + */ + +function Emitter(obj) { + if (obj) return mixin(obj); +}; + +/** + * Mixin the emitter properties. + * + * @param {Object} obj + * @return {Object} + * @api private + */ + +function mixin(obj) { + for (var key in Emitter.prototype) { + obj[key] = Emitter.prototype[key]; + } + return obj; +} + +/** + * Listen on the given `event` with `fn`. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + +Emitter.prototype.on = +Emitter.prototype.addEventListener = function(event, fn){ + this._callbacks = this._callbacks || {}; + (this._callbacks['$' + event] = this._callbacks['$' + event] || []) + .push(fn); + return this; +}; + +/** + * Adds an `event` listener that will be invoked a single + * time then automatically removed. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + +Emitter.prototype.once = function(event, fn){ + function on() { + this.off(event, on); + fn.apply(this, arguments); + } + + on.fn = fn; + this.on(event, on); + return this; +}; + +/** + * Remove the given callback for `event` or all + * registered callbacks. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + +Emitter.prototype.off = +Emitter.prototype.removeListener = +Emitter.prototype.removeAllListeners = +Emitter.prototype.removeEventListener = function(event, fn){ + this._callbacks = this._callbacks || {}; + + // all + if (0 == arguments.length) { + this._callbacks = {}; + return this; + } + + // specific event + var callbacks = this._callbacks['$' + event]; + if (!callbacks) return this; + + // remove all handlers + if (1 == arguments.length) { + delete this._callbacks['$' + event]; + return this; + } + + // remove specific handler + var cb; + for (var i = 0; i < callbacks.length; i++) { + cb = callbacks[i]; + if (cb === fn || cb.fn === fn) { + callbacks.splice(i, 1); + break; + } + } + return this; +}; + +/** + * Emit `event` with the given args. + * + * @param {String} event + * @param {Mixed} ... + * @return {Emitter} + */ + +Emitter.prototype.emit = function(event){ + this._callbacks = this._callbacks || {}; + var args = [].slice.call(arguments, 1) + , callbacks = this._callbacks['$' + event]; + + if (callbacks) { + callbacks = callbacks.slice(0); + for (var i = 0, len = callbacks.length; i < len; ++i) { + callbacks[i].apply(this, args); + } + } + + return this; +}; + +/** + * Return array of callbacks for `event`. + * + * @param {String} event + * @return {Array} + * @api public + */ + +Emitter.prototype.listeners = function(event){ + this._callbacks = this._callbacks || {}; + return this._callbacks['$' + event] || []; +}; + +/** + * Check if this emitter has `event` handlers. + * + * @param {String} event + * @return {Boolean} + * @api public + */ + +Emitter.prototype.hasListeners = function(event){ + return !! this.listeners(event).length; +}; diff --git a/node_modules/component-emitter/package.json b/node_modules/component-emitter/package.json new file mode 100644 index 0000000..b3538f1 --- /dev/null +++ b/node_modules/component-emitter/package.json @@ -0,0 +1,61 @@ +{ + "_args": [ + [ + "component-emitter@1.2.1", + "/Volumes/Clear Drive/Code/2406 Web Apps/Assignments/Assignment 3/project" + ] + ], + "_from": "component-emitter@1.2.1", + "_id": "component-emitter@1.2.1", + "_inBundle": false, + "_integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "_location": "/component-emitter", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "component-emitter@1.2.1", + "name": "component-emitter", + "escapedName": "component-emitter", + "rawSpec": "1.2.1", + "saveSpec": null, + "fetchSpec": "1.2.1" + }, + "_requiredBy": [ + "/engine.io-client", + "/socket.io-client", + "/socket.io-parser" + ], + "_resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "_spec": "1.2.1", + "_where": "/Volumes/Clear Drive/Code/2406 Web Apps/Assignments/Assignment 3/project", + "bugs": { + "url": "https://github.com/component/emitter/issues" + }, + "component": { + "scripts": { + "emitter/index.js": "index.js" + } + }, + "description": "Event emitter", + "devDependencies": { + "mocha": "*", + "should": "*" + }, + "files": [ + "index.js", + "LICENSE" + ], + "homepage": "https://github.com/component/emitter#readme", + "license": "MIT", + "main": "index.js", + "name": "component-emitter", + "repository": { + "type": "git", + "url": "git+https://github.com/component/emitter.git" + }, + "scripts": { + "test": "make test" + }, + "version": "1.2.1" +} diff --git a/node_modules/component-inherit/.npmignore b/node_modules/component-inherit/.npmignore new file mode 100644 index 0000000..665aa21 --- /dev/null +++ b/node_modules/component-inherit/.npmignore @@ -0,0 +1,3 @@ +components +build +node_modules diff --git a/node_modules/component-inherit/History.md b/node_modules/component-inherit/History.md new file mode 100644 index 0000000..22d87e1 --- /dev/null +++ b/node_modules/component-inherit/History.md @@ -0,0 +1,5 @@ + +0.0.2 / 2012-09-03 +================== + + * fix typo in package.json diff --git a/node_modules/component-inherit/Makefile b/node_modules/component-inherit/Makefile new file mode 100644 index 0000000..ebbc52a --- /dev/null +++ b/node_modules/component-inherit/Makefile @@ -0,0 +1,16 @@ + +build: components index.js + @component build + +components: + @Component install + +clean: + rm -fr build components template.js + +test: + @node_modules/.bin/mocha \ + --require should \ + --reporter spec + +.PHONY: clean test diff --git a/node_modules/component-inherit/Readme.md b/node_modules/component-inherit/Readme.md new file mode 100644 index 0000000..f03ab27 --- /dev/null +++ b/node_modules/component-inherit/Readme.md @@ -0,0 +1,24 @@ +# inherit + + Prototype inheritance utility. + +## Installation + +``` +$ component install component/inherit +``` + +## Example + +```js +var inherit = require('inherit'); + +function Human() {} +function Woman() {} + +inherit(Woman, Human); +``` + +## License + + MIT diff --git a/node_modules/component-inherit/component.json b/node_modules/component-inherit/component.json new file mode 100644 index 0000000..ae57747 --- /dev/null +++ b/node_modules/component-inherit/component.json @@ -0,0 +1,10 @@ +{ + "name": "inherit", + "description": "Prototype inheritance utility", + "version": "0.0.3", + "keywords": ["inherit", "utility"], + "dependencies": {}, + "scripts": [ + "index.js" + ] +} diff --git a/node_modules/component-inherit/index.js b/node_modules/component-inherit/index.js new file mode 100644 index 0000000..aaebc03 --- /dev/null +++ b/node_modules/component-inherit/index.js @@ -0,0 +1,7 @@ + +module.exports = function(a, b){ + var fn = function(){}; + fn.prototype = b.prototype; + a.prototype = new fn; + a.prototype.constructor = a; +}; \ No newline at end of file diff --git a/node_modules/component-inherit/package.json b/node_modules/component-inherit/package.json new file mode 100644 index 0000000..e98bd5a --- /dev/null +++ b/node_modules/component-inherit/package.json @@ -0,0 +1,51 @@ +{ + "_args": [ + [ + "component-inherit@0.0.3", + "/Volumes/Clear Drive/Code/2406 Web Apps/Assignments/Assignment 3/project" + ] + ], + "_from": "component-inherit@0.0.3", + "_id": "component-inherit@0.0.3", + "_inBundle": false, + "_integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", + "_location": "/component-inherit", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "component-inherit@0.0.3", + "name": "component-inherit", + "escapedName": "component-inherit", + "rawSpec": "0.0.3", + "saveSpec": null, + "fetchSpec": "0.0.3" + }, + "_requiredBy": [ + "/engine.io-client" + ], + "_resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", + "_spec": "0.0.3", + "_where": "/Volumes/Clear Drive/Code/2406 Web Apps/Assignments/Assignment 3/project", + "bugs": { + "url": "https://github.com/component/inherit/issues" + }, + "component": { + "scripts": { + "inherit/index.js": "index.js" + } + }, + "dependencies": {}, + "description": "Prototype inheritance utility", + "homepage": "https://github.com/component/inherit#readme", + "keywords": [ + "inherit", + "utility" + ], + "name": "component-inherit", + "repository": { + "type": "git", + "url": "git+https://github.com/component/inherit.git" + }, + "version": "0.0.3" +} diff --git a/node_modules/component-inherit/test/inherit.js b/node_modules/component-inherit/test/inherit.js new file mode 100644 index 0000000..14852f2 --- /dev/null +++ b/node_modules/component-inherit/test/inherit.js @@ -0,0 +1,21 @@ + +/** + * Module dependencies. + */ + +var inherit = require('..'); + +describe('inherit(a, b)', function(){ + it('should inherit b\'s prototype', function(){ + function Loki(){} + function Animal(){} + + Animal.prototype.species = 'unknown'; + + inherit(Loki, Animal); + + var loki = new Loki; + loki.species.should.equal('unknown'); + loki.constructor.should.equal(Loki); + }) +}) \ No newline at end of file diff --git a/node_modules/cookie/HISTORY.md b/node_modules/cookie/HISTORY.md new file mode 100644 index 0000000..5bd6485 --- /dev/null +++ b/node_modules/cookie/HISTORY.md @@ -0,0 +1,118 @@ +0.3.1 / 2016-05-26 +================== + + * Fix `sameSite: true` to work with draft-7 clients + - `true` now sends `SameSite=Strict` instead of `SameSite` + +0.3.0 / 2016-05-26 +================== + + * Add `sameSite` option + - Replaces `firstPartyOnly` option, never implemented by browsers + * Improve error message when `encode` is not a function + * Improve error message when `expires` is not a `Date` + +0.2.4 / 2016-05-20 +================== + + * perf: enable strict mode + * perf: use for loop in parse + * perf: use string concatination for serialization + +0.2.3 / 2015-10-25 +================== + + * Fix cookie `Max-Age` to never be a floating point number + +0.2.2 / 2015-09-17 +================== + + * Fix regression when setting empty cookie value + - Ease the new restriction, which is just basic header-level validation + * Fix typo in invalid value errors + +0.2.1 / 2015-09-17 +================== + + * Throw on invalid values provided to `serialize` + - Ensures the resulting string is a valid HTTP header value + +0.2.0 / 2015-08-13 +================== + + * Add `firstPartyOnly` option + * Throw better error for invalid argument to parse + * perf: hoist regular expression + +0.1.5 / 2015-09-17 +================== + + * Fix regression when setting empty cookie value + - Ease the new restriction, which is just basic header-level validation + * Fix typo in invalid value errors + +0.1.4 / 2015-09-17 +================== + + * Throw better error for invalid argument to parse + * Throw on invalid values provided to `serialize` + - Ensures the resulting string is a valid HTTP header value + +0.1.3 / 2015-05-19 +================== + + * Reduce the scope of try-catch deopt + * Remove argument reassignments + +0.1.2 / 2014-04-16 +================== + + * Remove unnecessary files from npm package + +0.1.1 / 2014-02-23 +================== + + * Fix bad parse when cookie value contained a comma + * Fix support for `maxAge` of `0` + +0.1.0 / 2013-05-01 +================== + + * Add `decode` option + * Add `encode` option + +0.0.6 / 2013-04-08 +================== + + * Ignore cookie parts missing `=` + +0.0.5 / 2012-10-29 +================== + + * Return raw cookie value if value unescape errors + +0.0.4 / 2012-06-21 +================== + + * Use encode/decodeURIComponent for cookie encoding/decoding + - Improve server/client interoperability + +0.0.3 / 2012-06-06 +================== + + * Only escape special characters per the cookie RFC + +0.0.2 / 2012-06-01 +================== + + * Fix `maxAge` option to not throw error + +0.0.1 / 2012-05-28 +================== + + * Add more tests + +0.0.0 / 2012-05-28 +================== + + * Initial release diff --git a/node_modules/cookie/LICENSE b/node_modules/cookie/LICENSE new file mode 100644 index 0000000..058b6b4 --- /dev/null +++ b/node_modules/cookie/LICENSE @@ -0,0 +1,24 @@ +(The MIT License) + +Copyright (c) 2012-2014 Roman Shtylman +Copyright (c) 2015 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/node_modules/cookie/README.md b/node_modules/cookie/README.md new file mode 100644 index 0000000..db0d078 --- /dev/null +++ b/node_modules/cookie/README.md @@ -0,0 +1,220 @@ +# cookie + +[![NPM Version][npm-image]][npm-url] +[![NPM Downloads][downloads-image]][downloads-url] +[![Node.js Version][node-version-image]][node-version-url] +[![Build Status][travis-image]][travis-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +Basic HTTP cookie parser and serializer for HTTP servers. + +## Installation + +```sh +$ npm install cookie +``` + +## API + +```js +var cookie = require('cookie'); +``` + +### cookie.parse(str, options) + +Parse an HTTP `Cookie` header string and returning an object of all cookie name-value pairs. +The `str` argument is the string representing a `Cookie` header value and `options` is an +optional object containing additional parsing options. + +```js +var cookies = cookie.parse('foo=bar; equation=E%3Dmc%5E2'); +// { foo: 'bar', equation: 'E=mc^2' } +``` + +#### Options + +`cookie.parse` accepts these properties in the options object. + +##### decode + +Specifies a function that will be used to decode a cookie's value. Since the value of a cookie +has a limited character set (and must be a simple string), this function can be used to decode +a previously-encoded cookie value into a JavaScript string or other object. + +The default function is the global `decodeURIComponent`, which will decode any URL-encoded +sequences into their byte representations. + +**note** if an error is thrown from this function, the original, non-decoded cookie value will +be returned as the cookie's value. + +### cookie.serialize(name, value, options) + +Serialize a cookie name-value pair into a `Set-Cookie` header string. The `name` argument is the +name for the cookie, the `value` argument is the value to set the cookie to, and the `options` +argument is an optional object containing additional serialization options. + +```js +var setCookie = cookie.serialize('foo', 'bar'); +// foo=bar +``` + +#### Options + +`cookie.serialize` accepts these properties in the options object. + +##### domain + +Specifies the value for the [`Domain` `Set-Cookie` attribute][rfc-6266-5.2.3]. By default, no +domain is set, and most clients will consider the cookie to apply to only the current domain. + +##### encode + +Specifies a function that will be used to encode a cookie's value. Since value of a cookie +has a limited character set (and must be a simple string), this function can be used to encode +a value into a string suited for a cookie's value. + +The default function is the global `ecodeURIComponent`, which will encode a JavaScript string +into UTF-8 byte sequences and then URL-encode any that fall outside of the cookie range. + +##### expires + +Specifies the `Date` object to be the value for the [`Expires` `Set-Cookie` attribute][rfc-6266-5.2.1]. +By default, no expiration is set, and most clients will consider this a "non-persistent cookie" and +will delete it on a condition like exiting a web browser application. + +**note** the [cookie storage model specification][rfc-6266-5.3] states that if both `expires` and +`magAge` are set, then `maxAge` takes precedence, but it is possiblke not all clients by obey this, +so if both are set, they should point to the same date and time. + +##### httpOnly + +Specifies the `boolean` value for the [`HttpOnly` `Set-Cookie` attribute][rfc-6266-5.2.6]. When truthy, +the `HttpOnly` attribute is set, otherwise it is not. By default, the `HttpOnly` attribute is not set. + +**note** be careful when setting this to `true`, as compliant clients will not allow client-side +JavaScript to see the cookie in `document.cookie`. + +##### maxAge + +Specifies the `number` (in seconds) to be the value for the [`Max-Age` `Set-Cookie` attribute][rfc-6266-5.2.2]. +The given number will be converted to an integer by rounding down. By default, no maximum age is set. + +**note** the [cookie storage model specification][rfc-6266-5.3] states that if both `expires` and +`magAge` are set, then `maxAge` takes precedence, but it is possiblke not all clients by obey this, +so if both are set, they should point to the same date and time. + +##### path + +Specifies the value for the [`Path` `Set-Cookie` attribute][rfc-6266-5.2.4]. By default, the path +is considered the ["default path"][rfc-6266-5.1.4]. By default, no maximum age is set, and most +clients will consider this a "non-persistent cookie" and will delete it on a condition like exiting +a web browser application. + +##### sameSite + +Specifies the `boolean` or `string` to be the value for the [`SameSite` `Set-Cookie` attribute][draft-west-first-party-cookies-07]. + + - `true` will set the `SameSite` attribute to `Strict` for strict same site enforcement. + - `false` will not set the `SameSite` attribute. + - `'lax'` will set the `SameSite` attribute to `Lax` for lax same site enforcement. + - `'strict'` will set the `SameSite` attribute to `Strict` for strict same site enforcement. + +More information about the different enforcement levels can be found in the specification +https://tools.ietf.org/html/draft-west-first-party-cookies-07#section-4.1.1 + +**note** This is an attribute that has not yet been fully standardized, and may change in the future. +This also means many clients may ignore this attribute until they understand it. + +##### secure + +Specifies the `boolean` value for the [`Secure` `Set-Cookie` attribute][rfc-6266-5.2.5]. When truthy, +the `Secure` attribute is set, otherwise it is not. By default, the `Secure` attribute is not set. + +**note** be careful when setting this to `true`, as compliant clients will not send the cookie back to +the server in the future if the browser does not have an HTTPS connection. + +## Example + +The following example uses this module in conjunction with the Node.js core HTTP server +to prompt a user for their name and display it back on future visits. + +```js +var cookie = require('cookie'); +var escapeHtml = require('escape-html'); +var http = require('http'); +var url = require('url'); + +function onRequest(req, res) { + // Parse the query string + var query = url.parse(req.url, true, true).query; + + if (query && query.name) { + // Set a new cookie with the name + res.setHeader('Set-Cookie', cookie.serialize('name', String(query.name), { + httpOnly: true, + maxAge: 60 * 60 * 24 * 7 // 1 week + })); + + // Redirect back after setting cookie + res.statusCode = 302; + res.setHeader('Location', req.headers.referer || '/'); + res.end(); + return; + } + + // Parse the cookies on the request + var cookies = cookie.parse(req.headers.cookie || ''); + + // Get the visitor name set in the cookie + var name = cookies.name; + + res.setHeader('Content-Type', 'text/html; charset=UTF-8'); + + if (name) { + res.write('

Welcome back, ' + escapeHtml(name) + '!

'); + } else { + res.write('

Hello, new visitor!

'); + } + + res.write('
'); + res.write(' '); + res.end(' values + * + * @param {string} str + * @param {object} [options] + * @return {object} + * @public + */ + +function parse(str, options) { + if (typeof str !== 'string') { + throw new TypeError('argument str must be a string'); + } + + var obj = {} + var opt = options || {}; + var pairs = str.split(pairSplitRegExp); + var dec = opt.decode || decode; + + for (var i = 0; i < pairs.length; i++) { + var pair = pairs[i]; + var eq_idx = pair.indexOf('='); + + // skip things that don't look like key=value + if (eq_idx < 0) { + continue; + } + + var key = pair.substr(0, eq_idx).trim() + var val = pair.substr(++eq_idx, pair.length).trim(); + + // quoted values + if ('"' == val[0]) { + val = val.slice(1, -1); + } + + // only assign once + if (undefined == obj[key]) { + obj[key] = tryDecode(val, dec); + } + } + + return obj; +} + +/** + * Serialize data into a cookie header. + * + * Serialize the a name value pair into a cookie string suitable for + * http headers. An optional options object specified cookie parameters. + * + * serialize('foo', 'bar', { httpOnly: true }) + * => "foo=bar; httpOnly" + * + * @param {string} name + * @param {string} val + * @param {object} [options] + * @return {string} + * @public + */ + +function serialize(name, val, options) { + var opt = options || {}; + var enc = opt.encode || encode; + + if (typeof enc !== 'function') { + throw new TypeError('option encode is invalid'); + } + + if (!fieldContentRegExp.test(name)) { + throw new TypeError('argument name is invalid'); + } + + var value = enc(val); + + if (value && !fieldContentRegExp.test(value)) { + throw new TypeError('argument val is invalid'); + } + + var str = name + '=' + value; + + if (null != opt.maxAge) { + var maxAge = opt.maxAge - 0; + if (isNaN(maxAge)) throw new Error('maxAge should be a Number'); + str += '; Max-Age=' + Math.floor(maxAge); + } + + if (opt.domain) { + if (!fieldContentRegExp.test(opt.domain)) { + throw new TypeError('option domain is invalid'); + } + + str += '; Domain=' + opt.domain; + } + + if (opt.path) { + if (!fieldContentRegExp.test(opt.path)) { + throw new TypeError('option path is invalid'); + } + + str += '; Path=' + opt.path; + } + + if (opt.expires) { + if (typeof opt.expires.toUTCString !== 'function') { + throw new TypeError('option expires is invalid'); + } + + str += '; Expires=' + opt.expires.toUTCString(); + } + + if (opt.httpOnly) { + str += '; HttpOnly'; + } + + if (opt.secure) { + str += '; Secure'; + } + + if (opt.sameSite) { + var sameSite = typeof opt.sameSite === 'string' + ? opt.sameSite.toLowerCase() : opt.sameSite; + + switch (sameSite) { + case true: + str += '; SameSite=Strict'; + break; + case 'lax': + str += '; SameSite=Lax'; + break; + case 'strict': + str += '; SameSite=Strict'; + break; + default: + throw new TypeError('option sameSite is invalid'); + } + } + + return str; +} + +/** + * Try decoding a string using a decoding function. + * + * @param {string} str + * @param {function} decode + * @private + */ + +function tryDecode(str, decode) { + try { + return decode(str); + } catch (e) { + return str; + } +} diff --git a/node_modules/cookie/package.json b/node_modules/cookie/package.json new file mode 100644 index 0000000..55696dd --- /dev/null +++ b/node_modules/cookie/package.json @@ -0,0 +1,74 @@ +{ + "_args": [ + [ + "cookie@0.3.1", + "/Volumes/Clear Drive/Code/2406 Web Apps/Assignments/Assignment 3/project" + ] + ], + "_from": "cookie@0.3.1", + "_id": "cookie@0.3.1", + "_inBundle": false, + "_integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", + "_location": "/cookie", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "cookie@0.3.1", + "name": "cookie", + "escapedName": "cookie", + "rawSpec": "0.3.1", + "saveSpec": null, + "fetchSpec": "0.3.1" + }, + "_requiredBy": [ + "/engine.io" + ], + "_resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "_spec": "0.3.1", + "_where": "/Volumes/Clear Drive/Code/2406 Web Apps/Assignments/Assignment 3/project", + "author": { + "name": "Roman Shtylman", + "email": "shtylman@gmail.com" + }, + "bugs": { + "url": "https://github.com/jshttp/cookie/issues" + }, + "contributors": [ + { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + } + ], + "description": "HTTP server cookie parsing and serialization", + "devDependencies": { + "istanbul": "0.4.3", + "mocha": "1.21.5" + }, + "engines": { + "node": ">= 0.6" + }, + "files": [ + "HISTORY.md", + "LICENSE", + "README.md", + "index.js" + ], + "homepage": "https://github.com/jshttp/cookie#readme", + "keywords": [ + "cookie", + "cookies" + ], + "license": "MIT", + "name": "cookie", + "repository": { + "type": "git", + "url": "git+https://github.com/jshttp/cookie.git" + }, + "scripts": { + "test": "mocha --reporter spec --bail --check-leaks test/", + "test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/" + }, + "version": "0.3.1" +} diff --git a/node_modules/debug/.coveralls.yml b/node_modules/debug/.coveralls.yml new file mode 100644 index 0000000..20a7068 --- /dev/null +++ b/node_modules/debug/.coveralls.yml @@ -0,0 +1 @@ +repo_token: SIAeZjKYlHK74rbcFvNHMUzjRiMpflxve diff --git a/node_modules/debug/.eslintrc b/node_modules/debug/.eslintrc new file mode 100644 index 0000000..8a37ae2 --- /dev/null +++ b/node_modules/debug/.eslintrc @@ -0,0 +1,11 @@ +{ + "env": { + "browser": true, + "node": true + }, + "rules": { + "no-console": 0, + "no-empty": [1, { "allowEmptyCatch": true }] + }, + "extends": "eslint:recommended" +} diff --git a/node_modules/debug/.npmignore b/node_modules/debug/.npmignore new file mode 100644 index 0000000..5f60eec --- /dev/null +++ b/node_modules/debug/.npmignore @@ -0,0 +1,9 @@ +support +test +examples +example +*.sock +dist +yarn.lock +coverage +bower.json diff --git a/node_modules/debug/.travis.yml b/node_modules/debug/.travis.yml new file mode 100644 index 0000000..6c6090c --- /dev/null +++ b/node_modules/debug/.travis.yml @@ -0,0 +1,14 @@ + +language: node_js +node_js: + - "6" + - "5" + - "4" + +install: + - make node_modules + +script: + - make lint + - make test + - make coveralls diff --git a/node_modules/debug/CHANGELOG.md b/node_modules/debug/CHANGELOG.md new file mode 100644 index 0000000..eadaa18 --- /dev/null +++ b/node_modules/debug/CHANGELOG.md @@ -0,0 +1,362 @@ + +2.6.9 / 2017-09-22 +================== + + * remove ReDoS regexp in %o formatter (#504) + +2.6.8 / 2017-05-18 +================== + + * Fix: Check for undefined on browser globals (#462, @marbemac) + +2.6.7 / 2017-05-16 +================== + + * Fix: Update ms to 2.0.0 to fix regular expression denial of service vulnerability (#458, @hubdotcom) + * Fix: Inline extend function in node implementation (#452, @dougwilson) + * Docs: Fix typo (#455, @msasad) + +2.6.5 / 2017-04-27 +================== + + * Fix: null reference check on window.documentElement.style.WebkitAppearance (#447, @thebigredgeek) + * Misc: clean up browser reference checks (#447, @thebigredgeek) + * Misc: add npm-debug.log to .gitignore (@thebigredgeek) + + +2.6.4 / 2017-04-20 +================== + + * Fix: bug that would occure if process.env.DEBUG is a non-string value. (#444, @LucianBuzzo) + * Chore: ignore bower.json in npm installations. (#437, @joaovieira) + * Misc: update "ms" to v0.7.3 (@tootallnate) + +2.6.3 / 2017-03-13 +================== + + * Fix: Electron reference to `process.env.DEBUG` (#431, @paulcbetts) + * Docs: Changelog fix (@thebigredgeek) + +2.6.2 / 2017-03-10 +================== + + * Fix: DEBUG_MAX_ARRAY_LENGTH (#420, @slavaGanzin) + * Docs: Add backers and sponsors from Open Collective (#422, @piamancini) + * Docs: Add Slackin invite badge (@tootallnate) + +2.6.1 / 2017-02-10 +================== + + * Fix: Module's `export default` syntax fix for IE8 `Expected identifier` error + * Fix: Whitelist DEBUG_FD for values 1 and 2 only (#415, @pi0) + * Fix: IE8 "Expected identifier" error (#414, @vgoma) + * Fix: Namespaces would not disable once enabled (#409, @musikov) + +2.6.0 / 2016-12-28 +================== + + * Fix: added better null pointer checks for browser useColors (@thebigredgeek) + * Improvement: removed explicit `window.debug` export (#404, @tootallnate) + * Improvement: deprecated `DEBUG_FD` environment variable (#405, @tootallnate) + +2.5.2 / 2016-12-25 +================== + + * Fix: reference error on window within webworkers (#393, @KlausTrainer) + * Docs: fixed README typo (#391, @lurch) + * Docs: added notice about v3 api discussion (@thebigredgeek) + +2.5.1 / 2016-12-20 +================== + + * Fix: babel-core compatibility + +2.5.0 / 2016-12-20 +================== + + * Fix: wrong reference in bower file (@thebigredgeek) + * Fix: webworker compatibility (@thebigredgeek) + * Fix: output formatting issue (#388, @kribblo) + * Fix: babel-loader compatibility (#383, @escwald) + * Misc: removed built asset from repo and publications (@thebigredgeek) + * Misc: moved source files to /src (#378, @yamikuronue) + * Test: added karma integration and replaced babel with browserify for browser tests (#378, @yamikuronue) + * Test: coveralls integration (#378, @yamikuronue) + * Docs: simplified language in the opening paragraph (#373, @yamikuronue) + +2.4.5 / 2016-12-17 +================== + + * Fix: `navigator` undefined in Rhino (#376, @jochenberger) + * Fix: custom log function (#379, @hsiliev) + * Improvement: bit of cleanup + linting fixes (@thebigredgeek) + * Improvement: rm non-maintainted `dist/` dir (#375, @freewil) + * Docs: simplified language in the opening paragraph. (#373, @yamikuronue) + +2.4.4 / 2016-12-14 +================== + + * Fix: work around debug being loaded in preload scripts for electron (#368, @paulcbetts) + +2.4.3 / 2016-12-14 +================== + + * Fix: navigation.userAgent error for react native (#364, @escwald) + +2.4.2 / 2016-12-14 +================== + + * Fix: browser colors (#367, @tootallnate) + * Misc: travis ci integration (@thebigredgeek) + * Misc: added linting and testing boilerplate with sanity check (@thebigredgeek) + +2.4.1 / 2016-12-13 +================== + + * Fix: typo that broke the package (#356) + +2.4.0 / 2016-12-13 +================== + + * Fix: bower.json references unbuilt src entry point (#342, @justmatt) + * Fix: revert "handle regex special characters" (@tootallnate) + * Feature: configurable util.inspect()`options for NodeJS (#327, @tootallnate) + * Feature: %O`(big O) pretty-prints objects (#322, @tootallnate) + * Improvement: allow colors in workers (#335, @botverse) + * Improvement: use same color for same namespace. (#338, @lchenay) + +2.3.3 / 2016-11-09 +================== + + * Fix: Catch `JSON.stringify()` errors (#195, Jovan Alleyne) + * Fix: Returning `localStorage` saved values (#331, Levi Thomason) + * Improvement: Don't create an empty object when no `process` (Nathan Rajlich) + +2.3.2 / 2016-11-09 +================== + + * Fix: be super-safe in index.js as well (@TooTallNate) + * Fix: should check whether process exists (Tom Newby) + +2.3.1 / 2016-11-09 +================== + + * Fix: Added electron compatibility (#324, @paulcbetts) + * Improvement: Added performance optimizations (@tootallnate) + * Readme: Corrected PowerShell environment variable example (#252, @gimre) + * Misc: Removed yarn lock file from source control (#321, @fengmk2) + +2.3.0 / 2016-11-07 +================== + + * Fix: Consistent placement of ms diff at end of output (#215, @gorangajic) + * Fix: Escaping of regex special characters in namespace strings (#250, @zacronos) + * Fix: Fixed bug causing crash on react-native (#282, @vkarpov15) + * Feature: Enabled ES6+ compatible import via default export (#212 @bucaran) + * Feature: Added %O formatter to reflect Chrome's console.log capability (#279, @oncletom) + * Package: Update "ms" to 0.7.2 (#315, @DevSide) + * Package: removed superfluous version property from bower.json (#207 @kkirsche) + * Readme: fix USE_COLORS to DEBUG_COLORS + * Readme: Doc fixes for format string sugar (#269, @mlucool) + * Readme: Updated docs for DEBUG_FD and DEBUG_COLORS environment variables (#232, @mattlyons0) + * Readme: doc fixes for PowerShell (#271 #243, @exoticknight @unreadable) + * Readme: better docs for browser support (#224, @matthewmueller) + * Tooling: Added yarn integration for development (#317, @thebigredgeek) + * Misc: Renamed History.md to CHANGELOG.md (@thebigredgeek) + * Misc: Added license file (#226 #274, @CantemoInternal @sdaitzman) + * Misc: Updated contributors (@thebigredgeek) + +2.2.0 / 2015-05-09 +================== + + * package: update "ms" to v0.7.1 (#202, @dougwilson) + * README: add logging to file example (#193, @DanielOchoa) + * README: fixed a typo (#191, @amir-s) + * browser: expose `storage` (#190, @stephenmathieson) + * Makefile: add a `distclean` target (#189, @stephenmathieson) + +2.1.3 / 2015-03-13 +================== + + * Updated stdout/stderr example (#186) + * Updated example/stdout.js to match debug current behaviour + * Renamed example/stderr.js to stdout.js + * Update Readme.md (#184) + * replace high intensity foreground color for bold (#182, #183) + +2.1.2 / 2015-03-01 +================== + + * dist: recompile + * update "ms" to v0.7.0 + * package: update "browserify" to v9.0.3 + * component: fix "ms.js" repo location + * changed bower package name + * updated documentation about using debug in a browser + * fix: security error on safari (#167, #168, @yields) + +2.1.1 / 2014-12-29 +================== + + * browser: use `typeof` to check for `console` existence + * browser: check for `console.log` truthiness (fix IE 8/9) + * browser: add support for Chrome apps + * Readme: added Windows usage remarks + * Add `bower.json` to properly support bower install + +2.1.0 / 2014-10-15 +================== + + * node: implement `DEBUG_FD` env variable support + * package: update "browserify" to v6.1.0 + * package: add "license" field to package.json (#135, @panuhorsmalahti) + +2.0.0 / 2014-09-01 +================== + + * package: update "browserify" to v5.11.0 + * node: use stderr rather than stdout for logging (#29, @stephenmathieson) + +1.0.4 / 2014-07-15 +================== + + * dist: recompile + * example: remove `console.info()` log usage + * example: add "Content-Type" UTF-8 header to browser example + * browser: place %c marker after the space character + * browser: reset the "content" color via `color: inherit` + * browser: add colors support for Firefox >= v31 + * debug: prefer an instance `log()` function over the global one (#119) + * Readme: update documentation about styled console logs for FF v31 (#116, @wryk) + +1.0.3 / 2014-07-09 +================== + + * Add support for multiple wildcards in namespaces (#122, @seegno) + * browser: fix lint + +1.0.2 / 2014-06-10 +================== + + * browser: update color palette (#113, @gscottolson) + * common: make console logging function configurable (#108, @timoxley) + * node: fix %o colors on old node <= 0.8.x + * Makefile: find node path using shell/which (#109, @timoxley) + +1.0.1 / 2014-06-06 +================== + + * browser: use `removeItem()` to clear localStorage + * browser, node: don't set DEBUG if namespaces is undefined (#107, @leedm777) + * package: add "contributors" section + * node: fix comment typo + * README: list authors + +1.0.0 / 2014-06-04 +================== + + * make ms diff be global, not be scope + * debug: ignore empty strings in enable() + * node: make DEBUG_COLORS able to disable coloring + * *: export the `colors` array + * npmignore: don't publish the `dist` dir + * Makefile: refactor to use browserify + * package: add "browserify" as a dev dependency + * Readme: add Web Inspector Colors section + * node: reset terminal color for the debug content + * node: map "%o" to `util.inspect()` + * browser: map "%j" to `JSON.stringify()` + * debug: add custom "formatters" + * debug: use "ms" module for humanizing the diff + * Readme: add "bash" syntax highlighting + * browser: add Firebug color support + * browser: add colors for WebKit browsers + * node: apply log to `console` + * rewrite: abstract common logic for Node & browsers + * add .jshintrc file + +0.8.1 / 2014-04-14 +================== + + * package: re-add the "component" section + +0.8.0 / 2014-03-30 +================== + + * add `enable()` method for nodejs. Closes #27 + * change from stderr to stdout + * remove unnecessary index.js file + +0.7.4 / 2013-11-13 +================== + + * remove "browserify" key from package.json (fixes something in browserify) + +0.7.3 / 2013-10-30 +================== + + * fix: catch localStorage security error when cookies are blocked (Chrome) + * add debug(err) support. Closes #46 + * add .browser prop to package.json. Closes #42 + +0.7.2 / 2013-02-06 +================== + + * fix package.json + * fix: Mobile Safari (private mode) is broken with debug + * fix: Use unicode to send escape character to shell instead of octal to work with strict mode javascript + +0.7.1 / 2013-02-05 +================== + + * add repository URL to package.json + * add DEBUG_COLORED to force colored output + * add browserify support + * fix component. Closes #24 + +0.7.0 / 2012-05-04 +================== + + * Added .component to package.json + * Added debug.component.js build + +0.6.0 / 2012-03-16 +================== + + * Added support for "-" prefix in DEBUG [Vinay Pulim] + * Added `.enabled` flag to the node version [TooTallNate] + +0.5.0 / 2012-02-02 +================== + + * Added: humanize diffs. Closes #8 + * Added `debug.disable()` to the CS variant + * Removed padding. Closes #10 + * Fixed: persist client-side variant again. Closes #9 + +0.4.0 / 2012-02-01 +================== + + * Added browser variant support for older browsers [TooTallNate] + * Added `debug.enable('project:*')` to browser variant [TooTallNate] + * Added padding to diff (moved it to the right) + +0.3.0 / 2012-01-26 +================== + + * Added millisecond diff when isatty, otherwise UTC string + +0.2.0 / 2012-01-22 +================== + + * Added wildcard support + +0.1.0 / 2011-12-02 +================== + + * Added: remove colors unless stderr isatty [TooTallNate] + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/debug/LICENSE b/node_modules/debug/LICENSE new file mode 100644 index 0000000..658c933 --- /dev/null +++ b/node_modules/debug/LICENSE @@ -0,0 +1,19 @@ +(The MIT License) + +Copyright (c) 2014 TJ Holowaychuk + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software +and associated documentation files (the 'Software'), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/node_modules/debug/Makefile b/node_modules/debug/Makefile new file mode 100644 index 0000000..584da8b --- /dev/null +++ b/node_modules/debug/Makefile @@ -0,0 +1,50 @@ +# get Makefile directory name: http://stackoverflow.com/a/5982798/376773 +THIS_MAKEFILE_PATH:=$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)) +THIS_DIR:=$(shell cd $(dir $(THIS_MAKEFILE_PATH));pwd) + +# BIN directory +BIN := $(THIS_DIR)/node_modules/.bin + +# Path +PATH := node_modules/.bin:$(PATH) +SHELL := /bin/bash + +# applications +NODE ?= $(shell which node) +YARN ?= $(shell which yarn) +PKG ?= $(if $(YARN),$(YARN),$(NODE) $(shell which npm)) +BROWSERIFY ?= $(NODE) $(BIN)/browserify + +.FORCE: + +install: node_modules + +node_modules: package.json + @NODE_ENV= $(PKG) install + @touch node_modules + +lint: .FORCE + eslint browser.js debug.js index.js node.js + +test-node: .FORCE + istanbul cover node_modules/mocha/bin/_mocha -- test/**.js + +test-browser: .FORCE + mkdir -p dist + + @$(BROWSERIFY) \ + --standalone debug \ + . > dist/debug.js + + karma start --single-run + rimraf dist + +test: .FORCE + concurrently \ + "make test-node" \ + "make test-browser" + +coveralls: + cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js + +.PHONY: all install clean distclean diff --git a/node_modules/debug/README.md b/node_modules/debug/README.md new file mode 100644 index 0000000..f67be6b --- /dev/null +++ b/node_modules/debug/README.md @@ -0,0 +1,312 @@ +# debug +[![Build Status](https://travis-ci.org/visionmedia/debug.svg?branch=master)](https://travis-ci.org/visionmedia/debug) [![Coverage Status](https://coveralls.io/repos/github/visionmedia/debug/badge.svg?branch=master)](https://coveralls.io/github/visionmedia/debug?branch=master) [![Slack](https://visionmedia-community-slackin.now.sh/badge.svg)](https://visionmedia-community-slackin.now.sh/) [![OpenCollective](https://opencollective.com/debug/backers/badge.svg)](#backers) +[![OpenCollective](https://opencollective.com/debug/sponsors/badge.svg)](#sponsors) + + + +A tiny node.js debugging utility modelled after node core's debugging technique. + +**Discussion around the V3 API is under way [here](https://github.com/visionmedia/debug/issues/370)** + +## Installation + +```bash +$ npm install debug +``` + +## Usage + +`debug` exposes a function; simply pass this function the name of your module, and it will return a decorated version of `console.error` for you to pass debug statements to. This will allow you to toggle the debug output for different parts of your module as well as the module as a whole. + +Example _app.js_: + +```js +var debug = require('debug')('http') + , http = require('http') + , name = 'My App'; + +// fake app + +debug('booting %s', name); + +http.createServer(function(req, res){ + debug(req.method + ' ' + req.url); + res.end('hello\n'); +}).listen(3000, function(){ + debug('listening'); +}); + +// fake worker of some kind + +require('./worker'); +``` + +Example _worker.js_: + +```js +var debug = require('debug')('worker'); + +setInterval(function(){ + debug('doing some work'); +}, 1000); +``` + + The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples: + + ![debug http and worker](http://f.cl.ly/items/18471z1H402O24072r1J/Screenshot.png) + + ![debug worker](http://f.cl.ly/items/1X413v1a3M0d3C2c1E0i/Screenshot.png) + +#### Windows note + + On Windows the environment variable is set using the `set` command. + + ```cmd + set DEBUG=*,-not_this + ``` + + Note that PowerShell uses different syntax to set environment variables. + + ```cmd + $env:DEBUG = "*,-not_this" + ``` + +Then, run the program to be debugged as usual. + +## Millisecond diff + + When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls. + + ![](http://f.cl.ly/items/2i3h1d3t121M2Z1A3Q0N/Screenshot.png) + + When stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below: + + ![](http://f.cl.ly/items/112H3i0e0o0P0a2Q2r11/Screenshot.png) + +## Conventions + + If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser". + +## Wildcards + + The `*` character may be used as a wildcard. Suppose for example your library has debuggers named "connect:bodyParser", "connect:compress", "connect:session", instead of listing all three with `DEBUG=connect:bodyParser,connect:compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`. + + You can also exclude specific debuggers by prefixing them with a "-" character. For example, `DEBUG=*,-connect:*` would include all debuggers except those starting with "connect:". + +## Environment Variables + + When running through Node.js, you can set a few environment variables that will + change the behavior of the debug logging: + +| Name | Purpose | +|-----------|-------------------------------------------------| +| `DEBUG` | Enables/disables specific debugging namespaces. | +| `DEBUG_COLORS`| Whether or not to use colors in the debug output. | +| `DEBUG_DEPTH` | Object inspection depth. | +| `DEBUG_SHOW_HIDDEN` | Shows hidden properties on inspected objects. | + + + __Note:__ The environment variables beginning with `DEBUG_` end up being + converted into an Options object that gets used with `%o`/`%O` formatters. + See the Node.js documentation for + [`util.inspect()`](https://nodejs.org/api/util.html#util_util_inspect_object_options) + for the complete list. + +## Formatters + + + Debug uses [printf-style](https://wikipedia.org/wiki/Printf_format_string) formatting. Below are the officially supported formatters: + +| Formatter | Representation | +|-----------|----------------| +| `%O` | Pretty-print an Object on multiple lines. | +| `%o` | Pretty-print an Object all on a single line. | +| `%s` | String. | +| `%d` | Number (both integer and float). | +| `%j` | JSON. Replaced with the string '[Circular]' if the argument contains circular references. | +| `%%` | Single percent sign ('%'). This does not consume an argument. | + +### Custom formatters + + You can add custom formatters by extending the `debug.formatters` object. For example, if you wanted to add support for rendering a Buffer as hex with `%h`, you could do something like: + +```js +const createDebug = require('debug') +createDebug.formatters.h = (v) => { + return v.toString('hex') +} + +// …elsewhere +const debug = createDebug('foo') +debug('this is hex: %h', new Buffer('hello world')) +// foo this is hex: 68656c6c6f20776f726c6421 +0ms +``` + +## Browser support + You can build a browser-ready script using [browserify](https://github.com/substack/node-browserify), + or just use the [browserify-as-a-service](https://wzrd.in/) [build](https://wzrd.in/standalone/debug@latest), + if you don't want to build it yourself. + + Debug's enable state is currently persisted by `localStorage`. + Consider the situation shown below where you have `worker:a` and `worker:b`, + and wish to debug both. You can enable this using `localStorage.debug`: + +```js +localStorage.debug = 'worker:*' +``` + +And then refresh the page. + +```js +a = debug('worker:a'); +b = debug('worker:b'); + +setInterval(function(){ + a('doing some work'); +}, 1000); + +setInterval(function(){ + b('doing some work'); +}, 1200); +``` + +#### Web Inspector Colors + + Colors are also enabled on "Web Inspectors" that understand the `%c` formatting + option. These are WebKit web inspectors, Firefox ([since version + 31](https://hacks.mozilla.org/2014/05/editable-box-model-multiple-selection-sublime-text-keys-much-more-firefox-developer-tools-episode-31/)) + and the Firebug plugin for Firefox (any version). + + Colored output looks something like: + + ![](https://cloud.githubusercontent.com/assets/71256/3139768/b98c5fd8-e8ef-11e3-862a-f7253b6f47c6.png) + + +## Output streams + + By default `debug` will log to stderr, however this can be configured per-namespace by overriding the `log` method: + +Example _stdout.js_: + +```js +var debug = require('debug'); +var error = debug('app:error'); + +// by default stderr is used +error('goes to stderr!'); + +var log = debug('app:log'); +// set this namespace to log via console.log +log.log = console.log.bind(console); // don't forget to bind to console! +log('goes to stdout'); +error('still goes to stderr!'); + +// set all output to go via console.info +// overrides all per-namespace log settings +debug.log = console.info.bind(console); +error('now goes to stdout via console.info'); +log('still goes to stdout, but via console.info now'); +``` + + +## Authors + + - TJ Holowaychuk + - Nathan Rajlich + - Andrew Rhyne + +## Backers + +Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/debug#backer)] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +## Sponsors + +Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/debug#sponsor)] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +## License + +(The MIT License) + +Copyright (c) 2014-2016 TJ Holowaychuk <tj@vision-media.ca> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/debug/component.json b/node_modules/debug/component.json new file mode 100644 index 0000000..9de2641 --- /dev/null +++ b/node_modules/debug/component.json @@ -0,0 +1,19 @@ +{ + "name": "debug", + "repo": "visionmedia/debug", + "description": "small debugging utility", + "version": "2.6.9", + "keywords": [ + "debug", + "log", + "debugger" + ], + "main": "src/browser.js", + "scripts": [ + "src/browser.js", + "src/debug.js" + ], + "dependencies": { + "rauchg/ms.js": "0.7.1" + } +} diff --git a/node_modules/debug/karma.conf.js b/node_modules/debug/karma.conf.js new file mode 100644 index 0000000..103a82d --- /dev/null +++ b/node_modules/debug/karma.conf.js @@ -0,0 +1,70 @@ +// Karma configuration +// Generated on Fri Dec 16 2016 13:09:51 GMT+0000 (UTC) + +module.exports = function(config) { + config.set({ + + // base path that will be used to resolve all patterns (eg. files, exclude) + basePath: '', + + + // frameworks to use + // available frameworks: https://npmjs.org/browse/keyword/karma-adapter + frameworks: ['mocha', 'chai', 'sinon'], + + + // list of files / patterns to load in the browser + files: [ + 'dist/debug.js', + 'test/*spec.js' + ], + + + // list of files to exclude + exclude: [ + 'src/node.js' + ], + + + // preprocess matching files before serving them to the browser + // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor + preprocessors: { + }, + + // test results reporter to use + // possible values: 'dots', 'progress' + // available reporters: https://npmjs.org/browse/keyword/karma-reporter + reporters: ['progress'], + + + // web server port + port: 9876, + + + // enable / disable colors in the output (reporters and logs) + colors: true, + + + // level of logging + // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG + logLevel: config.LOG_INFO, + + + // enable / disable watching file and executing tests whenever any file changes + autoWatch: true, + + + // start these browsers + // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher + browsers: ['PhantomJS'], + + + // Continuous Integration mode + // if true, Karma captures browsers, runs the tests and exits + singleRun: false, + + // Concurrency level + // how many browser should be started simultaneous + concurrency: Infinity + }) +} diff --git a/node_modules/debug/node.js b/node_modules/debug/node.js new file mode 100644 index 0000000..7fc36fe --- /dev/null +++ b/node_modules/debug/node.js @@ -0,0 +1 @@ +module.exports = require('./src/node'); diff --git a/node_modules/debug/package.json b/node_modules/debug/package.json new file mode 100644 index 0000000..b419551 --- /dev/null +++ b/node_modules/debug/package.json @@ -0,0 +1,92 @@ +{ + "_args": [ + [ + "debug@2.6.9", + "/Volumes/Clear Drive/Code/2406 Web Apps/Assignments/Assignment 3/project" + ] + ], + "_from": "debug@2.6.9", + "_id": "debug@2.6.9", + "_inBundle": false, + "_integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "_location": "/debug", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "debug@2.6.9", + "name": "debug", + "escapedName": "debug", + "rawSpec": "2.6.9", + "saveSpec": null, + "fetchSpec": "2.6.9" + }, + "_requiredBy": [ + "/socket.io", + "/socket.io-client" + ], + "_resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "_spec": "2.6.9", + "_where": "/Volumes/Clear Drive/Code/2406 Web Apps/Assignments/Assignment 3/project", + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "browser": "./src/browser.js", + "bugs": { + "url": "https://github.com/visionmedia/debug/issues" + }, + "component": { + "scripts": { + "debug/index.js": "browser.js", + "debug/debug.js": "debug.js" + } + }, + "contributors": [ + { + "name": "Nathan Rajlich", + "email": "nathan@tootallnate.net", + "url": "http://n8.io" + }, + { + "name": "Andrew Rhyne", + "email": "rhyneandrew@gmail.com" + } + ], + "dependencies": { + "ms": "2.0.0" + }, + "description": "small debugging utility", + "devDependencies": { + "browserify": "9.0.3", + "chai": "^3.5.0", + "concurrently": "^3.1.0", + "coveralls": "^2.11.15", + "eslint": "^3.12.1", + "istanbul": "^0.4.5", + "karma": "^1.3.0", + "karma-chai": "^0.1.0", + "karma-mocha": "^1.3.0", + "karma-phantomjs-launcher": "^1.0.2", + "karma-sinon": "^1.0.5", + "mocha": "^3.2.0", + "mocha-lcov-reporter": "^1.2.0", + "rimraf": "^2.5.4", + "sinon": "^1.17.6", + "sinon-chai": "^2.8.0" + }, + "homepage": "https://github.com/visionmedia/debug#readme", + "keywords": [ + "debug", + "log", + "debugger" + ], + "license": "MIT", + "main": "./src/index.js", + "name": "debug", + "repository": { + "type": "git", + "url": "git://github.com/visionmedia/debug.git" + }, + "version": "2.6.9" +} diff --git a/node_modules/debug/src/browser.js b/node_modules/debug/src/browser.js new file mode 100644 index 0000000..7106924 --- /dev/null +++ b/node_modules/debug/src/browser.js @@ -0,0 +1,185 @@ +/** + * This is the web browser implementation of `debug()`. + * + * Expose `debug()` as the module. + */ + +exports = module.exports = require('./debug'); +exports.log = log; +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; +exports.storage = 'undefined' != typeof chrome + && 'undefined' != typeof chrome.storage + ? chrome.storage.local + : localstorage(); + +/** + * Colors. + */ + +exports.colors = [ + 'lightseagreen', + 'forestgreen', + 'goldenrod', + 'dodgerblue', + 'darkorchid', + 'crimson' +]; + +/** + * Currently only WebKit-based Web Inspectors, Firefox >= v31, + * and the Firebug extension (any Firefox version) are known + * to support "%c" CSS customizations. + * + * TODO: add a `localStorage` variable to explicitly enable/disable colors + */ + +function useColors() { + // NB: In an Electron preload script, document will be defined but not fully + // initialized. Since we know we're in Chrome, we'll just detect this case + // explicitly + if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') { + return true; + } + + // is webkit? http://stackoverflow.com/a/16459606/376773 + // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 + return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || + // is firebug? http://stackoverflow.com/a/398120/376773 + (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || + // is firefox >= v31? + // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) || + // double check webkit in userAgent just in case we are in a worker + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); +} + +/** + * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. + */ + +exports.formatters.j = function(v) { + try { + return JSON.stringify(v); + } catch (err) { + return '[UnexpectedJSONParseError]: ' + err.message; + } +}; + + +/** + * Colorize log arguments if enabled. + * + * @api public + */ + +function formatArgs(args) { + var useColors = this.useColors; + + args[0] = (useColors ? '%c' : '') + + this.namespace + + (useColors ? ' %c' : ' ') + + args[0] + + (useColors ? '%c ' : ' ') + + '+' + exports.humanize(this.diff); + + if (!useColors) return; + + var c = 'color: ' + this.color; + args.splice(1, 0, c, 'color: inherit') + + // the final "%c" is somewhat tricky, because there could be other + // arguments passed either before or after the %c, so we need to + // figure out the correct index to insert the CSS into + var index = 0; + var lastC = 0; + args[0].replace(/%[a-zA-Z%]/g, function(match) { + if ('%%' === match) return; + index++; + if ('%c' === match) { + // we only are interested in the *last* %c + // (the user may have provided their own) + lastC = index; + } + }); + + args.splice(lastC, 0, c); +} + +/** + * Invokes `console.log()` when available. + * No-op when `console.log` is not a "function". + * + * @api public + */ + +function log() { + // this hackery is required for IE8/9, where + // the `console.log` function doesn't have 'apply' + return 'object' === typeof console + && console.log + && Function.prototype.apply.call(console.log, console, arguments); +} + +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ + +function save(namespaces) { + try { + if (null == namespaces) { + exports.storage.removeItem('debug'); + } else { + exports.storage.debug = namespaces; + } + } catch(e) {} +} + +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ + +function load() { + var r; + try { + r = exports.storage.debug; + } catch(e) {} + + // If debug isn't set in LS, and we're in Electron, try to load $DEBUG + if (!r && typeof process !== 'undefined' && 'env' in process) { + r = process.env.DEBUG; + } + + return r; +} + +/** + * Enable namespaces listed in `localStorage.debug` initially. + */ + +exports.enable(load()); + +/** + * Localstorage attempts to return the localstorage. + * + * This is necessary because safari throws + * when a user disables cookies/localstorage + * and you attempt to access it. + * + * @return {LocalStorage} + * @api private + */ + +function localstorage() { + try { + return window.localStorage; + } catch (e) {} +} diff --git a/node_modules/debug/src/debug.js b/node_modules/debug/src/debug.js new file mode 100644 index 0000000..6a5e3fc --- /dev/null +++ b/node_modules/debug/src/debug.js @@ -0,0 +1,202 @@ + +/** + * This is the common logic for both the Node.js and web browser + * implementations of `debug()`. + * + * Expose `debug()` as the module. + */ + +exports = module.exports = createDebug.debug = createDebug['default'] = createDebug; +exports.coerce = coerce; +exports.disable = disable; +exports.enable = enable; +exports.enabled = enabled; +exports.humanize = require('ms'); + +/** + * The currently active debug mode names, and names to skip. + */ + +exports.names = []; +exports.skips = []; + +/** + * Map of special "%n" handling functions, for the debug "format" argument. + * + * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". + */ + +exports.formatters = {}; + +/** + * Previous log timestamp. + */ + +var prevTime; + +/** + * Select a color. + * @param {String} namespace + * @return {Number} + * @api private + */ + +function selectColor(namespace) { + var hash = 0, i; + + for (i in namespace) { + hash = ((hash << 5) - hash) + namespace.charCodeAt(i); + hash |= 0; // Convert to 32bit integer + } + + return exports.colors[Math.abs(hash) % exports.colors.length]; +} + +/** + * Create a debugger with the given `namespace`. + * + * @param {String} namespace + * @return {Function} + * @api public + */ + +function createDebug(namespace) { + + function debug() { + // disabled? + if (!debug.enabled) return; + + var self = debug; + + // set `diff` timestamp + var curr = +new Date(); + var ms = curr - (prevTime || curr); + self.diff = ms; + self.prev = prevTime; + self.curr = curr; + prevTime = curr; + + // turn the `arguments` into a proper Array + var args = new Array(arguments.length); + for (var i = 0; i < args.length; i++) { + args[i] = arguments[i]; + } + + args[0] = exports.coerce(args[0]); + + if ('string' !== typeof args[0]) { + // anything else let's inspect with %O + args.unshift('%O'); + } + + // apply any `formatters` transformations + var index = 0; + args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) { + // if we encounter an escaped % then don't increase the array index + if (match === '%%') return match; + index++; + var formatter = exports.formatters[format]; + if ('function' === typeof formatter) { + var val = args[index]; + match = formatter.call(self, val); + + // now we need to remove `args[index]` since it's inlined in the `format` + args.splice(index, 1); + index--; + } + return match; + }); + + // apply env-specific formatting (colors, etc.) + exports.formatArgs.call(self, args); + + var logFn = debug.log || exports.log || console.log.bind(console); + logFn.apply(self, args); + } + + debug.namespace = namespace; + debug.enabled = exports.enabled(namespace); + debug.useColors = exports.useColors(); + debug.color = selectColor(namespace); + + // env-specific initialization logic for debug instances + if ('function' === typeof exports.init) { + exports.init(debug); + } + + return debug; +} + +/** + * Enables a debug mode by namespaces. This can include modes + * separated by a colon and wildcards. + * + * @param {String} namespaces + * @api public + */ + +function enable(namespaces) { + exports.save(namespaces); + + exports.names = []; + exports.skips = []; + + var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); + var len = split.length; + + for (var i = 0; i < len; i++) { + if (!split[i]) continue; // ignore empty strings + namespaces = split[i].replace(/\*/g, '.*?'); + if (namespaces[0] === '-') { + exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); + } else { + exports.names.push(new RegExp('^' + namespaces + '$')); + } + } +} + +/** + * Disable debug output. + * + * @api public + */ + +function disable() { + exports.enable(''); +} + +/** + * Returns true if the given mode name is enabled, false otherwise. + * + * @param {String} name + * @return {Boolean} + * @api public + */ + +function enabled(name) { + var i, len; + for (i = 0, len = exports.skips.length; i < len; i++) { + if (exports.skips[i].test(name)) { + return false; + } + } + for (i = 0, len = exports.names.length; i < len; i++) { + if (exports.names[i].test(name)) { + return true; + } + } + return false; +} + +/** + * Coerce `val`. + * + * @param {Mixed} val + * @return {Mixed} + * @api private + */ + +function coerce(val) { + if (val instanceof Error) return val.stack || val.message; + return val; +} diff --git a/node_modules/debug/src/index.js b/node_modules/debug/src/index.js new file mode 100644 index 0000000..e12cf4d --- /dev/null +++ b/node_modules/debug/src/index.js @@ -0,0 +1,10 @@ +/** + * Detect Electron renderer process, which is node, but we should + * treat as a browser. + */ + +if (typeof process !== 'undefined' && process.type === 'renderer') { + module.exports = require('./browser.js'); +} else { + module.exports = require('./node.js'); +} diff --git a/node_modules/debug/src/inspector-log.js b/node_modules/debug/src/inspector-log.js new file mode 100644 index 0000000..60ea6c0 --- /dev/null +++ b/node_modules/debug/src/inspector-log.js @@ -0,0 +1,15 @@ +module.exports = inspectorLog; + +// black hole +const nullStream = new (require('stream').Writable)(); +nullStream._write = () => {}; + +/** + * Outputs a `console.log()` to the Node.js Inspector console *only*. + */ +function inspectorLog() { + const stdout = console._stdout; + console._stdout = nullStream; + console.log.apply(console, arguments); + console._stdout = stdout; +} diff --git a/node_modules/debug/src/node.js b/node_modules/debug/src/node.js new file mode 100644 index 0000000..b15109c --- /dev/null +++ b/node_modules/debug/src/node.js @@ -0,0 +1,248 @@ +/** + * Module dependencies. + */ + +var tty = require('tty'); +var util = require('util'); + +/** + * This is the Node.js implementation of `debug()`. + * + * Expose `debug()` as the module. + */ + +exports = module.exports = require('./debug'); +exports.init = init; +exports.log = log; +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; + +/** + * Colors. + */ + +exports.colors = [6, 2, 3, 4, 5, 1]; + +/** + * Build up the default `inspectOpts` object from the environment variables. + * + * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js + */ + +exports.inspectOpts = Object.keys(process.env).filter(function (key) { + return /^debug_/i.test(key); +}).reduce(function (obj, key) { + // camel-case + var prop = key + .substring(6) + .toLowerCase() + .replace(/_([a-z])/g, function (_, k) { return k.toUpperCase() }); + + // coerce string value into JS value + var val = process.env[key]; + if (/^(yes|on|true|enabled)$/i.test(val)) val = true; + else if (/^(no|off|false|disabled)$/i.test(val)) val = false; + else if (val === 'null') val = null; + else val = Number(val); + + obj[prop] = val; + return obj; +}, {}); + +/** + * The file descriptor to write the `debug()` calls to. + * Set the `DEBUG_FD` env variable to override with another value. i.e.: + * + * $ DEBUG_FD=3 node script.js 3>debug.log + */ + +var fd = parseInt(process.env.DEBUG_FD, 10) || 2; + +if (1 !== fd && 2 !== fd) { + util.deprecate(function(){}, 'except for stderr(2) and stdout(1), any other usage of DEBUG_FD is deprecated. Override debug.log if you want to use a different log function (https://git.io/debug_fd)')() +} + +var stream = 1 === fd ? process.stdout : + 2 === fd ? process.stderr : + createWritableStdioStream(fd); + +/** + * Is stdout a TTY? Colored output is enabled when `true`. + */ + +function useColors() { + return 'colors' in exports.inspectOpts + ? Boolean(exports.inspectOpts.colors) + : tty.isatty(fd); +} + +/** + * Map %o to `util.inspect()`, all on a single line. + */ + +exports.formatters.o = function(v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts) + .split('\n').map(function(str) { + return str.trim() + }).join(' '); +}; + +/** + * Map %o to `util.inspect()`, allowing multiple lines if needed. + */ + +exports.formatters.O = function(v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts); +}; + +/** + * Adds ANSI color escape codes if enabled. + * + * @api public + */ + +function formatArgs(args) { + var name = this.namespace; + var useColors = this.useColors; + + if (useColors) { + var c = this.color; + var prefix = ' \u001b[3' + c + ';1m' + name + ' ' + '\u001b[0m'; + + args[0] = prefix + args[0].split('\n').join('\n' + prefix); + args.push('\u001b[3' + c + 'm+' + exports.humanize(this.diff) + '\u001b[0m'); + } else { + args[0] = new Date().toUTCString() + + ' ' + name + ' ' + args[0]; + } +} + +/** + * Invokes `util.format()` with the specified arguments and writes to `stream`. + */ + +function log() { + return stream.write(util.format.apply(util, arguments) + '\n'); +} + +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ + +function save(namespaces) { + if (null == namespaces) { + // If you set a process.env field to null or undefined, it gets cast to the + // string 'null' or 'undefined'. Just delete instead. + delete process.env.DEBUG; + } else { + process.env.DEBUG = namespaces; + } +} + +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ + +function load() { + return process.env.DEBUG; +} + +/** + * Copied from `node/src/node.js`. + * + * XXX: It's lame that node doesn't expose this API out-of-the-box. It also + * relies on the undocumented `tty_wrap.guessHandleType()` which is also lame. + */ + +function createWritableStdioStream (fd) { + var stream; + var tty_wrap = process.binding('tty_wrap'); + + // Note stream._type is used for test-module-load-list.js + + switch (tty_wrap.guessHandleType(fd)) { + case 'TTY': + stream = new tty.WriteStream(fd); + stream._type = 'tty'; + + // Hack to have stream not keep the event loop alive. + // See https://github.com/joyent/node/issues/1726 + if (stream._handle && stream._handle.unref) { + stream._handle.unref(); + } + break; + + case 'FILE': + var fs = require('fs'); + stream = new fs.SyncWriteStream(fd, { autoClose: false }); + stream._type = 'fs'; + break; + + case 'PIPE': + case 'TCP': + var net = require('net'); + stream = new net.Socket({ + fd: fd, + readable: false, + writable: true + }); + + // FIXME Should probably have an option in net.Socket to create a + // stream from an existing fd which is writable only. But for now + // we'll just add this hack and set the `readable` member to false. + // Test: ./node test/fixtures/echo.js < /etc/passwd + stream.readable = false; + stream.read = null; + stream._type = 'pipe'; + + // FIXME Hack to have stream not keep the event loop alive. + // See https://github.com/joyent/node/issues/1726 + if (stream._handle && stream._handle.unref) { + stream._handle.unref(); + } + break; + + default: + // Probably an error on in uv_guess_handle() + throw new Error('Implement me. Unknown stream file type!'); + } + + // For supporting legacy API we put the FD here. + stream.fd = fd; + + stream._isStdio = true; + + return stream; +} + +/** + * Init logic for `debug` instances. + * + * Create a new `inspectOpts` object in case `useColors` is set + * differently for a particular `debug` instance. + */ + +function init (debug) { + debug.inspectOpts = {}; + + var keys = Object.keys(exports.inspectOpts); + for (var i = 0; i < keys.length; i++) { + debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]]; + } +} + +/** + * Enable namespaces listed in `process.env.DEBUG` initially. + */ + +exports.enable(load()); diff --git a/node_modules/engine.io-client/LICENSE b/node_modules/engine.io-client/LICENSE new file mode 100644 index 0000000..b248ba1 --- /dev/null +++ b/node_modules/engine.io-client/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2014-2015 Automattic + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/engine.io-client/README.md b/node_modules/engine.io-client/README.md new file mode 100644 index 0000000..7e335a3 --- /dev/null +++ b/node_modules/engine.io-client/README.md @@ -0,0 +1,299 @@ + +# Engine.IO client + +[![Build Status](https://travis-ci.org/socketio/engine.io-client.svg?branch=master)](http://travis-ci.org/socketio/engine.io-client) +[![NPM version](https://badge.fury.io/js/engine.io-client.svg)](http://badge.fury.io/js/engine.io-client) + +This is the client for [Engine.IO](http://github.com/socketio/engine.io), +the implementation of transport-based cross-browser/cross-device +bi-directional communication layer for [Socket.IO](http://github.com/socketio/socket.io). + +## How to use + +### Standalone + +You can find an `engine.io.js` file in this repository, which is a +standalone build you can use as follows: + +```html + + +``` + +### With browserify + +Engine.IO is a commonjs module, which means you can include it by using +`require` on the browser and package using [browserify](http://browserify.org/): + +1. install the client package + + ```bash + $ npm install engine.io-client + ``` + +1. write your app code + + ```js + var socket = require('engine.io-client')('ws://localhost'); + socket.on('open', function(){ + socket.on('message', function(data){}); + socket.on('close', function(){}); + }); + ``` + +1. build your app bundle + + ```bash + $ browserify app.js > bundle.js + ``` + +1. include on your page + + ```html + + ``` + +### Sending and receiving binary + +```html + + +``` + +### Node.JS + +Add `engine.io-client` to your `package.json` and then: + +```js +var socket = require('engine.io-client')('ws://localhost'); +socket.on('open', function(){ + socket.on('message', function(data){}); + socket.on('close', function(){}); +}); +``` + +### Node.js with certificates +```js +var opts = { + key: fs.readFileSync('test/fixtures/client.key'), + cert: fs.readFileSync('test/fixtures/client.crt'), + ca: fs.readFileSync('test/fixtures/ca.crt') +}; + +var socket = require('engine.io-client')('ws://localhost', opts); +socket.on('open', function(){ + socket.on('message', function(data){}); + socket.on('close', function(){}); +}); +``` + +### Node.js with extraHeaders +```js +var opts = { + extraHeaders: { + 'X-Custom-Header-For-My-Project': 'my-secret-access-token', + 'Cookie': 'user_session=NI2JlCKF90aE0sJZD9ZzujtdsUqNYSBYxzlTsvdSUe35ZzdtVRGqYFr0kdGxbfc5gUOkR9RGp20GVKza; path=/; expires=Tue, 07-Apr-2015 18:18:08 GMT; secure; HttpOnly' + } +}; + +var socket = require('engine.io-client')('ws://localhost', opts); +socket.on('open', function(){ + socket.on('message', function(data){}); + socket.on('close', function(){}); +}); +``` + +## Features + +- Lightweight +- Runs on browser and node.js seamlessly +- Transports are independent of `Engine` + - Easy to debug + - Easy to unit test +- Runs inside HTML5 WebWorker +- Can send and receive binary data + - Receives as ArrayBuffer or Blob when in browser, and Buffer or ArrayBuffer + in Node + - When XHR2 or WebSockets are used, binary is emitted directly. Otherwise + binary is encoded into base64 strings, and decoded when binary types are + supported. + - With browsers that don't support ArrayBuffer, an object { base64: true, + data: dataAsBase64String } is emitted on the `message` event. + +## API + +### Socket + +The client class. Mixes in [Emitter](http://github.com/component/emitter). +Exposed as `eio` in the browser standalone build. + +#### Properties + +- `protocol` _(Number)_: protocol revision number +- `binaryType` _(String)_ : can be set to 'arraybuffer' or 'blob' in browsers, + and `buffer` or `arraybuffer` in Node. Blob is only used in browser if it's + supported. + +#### Events + +- `open` + - Fired upon successful connection. +- `message` + - Fired when data is received from the server. + - **Arguments** + - `String` | `ArrayBuffer`: utf-8 encoded data or ArrayBuffer containing + binary data +- `close` + - Fired upon disconnection. In compliance with the WebSocket API spec, this event may be + fired even if the `open` event does not occur (i.e. due to connection error or `close()`). +- `error` + - Fired when an error occurs. +- `flush` + - Fired upon completing a buffer flush +- `drain` + - Fired after `drain` event of transport if writeBuffer is empty +- `upgradeError` + - Fired if an error occurs with a transport we're trying to upgrade to. +- `upgrade` + - Fired upon upgrade success, after the new transport is set +- `ping` + - Fired upon _flushing_ a ping packet (ie: actual packet write out) +- `pong` + - Fired upon receiving a pong packet. + +#### Methods + +- **constructor** + - Initializes the client + - **Parameters** + - `String` uri + - `Object`: optional, options object + - **Options** + - `agent` (`http.Agent`): `http.Agent` to use, defaults to `false` (NodeJS only) + - `upgrade` (`Boolean`): defaults to true, whether the client should try + to upgrade the transport from long-polling to something better. + - `forceJSONP` (`Boolean`): forces JSONP for polling transport. + - `jsonp` (`Boolean`): determines whether to use JSONP when + necessary for polling. If disabled (by settings to false) an error will + be emitted (saying "No transports available") if no other transports + are available. If another transport is available for opening a + connection (e.g. WebSocket) that transport + will be used instead. + - `forceBase64` (`Boolean`): forces base 64 encoding for polling transport even when XHR2 responseType is available and WebSocket even if the used standard supports binary. + - `enablesXDR` (`Boolean`): enables XDomainRequest for IE8 to avoid loading bar flashing with click sound. default to `false` because XDomainRequest has a flaw of not sending cookie. + - `timestampRequests` (`Boolean`): whether to add the timestamp with each + transport request. Note: polling requests are always stamped unless this + option is explicitly set to `false` (`false`) + - `timestampParam` (`String`): timestamp parameter (`t`) + - `policyPort` (`Number`): port the policy server listens on (`843`) + - `path` (`String`): path to connect to, default is `/engine.io` + - `transports` (`Array`): a list of transports to try (in order). + Defaults to `['polling', 'websocket']`. `Engine` + always attempts to connect directly with the first one, provided the + feature detection test for it passes. + - `transportOptions` (`Object`): hash of options, indexed by transport name, overriding the common options for the given transport + - `rememberUpgrade` (`Boolean`): defaults to false. + If true and if the previous websocket connection to the server succeeded, + the connection attempt will bypass the normal upgrade process and will initially + try websocket. A connection attempt following a transport error will use the + normal upgrade process. It is recommended you turn this on only when using + SSL/TLS connections, or if you know that your network does not block websockets. + - `pfx` (`String`): Certificate, Private key and CA certificates to use for SSL. Can be used in Node.js client environment to manually specify certificate information. + - `key` (`String`): Private key to use for SSL. Can be used in Node.js client environment to manually specify certificate information. + - `passphrase` (`String`): A string of passphrase for the private key or pfx. Can be used in Node.js client environment to manually specify certificate information. + - `cert` (`String`): Public x509 certificate to use. Can be used in Node.js client environment to manually specify certificate information. + - `ca` (`String`|`Array`): An authority certificate or array of authority certificates to check the remote host against.. Can be used in Node.js client environment to manually specify certificate information. + - `ciphers` (`String`): A string describing the ciphers to use or exclude. Consult the [cipher format list](http://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT) for details on the format. Can be used in Node.js client environment to manually specify certificate information. + - `rejectUnauthorized` (`Boolean`): If true, the server certificate is verified against the list of supplied CAs. An 'error' event is emitted if verification fails. Verification happens at the connection level, before the HTTP request is sent. Can be used in Node.js client environment to manually specify certificate information. + - `perMessageDeflate` (`Object|Boolean`): parameters of the WebSocket permessage-deflate extension + (see [ws module](https://github.com/einaros/ws) api docs). Set to `false` to disable. (`true`) + - `threshold` (`Number`): data is compressed only if the byte size is above this value. This option is ignored on the browser. (`1024`) + - `extraHeaders` (`Object`): Headers that will be passed for each request to the server (via xhr-polling and via websockets). These values then can be used during handshake or for special proxies. Can only be used in Node.js client environment. + - `onlyBinaryUpgrades` (`Boolean`): whether transport upgrades should be restricted to transports supporting binary data (`false`) + - `forceNode` (`Boolean`): Uses NodeJS implementation for websockets - even if there is a native Browser-Websocket available, which is preferred by default over the NodeJS implementation. (This is useful when using hybrid platforms like nw.js or electron) (`false`, NodeJS only) + - `localAddress` (`String`): the local IP address to connect to + - **Polling-only options** + - `requestTimeout` (`Number`): Timeout for xhr-polling requests in milliseconds (`0`) + - **Websocket-only options** + - `protocols` (`Array`): a list of subprotocols (see [MDN reference](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers#Subprotocols)) +- `send` + - Sends a message to the server + - **Parameters** + - `String` | `ArrayBuffer` | `ArrayBufferView` | `Blob`: data to send + - `Object`: optional, options object + - `Function`: optional, callback upon `drain` + - **Options** + - `compress` (`Boolean`): whether to compress sending data. This option is ignored and forced to be `true` on the browser. (`true`) +- `close` + - Disconnects the client. + +### Transport + +The transport class. Private. _Inherits from EventEmitter_. + +#### Events + +- `poll`: emitted by polling transports upon starting a new request +- `pollComplete`: emitted by polling transports upon completing a request +- `drain`: emitted by polling transports upon a buffer drain + +## Tests + +`engine.io-client` is used to test +[engine](http://github.com/socketio/engine.io). Running the `engine.io` +test suite ensures the client works and vice-versa. + +Browser tests are run using [zuul](https://github.com/defunctzombie/zuul). You can +run the tests locally using the following command. + +``` +./node_modules/.bin/zuul --local 8080 -- test/index.js +``` + +Additionally, `engine.io-client` has a standalone test suite you can run +with `make test` which will run node.js and browser tests. You must have zuul setup with +a saucelabs account. + +## Support + +The support channels for `engine.io-client` are the same as `socket.io`: + - irc.freenode.net **#socket.io** + - [Google Groups](http://groups.google.com/group/socket_io) + - [Website](http://socket.io) + +## Development + +To contribute patches, run tests or benchmarks, make sure to clone the +repository: + +```bash +git clone git://github.com/socketio/engine.io-client.git +``` + +Then: + +```bash +cd engine.io-client +npm install +``` + +See the `Tests` section above for how to run tests before submitting any patches. + +## License + +MIT - Copyright (c) 2014 Automattic, Inc. diff --git a/node_modules/engine.io-client/engine.io.js b/node_modules/engine.io-client/engine.io.js new file mode 100644 index 0000000..9ed4a0c --- /dev/null +++ b/node_modules/engine.io-client/engine.io.js @@ -0,0 +1,4700 @@ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else if(typeof exports === 'object') + exports["eio"] = factory(); + else + root["eio"] = factory(); +})(this, function() { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; + +/******/ // The require function +/******/ function __webpack_require__(moduleId) { + +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; + +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; + +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); + +/******/ // Flag the module as loaded +/******/ module.loaded = true; + +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } + + +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; + +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; + +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; + +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + module.exports = __webpack_require__(1); + + /** + * Exports parser + * + * @api public + * + */ + module.exports.parser = __webpack_require__(8); + +/***/ }, +/* 1 */ +/***/ function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(global) {'use strict'; + + var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; + + /** + * Module dependencies. + */ + + var transports = __webpack_require__(2); + var Emitter = __webpack_require__(18); + var debug = __webpack_require__(22)('engine.io-client:socket'); + var index = __webpack_require__(29); + var parser = __webpack_require__(8); + var parseuri = __webpack_require__(30); + var parseqs = __webpack_require__(19); + + /** + * Module exports. + */ + + module.exports = Socket; + + /** + * Socket constructor. + * + * @param {String|Object} uri or options + * @param {Object} options + * @api public + */ + + function Socket(uri, opts) { + if (!(this instanceof Socket)) return new Socket(uri, opts); + + opts = opts || {}; + + if (uri && 'object' === (typeof uri === 'undefined' ? 'undefined' : _typeof(uri))) { + opts = uri; + uri = null; + } + + if (uri) { + uri = parseuri(uri); + opts.hostname = uri.host; + opts.secure = uri.protocol === 'https' || uri.protocol === 'wss'; + opts.port = uri.port; + if (uri.query) opts.query = uri.query; + } else if (opts.host) { + opts.hostname = parseuri(opts.host).host; + } + + this.secure = null != opts.secure ? opts.secure : global.location && 'https:' === location.protocol; + + if (opts.hostname && !opts.port) { + // if no port is specified manually, use the protocol default + opts.port = this.secure ? '443' : '80'; + } + + this.agent = opts.agent || false; + this.hostname = opts.hostname || (global.location ? location.hostname : 'localhost'); + this.port = opts.port || (global.location && location.port ? location.port : this.secure ? 443 : 80); + this.query = opts.query || {}; + if ('string' === typeof this.query) this.query = parseqs.decode(this.query); + this.upgrade = false !== opts.upgrade; + this.path = (opts.path || '/engine.io').replace(/\/$/, '') + '/'; + this.forceJSONP = !!opts.forceJSONP; + this.jsonp = false !== opts.jsonp; + this.forceBase64 = !!opts.forceBase64; + this.enablesXDR = !!opts.enablesXDR; + this.timestampParam = opts.timestampParam || 't'; + this.timestampRequests = opts.timestampRequests; + this.transports = opts.transports || ['polling', 'websocket']; + this.transportOptions = opts.transportOptions || {}; + this.readyState = ''; + this.writeBuffer = []; + this.prevBufferLen = 0; + this.policyPort = opts.policyPort || 843; + this.rememberUpgrade = opts.rememberUpgrade || false; + this.binaryType = null; + this.onlyBinaryUpgrades = opts.onlyBinaryUpgrades; + this.perMessageDeflate = false !== opts.perMessageDeflate ? opts.perMessageDeflate || {} : false; + + if (true === this.perMessageDeflate) this.perMessageDeflate = {}; + if (this.perMessageDeflate && null == this.perMessageDeflate.threshold) { + this.perMessageDeflate.threshold = 1024; + } + + // SSL options for Node.js client + this.pfx = opts.pfx || null; + this.key = opts.key || null; + this.passphrase = opts.passphrase || null; + this.cert = opts.cert || null; + this.ca = opts.ca || null; + this.ciphers = opts.ciphers || null; + this.rejectUnauthorized = opts.rejectUnauthorized === undefined ? true : opts.rejectUnauthorized; + this.forceNode = !!opts.forceNode; + + // other options for Node.js client + var freeGlobal = (typeof global === 'undefined' ? 'undefined' : _typeof(global)) === 'object' && global; + if (freeGlobal.global === freeGlobal) { + if (opts.extraHeaders && Object.keys(opts.extraHeaders).length > 0) { + this.extraHeaders = opts.extraHeaders; + } + + if (opts.localAddress) { + this.localAddress = opts.localAddress; + } + } + + // set on handshake + this.id = null; + this.upgrades = null; + this.pingInterval = null; + this.pingTimeout = null; + + // set on heartbeat + this.pingIntervalTimer = null; + this.pingTimeoutTimer = null; + + this.open(); + } + + Socket.priorWebsocketSuccess = false; + + /** + * Mix in `Emitter`. + */ + + Emitter(Socket.prototype); + + /** + * Protocol version. + * + * @api public + */ + + Socket.protocol = parser.protocol; // this is an int + + /** + * Expose deps for legacy compatibility + * and standalone browser access. + */ + + Socket.Socket = Socket; + Socket.Transport = __webpack_require__(7); + Socket.transports = __webpack_require__(2); + Socket.parser = __webpack_require__(8); + + /** + * Creates transport of the given type. + * + * @param {String} transport name + * @return {Transport} + * @api private + */ + + Socket.prototype.createTransport = function (name) { + debug('creating transport "%s"', name); + var query = clone(this.query); + + // append engine.io protocol identifier + query.EIO = parser.protocol; + + // transport name + query.transport = name; + + // per-transport options + var options = this.transportOptions[name] || {}; + + // session id if we already have one + if (this.id) query.sid = this.id; + + var transport = new transports[name]({ + query: query, + socket: this, + agent: options.agent || this.agent, + hostname: options.hostname || this.hostname, + port: options.port || this.port, + secure: options.secure || this.secure, + path: options.path || this.path, + forceJSONP: options.forceJSONP || this.forceJSONP, + jsonp: options.jsonp || this.jsonp, + forceBase64: options.forceBase64 || this.forceBase64, + enablesXDR: options.enablesXDR || this.enablesXDR, + timestampRequests: options.timestampRequests || this.timestampRequests, + timestampParam: options.timestampParam || this.timestampParam, + policyPort: options.policyPort || this.policyPort, + pfx: options.pfx || this.pfx, + key: options.key || this.key, + passphrase: options.passphrase || this.passphrase, + cert: options.cert || this.cert, + ca: options.ca || this.ca, + ciphers: options.ciphers || this.ciphers, + rejectUnauthorized: options.rejectUnauthorized || this.rejectUnauthorized, + perMessageDeflate: options.perMessageDeflate || this.perMessageDeflate, + extraHeaders: options.extraHeaders || this.extraHeaders, + forceNode: options.forceNode || this.forceNode, + localAddress: options.localAddress || this.localAddress, + requestTimeout: options.requestTimeout || this.requestTimeout, + protocols: options.protocols || void 0 + }); + + return transport; + }; + + function clone(obj) { + var o = {}; + for (var i in obj) { + if (obj.hasOwnProperty(i)) { + o[i] = obj[i]; + } + } + return o; + } + + /** + * Initializes transport to use and starts probe. + * + * @api private + */ + Socket.prototype.open = function () { + var transport; + if (this.rememberUpgrade && Socket.priorWebsocketSuccess && this.transports.indexOf('websocket') !== -1) { + transport = 'websocket'; + } else if (0 === this.transports.length) { + // Emit error on next tick so it can be listened to + var self = this; + setTimeout(function () { + self.emit('error', 'No transports available'); + }, 0); + return; + } else { + transport = this.transports[0]; + } + this.readyState = 'opening'; + + // Retry with the next transport if the transport is disabled (jsonp: false) + try { + transport = this.createTransport(transport); + } catch (e) { + this.transports.shift(); + this.open(); + return; + } + + transport.open(); + this.setTransport(transport); + }; + + /** + * Sets the current transport. Disables the existing one (if any). + * + * @api private + */ + + Socket.prototype.setTransport = function (transport) { + debug('setting transport %s', transport.name); + var self = this; + + if (this.transport) { + debug('clearing existing transport %s', this.transport.name); + this.transport.removeAllListeners(); + } + + // set up transport + this.transport = transport; + + // set up transport listeners + transport.on('drain', function () { + self.onDrain(); + }).on('packet', function (packet) { + self.onPacket(packet); + }).on('error', function (e) { + self.onError(e); + }).on('close', function () { + self.onClose('transport close'); + }); + }; + + /** + * Probes a transport. + * + * @param {String} transport name + * @api private + */ + + Socket.prototype.probe = function (name) { + debug('probing transport "%s"', name); + var transport = this.createTransport(name, { probe: 1 }); + var failed = false; + var self = this; + + Socket.priorWebsocketSuccess = false; + + function onTransportOpen() { + if (self.onlyBinaryUpgrades) { + var upgradeLosesBinary = !this.supportsBinary && self.transport.supportsBinary; + failed = failed || upgradeLosesBinary; + } + if (failed) return; + + debug('probe transport "%s" opened', name); + transport.send([{ type: 'ping', data: 'probe' }]); + transport.once('packet', function (msg) { + if (failed) return; + if ('pong' === msg.type && 'probe' === msg.data) { + debug('probe transport "%s" pong', name); + self.upgrading = true; + self.emit('upgrading', transport); + if (!transport) return; + Socket.priorWebsocketSuccess = 'websocket' === transport.name; + + debug('pausing current transport "%s"', self.transport.name); + self.transport.pause(function () { + if (failed) return; + if ('closed' === self.readyState) return; + debug('changing transport and sending upgrade packet'); + + cleanup(); + + self.setTransport(transport); + transport.send([{ type: 'upgrade' }]); + self.emit('upgrade', transport); + transport = null; + self.upgrading = false; + self.flush(); + }); + } else { + debug('probe transport "%s" failed', name); + var err = new Error('probe error'); + err.transport = transport.name; + self.emit('upgradeError', err); + } + }); + } + + function freezeTransport() { + if (failed) return; + + // Any callback called by transport should be ignored since now + failed = true; + + cleanup(); + + transport.close(); + transport = null; + } + + // Handle any error that happens while probing + function onerror(err) { + var error = new Error('probe error: ' + err); + error.transport = transport.name; + + freezeTransport(); + + debug('probe transport "%s" failed because of error: %s', name, err); + + self.emit('upgradeError', error); + } + + function onTransportClose() { + onerror('transport closed'); + } + + // When the socket is closed while we're probing + function onclose() { + onerror('socket closed'); + } + + // When the socket is upgraded while we're probing + function onupgrade(to) { + if (transport && to.name !== transport.name) { + debug('"%s" works - aborting "%s"', to.name, transport.name); + freezeTransport(); + } + } + + // Remove all listeners on the transport and on self + function cleanup() { + transport.removeListener('open', onTransportOpen); + transport.removeListener('error', onerror); + transport.removeListener('close', onTransportClose); + self.removeListener('close', onclose); + self.removeListener('upgrading', onupgrade); + } + + transport.once('open', onTransportOpen); + transport.once('error', onerror); + transport.once('close', onTransportClose); + + this.once('close', onclose); + this.once('upgrading', onupgrade); + + transport.open(); + }; + + /** + * Called when connection is deemed open. + * + * @api public + */ + + Socket.prototype.onOpen = function () { + debug('socket open'); + this.readyState = 'open'; + Socket.priorWebsocketSuccess = 'websocket' === this.transport.name; + this.emit('open'); + this.flush(); + + // we check for `readyState` in case an `open` + // listener already closed the socket + if ('open' === this.readyState && this.upgrade && this.transport.pause) { + debug('starting upgrade probes'); + for (var i = 0, l = this.upgrades.length; i < l; i++) { + this.probe(this.upgrades[i]); + } + } + }; + + /** + * Handles a packet. + * + * @api private + */ + + Socket.prototype.onPacket = function (packet) { + if ('opening' === this.readyState || 'open' === this.readyState || 'closing' === this.readyState) { + debug('socket receive: type "%s", data "%s"', packet.type, packet.data); + + this.emit('packet', packet); + + // Socket is live - any packet counts + this.emit('heartbeat'); + + switch (packet.type) { + case 'open': + this.onHandshake(JSON.parse(packet.data)); + break; + + case 'pong': + this.setPing(); + this.emit('pong'); + break; + + case 'error': + var err = new Error('server error'); + err.code = packet.data; + this.onError(err); + break; + + case 'message': + this.emit('data', packet.data); + this.emit('message', packet.data); + break; + } + } else { + debug('packet received with socket readyState "%s"', this.readyState); + } + }; + + /** + * Called upon handshake completion. + * + * @param {Object} handshake obj + * @api private + */ + + Socket.prototype.onHandshake = function (data) { + this.emit('handshake', data); + this.id = data.sid; + this.transport.query.sid = data.sid; + this.upgrades = this.filterUpgrades(data.upgrades); + this.pingInterval = data.pingInterval; + this.pingTimeout = data.pingTimeout; + this.onOpen(); + // In case open handler closes socket + if ('closed' === this.readyState) return; + this.setPing(); + + // Prolong liveness of socket on heartbeat + this.removeListener('heartbeat', this.onHeartbeat); + this.on('heartbeat', this.onHeartbeat); + }; + + /** + * Resets ping timeout. + * + * @api private + */ + + Socket.prototype.onHeartbeat = function (timeout) { + clearTimeout(this.pingTimeoutTimer); + var self = this; + self.pingTimeoutTimer = setTimeout(function () { + if ('closed' === self.readyState) return; + self.onClose('ping timeout'); + }, timeout || self.pingInterval + self.pingTimeout); + }; + + /** + * Pings server every `this.pingInterval` and expects response + * within `this.pingTimeout` or closes connection. + * + * @api private + */ + + Socket.prototype.setPing = function () { + var self = this; + clearTimeout(self.pingIntervalTimer); + self.pingIntervalTimer = setTimeout(function () { + debug('writing ping packet - expecting pong within %sms', self.pingTimeout); + self.ping(); + self.onHeartbeat(self.pingTimeout); + }, self.pingInterval); + }; + + /** + * Sends a ping packet. + * + * @api private + */ + + Socket.prototype.ping = function () { + var self = this; + this.sendPacket('ping', function () { + self.emit('ping'); + }); + }; + + /** + * Called on `drain` event + * + * @api private + */ + + Socket.prototype.onDrain = function () { + this.writeBuffer.splice(0, this.prevBufferLen); + + // setting prevBufferLen = 0 is very important + // for example, when upgrading, upgrade packet is sent over, + // and a nonzero prevBufferLen could cause problems on `drain` + this.prevBufferLen = 0; + + if (0 === this.writeBuffer.length) { + this.emit('drain'); + } else { + this.flush(); + } + }; + + /** + * Flush write buffers. + * + * @api private + */ + + Socket.prototype.flush = function () { + if ('closed' !== this.readyState && this.transport.writable && !this.upgrading && this.writeBuffer.length) { + debug('flushing %d packets in socket', this.writeBuffer.length); + this.transport.send(this.writeBuffer); + // keep track of current length of writeBuffer + // splice writeBuffer and callbackBuffer on `drain` + this.prevBufferLen = this.writeBuffer.length; + this.emit('flush'); + } + }; + + /** + * Sends a message. + * + * @param {String} message. + * @param {Function} callback function. + * @param {Object} options. + * @return {Socket} for chaining. + * @api public + */ + + Socket.prototype.write = Socket.prototype.send = function (msg, options, fn) { + this.sendPacket('message', msg, options, fn); + return this; + }; + + /** + * Sends a packet. + * + * @param {String} packet type. + * @param {String} data. + * @param {Object} options. + * @param {Function} callback function. + * @api private + */ + + Socket.prototype.sendPacket = function (type, data, options, fn) { + if ('function' === typeof data) { + fn = data; + data = undefined; + } + + if ('function' === typeof options) { + fn = options; + options = null; + } + + if ('closing' === this.readyState || 'closed' === this.readyState) { + return; + } + + options = options || {}; + options.compress = false !== options.compress; + + var packet = { + type: type, + data: data, + options: options + }; + this.emit('packetCreate', packet); + this.writeBuffer.push(packet); + if (fn) this.once('flush', fn); + this.flush(); + }; + + /** + * Closes the connection. + * + * @api private + */ + + Socket.prototype.close = function () { + if ('opening' === this.readyState || 'open' === this.readyState) { + this.readyState = 'closing'; + + var self = this; + + if (this.writeBuffer.length) { + this.once('drain', function () { + if (this.upgrading) { + waitForUpgrade(); + } else { + close(); + } + }); + } else if (this.upgrading) { + waitForUpgrade(); + } else { + close(); + } + } + + function close() { + self.onClose('forced close'); + debug('socket closing - telling transport to close'); + self.transport.close(); + } + + function cleanupAndClose() { + self.removeListener('upgrade', cleanupAndClose); + self.removeListener('upgradeError', cleanupAndClose); + close(); + } + + function waitForUpgrade() { + // wait for upgrade to finish since we can't send packets while pausing a transport + self.once('upgrade', cleanupAndClose); + self.once('upgradeError', cleanupAndClose); + } + + return this; + }; + + /** + * Called upon transport error + * + * @api private + */ + + Socket.prototype.onError = function (err) { + debug('socket error %j', err); + Socket.priorWebsocketSuccess = false; + this.emit('error', err); + this.onClose('transport error', err); + }; + + /** + * Called upon transport close. + * + * @api private + */ + + Socket.prototype.onClose = function (reason, desc) { + if ('opening' === this.readyState || 'open' === this.readyState || 'closing' === this.readyState) { + debug('socket close with reason: "%s"', reason); + var self = this; + + // clear timers + clearTimeout(this.pingIntervalTimer); + clearTimeout(this.pingTimeoutTimer); + + // stop event from firing again for transport + this.transport.removeAllListeners('close'); + + // ensure transport won't stay open + this.transport.close(); + + // ignore further transport communication + this.transport.removeAllListeners(); + + // set ready state + this.readyState = 'closed'; + + // clear session id + this.id = null; + + // emit close event + this.emit('close', reason, desc); + + // clean buffers after, so users can still + // grab the buffers on `close` event + self.writeBuffer = []; + self.prevBufferLen = 0; + } + }; + + /** + * Filters upgrades, returning only those matching client transports. + * + * @param {Array} server upgrades + * @api private + * + */ + + Socket.prototype.filterUpgrades = function (upgrades) { + var filteredUpgrades = []; + for (var i = 0, j = upgrades.length; i < j; i++) { + if (~index(this.transports, upgrades[i])) filteredUpgrades.push(upgrades[i]); + } + return filteredUpgrades; + }; + /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) + +/***/ }, +/* 2 */ +/***/ function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(global) {'use strict'; + + /** + * Module dependencies + */ + + var XMLHttpRequest = __webpack_require__(3); + var XHR = __webpack_require__(5); + var JSONP = __webpack_require__(26); + var websocket = __webpack_require__(27); + + /** + * Export transports. + */ + + exports.polling = polling; + exports.websocket = websocket; + + /** + * Polling transport polymorphic constructor. + * Decides on xhr vs jsonp based on feature detection. + * + * @api private + */ + + function polling(opts) { + var xhr; + var xd = false; + var xs = false; + var jsonp = false !== opts.jsonp; + + if (global.location) { + var isSSL = 'https:' === location.protocol; + var port = location.port; + + // some user agents have empty `location.port` + if (!port) { + port = isSSL ? 443 : 80; + } + + xd = opts.hostname !== location.hostname || port !== opts.port; + xs = opts.secure !== isSSL; + } + + opts.xdomain = xd; + opts.xscheme = xs; + xhr = new XMLHttpRequest(opts); + + if ('open' in xhr && !opts.forceJSONP) { + return new XHR(opts); + } else { + if (!jsonp) throw new Error('JSONP disabled'); + return new JSONP(opts); + } + } + /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) + +/***/ }, +/* 3 */ +/***/ function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(global) {'use strict'; + + // browser shim for xmlhttprequest module + + var hasCORS = __webpack_require__(4); + + module.exports = function (opts) { + var xdomain = opts.xdomain; + + // scheme must be same when usign XDomainRequest + // http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx + var xscheme = opts.xscheme; + + // XDomainRequest has a flow of not sending cookie, therefore it should be disabled as a default. + // https://github.com/Automattic/engine.io-client/pull/217 + var enablesXDR = opts.enablesXDR; + + // XMLHttpRequest can be disabled on IE + try { + if ('undefined' !== typeof XMLHttpRequest && (!xdomain || hasCORS)) { + return new XMLHttpRequest(); + } + } catch (e) {} + + // Use XDomainRequest for IE8 if enablesXDR is true + // because loading bar keeps flashing when using jsonp-polling + // https://github.com/yujiosaka/socke.io-ie8-loading-example + try { + if ('undefined' !== typeof XDomainRequest && !xscheme && enablesXDR) { + return new XDomainRequest(); + } + } catch (e) {} + + if (!xdomain) { + try { + return new global[['Active'].concat('Object').join('X')]('Microsoft.XMLHTTP'); + } catch (e) {} + } + }; + /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) + +/***/ }, +/* 4 */ +/***/ function(module, exports) { + + + /** + * Module exports. + * + * Logic borrowed from Modernizr: + * + * - https://github.com/Modernizr/Modernizr/blob/master/feature-detects/cors.js + */ + + try { + module.exports = typeof XMLHttpRequest !== 'undefined' && + 'withCredentials' in new XMLHttpRequest(); + } catch (err) { + // if XMLHttp support is disabled in IE then it will throw + // when trying to create + module.exports = false; + } + + +/***/ }, +/* 5 */ +/***/ function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(global) {'use strict'; + + /** + * Module requirements. + */ + + var XMLHttpRequest = __webpack_require__(3); + var Polling = __webpack_require__(6); + var Emitter = __webpack_require__(18); + var inherit = __webpack_require__(20); + var debug = __webpack_require__(22)('engine.io-client:polling-xhr'); + + /** + * Module exports. + */ + + module.exports = XHR; + module.exports.Request = Request; + + /** + * Empty function + */ + + function empty() {} + + /** + * XHR Polling constructor. + * + * @param {Object} opts + * @api public + */ + + function XHR(opts) { + Polling.call(this, opts); + this.requestTimeout = opts.requestTimeout; + this.extraHeaders = opts.extraHeaders; + + if (global.location) { + var isSSL = 'https:' === location.protocol; + var port = location.port; + + // some user agents have empty `location.port` + if (!port) { + port = isSSL ? 443 : 80; + } + + this.xd = opts.hostname !== global.location.hostname || port !== opts.port; + this.xs = opts.secure !== isSSL; + } + } + + /** + * Inherits from Polling. + */ + + inherit(XHR, Polling); + + /** + * XHR supports binary + */ + + XHR.prototype.supportsBinary = true; + + /** + * Creates a request. + * + * @param {String} method + * @api private + */ + + XHR.prototype.request = function (opts) { + opts = opts || {}; + opts.uri = this.uri(); + opts.xd = this.xd; + opts.xs = this.xs; + opts.agent = this.agent || false; + opts.supportsBinary = this.supportsBinary; + opts.enablesXDR = this.enablesXDR; + + // SSL options for Node.js client + opts.pfx = this.pfx; + opts.key = this.key; + opts.passphrase = this.passphrase; + opts.cert = this.cert; + opts.ca = this.ca; + opts.ciphers = this.ciphers; + opts.rejectUnauthorized = this.rejectUnauthorized; + opts.requestTimeout = this.requestTimeout; + + // other options for Node.js client + opts.extraHeaders = this.extraHeaders; + + return new Request(opts); + }; + + /** + * Sends data. + * + * @param {String} data to send. + * @param {Function} called upon flush. + * @api private + */ + + XHR.prototype.doWrite = function (data, fn) { + var isBinary = typeof data !== 'string' && data !== undefined; + var req = this.request({ method: 'POST', data: data, isBinary: isBinary }); + var self = this; + req.on('success', fn); + req.on('error', function (err) { + self.onError('xhr post error', err); + }); + this.sendXhr = req; + }; + + /** + * Starts a poll cycle. + * + * @api private + */ + + XHR.prototype.doPoll = function () { + debug('xhr poll'); + var req = this.request(); + var self = this; + req.on('data', function (data) { + self.onData(data); + }); + req.on('error', function (err) { + self.onError('xhr poll error', err); + }); + this.pollXhr = req; + }; + + /** + * Request constructor + * + * @param {Object} options + * @api public + */ + + function Request(opts) { + this.method = opts.method || 'GET'; + this.uri = opts.uri; + this.xd = !!opts.xd; + this.xs = !!opts.xs; + this.async = false !== opts.async; + this.data = undefined !== opts.data ? opts.data : null; + this.agent = opts.agent; + this.isBinary = opts.isBinary; + this.supportsBinary = opts.supportsBinary; + this.enablesXDR = opts.enablesXDR; + this.requestTimeout = opts.requestTimeout; + + // SSL options for Node.js client + this.pfx = opts.pfx; + this.key = opts.key; + this.passphrase = opts.passphrase; + this.cert = opts.cert; + this.ca = opts.ca; + this.ciphers = opts.ciphers; + this.rejectUnauthorized = opts.rejectUnauthorized; + + // other options for Node.js client + this.extraHeaders = opts.extraHeaders; + + this.create(); + } + + /** + * Mix in `Emitter`. + */ + + Emitter(Request.prototype); + + /** + * Creates the XHR object and sends the request. + * + * @api private + */ + + Request.prototype.create = function () { + var opts = { agent: this.agent, xdomain: this.xd, xscheme: this.xs, enablesXDR: this.enablesXDR }; + + // SSL options for Node.js client + opts.pfx = this.pfx; + opts.key = this.key; + opts.passphrase = this.passphrase; + opts.cert = this.cert; + opts.ca = this.ca; + opts.ciphers = this.ciphers; + opts.rejectUnauthorized = this.rejectUnauthorized; + + var xhr = this.xhr = new XMLHttpRequest(opts); + var self = this; + + try { + debug('xhr open %s: %s', this.method, this.uri); + xhr.open(this.method, this.uri, this.async); + try { + if (this.extraHeaders) { + xhr.setDisableHeaderCheck && xhr.setDisableHeaderCheck(true); + for (var i in this.extraHeaders) { + if (this.extraHeaders.hasOwnProperty(i)) { + xhr.setRequestHeader(i, this.extraHeaders[i]); + } + } + } + } catch (e) {} + + if ('POST' === this.method) { + try { + if (this.isBinary) { + xhr.setRequestHeader('Content-type', 'application/octet-stream'); + } else { + xhr.setRequestHeader('Content-type', 'text/plain;charset=UTF-8'); + } + } catch (e) {} + } + + try { + xhr.setRequestHeader('Accept', '*/*'); + } catch (e) {} + + if (this.supportsBinary) { + xhr.responseType = 'arraybuffer'; + } + + // ie6 check + if ('withCredentials' in xhr) { + xhr.withCredentials = true; + } + + if (this.requestTimeout) { + xhr.timeout = this.requestTimeout; + } + + if (this.hasXDR()) { + xhr.onload = function () { + self.onLoad(); + }; + xhr.onerror = function () { + self.onError(xhr.responseText); + }; + } else { + xhr.onreadystatechange = function () { + if (xhr.readyState === 2) { + try { + var contentType = xhr.getResponseHeader('Content-Type'); + if (contentType !== 'application/octet-stream') { + xhr.responseType = 'text'; + } + } catch (e) {} + } + if (4 !== xhr.readyState) return; + if (200 === xhr.status || 1223 === xhr.status) { + self.onLoad(); + } else { + // make sure the `error` event handler that's user-set + // does not throw in the same tick and gets caught here + setTimeout(function () { + self.onError(xhr.status); + }, 0); + } + }; + } + + debug('xhr data %s', this.data); + xhr.send(this.data); + } catch (e) { + // Need to defer since .create() is called directly fhrom the constructor + // and thus the 'error' event can only be only bound *after* this exception + // occurs. Therefore, also, we cannot throw here at all. + setTimeout(function () { + self.onError(e); + }, 0); + return; + } + + if (global.document) { + this.index = Request.requestsCount++; + Request.requests[this.index] = this; + } + }; + + /** + * Called upon successful response. + * + * @api private + */ + + Request.prototype.onSuccess = function () { + this.emit('success'); + this.cleanup(); + }; + + /** + * Called if we have data. + * + * @api private + */ + + Request.prototype.onData = function (data) { + this.emit('data', data); + this.onSuccess(); + }; + + /** + * Called upon error. + * + * @api private + */ + + Request.prototype.onError = function (err) { + this.emit('error', err); + this.cleanup(true); + }; + + /** + * Cleans up house. + * + * @api private + */ + + Request.prototype.cleanup = function (fromError) { + if ('undefined' === typeof this.xhr || null === this.xhr) { + return; + } + // xmlhttprequest + if (this.hasXDR()) { + this.xhr.onload = this.xhr.onerror = empty; + } else { + this.xhr.onreadystatechange = empty; + } + + if (fromError) { + try { + this.xhr.abort(); + } catch (e) {} + } + + if (global.document) { + delete Request.requests[this.index]; + } + + this.xhr = null; + }; + + /** + * Called upon load. + * + * @api private + */ + + Request.prototype.onLoad = function () { + var data; + try { + var contentType; + try { + contentType = this.xhr.getResponseHeader('Content-Type'); + } catch (e) {} + if (contentType === 'application/octet-stream') { + if (this.xhr.responseType === 'arraybuffer') { + data = this.xhr.response || this.xhr.responseText; + } else { + data = String.fromCharCode.apply(null, new Uint8Array(this.xhr.response)); + } + } else { + data = this.xhr.responseText; + } + } catch (e) { + this.onError(e); + } + if (null != data) { + this.onData(data); + } + }; + + /** + * Check if it has XDomainRequest. + * + * @api private + */ + + Request.prototype.hasXDR = function () { + return 'undefined' !== typeof global.XDomainRequest && !this.xs && this.enablesXDR; + }; + + /** + * Aborts the request. + * + * @api public + */ + + Request.prototype.abort = function () { + this.cleanup(); + }; + + /** + * Aborts pending requests when unloading the window. This is needed to prevent + * memory leaks (e.g. when using IE) and to ensure that no spurious error is + * emitted. + */ + + Request.requestsCount = 0; + Request.requests = {}; + + if (global.document) { + if (global.attachEvent) { + global.attachEvent('onunload', unloadHandler); + } else if (global.addEventListener) { + global.addEventListener('beforeunload', unloadHandler, false); + } + } + + function unloadHandler() { + for (var i in Request.requests) { + if (Request.requests.hasOwnProperty(i)) { + Request.requests[i].abort(); + } + } + } + /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) + +/***/ }, +/* 6 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + /** + * Module dependencies. + */ + + var Transport = __webpack_require__(7); + var parseqs = __webpack_require__(19); + var parser = __webpack_require__(8); + var inherit = __webpack_require__(20); + var yeast = __webpack_require__(21); + var debug = __webpack_require__(22)('engine.io-client:polling'); + + /** + * Module exports. + */ + + module.exports = Polling; + + /** + * Is XHR2 supported? + */ + + var hasXHR2 = function () { + var XMLHttpRequest = __webpack_require__(3); + var xhr = new XMLHttpRequest({ xdomain: false }); + return null != xhr.responseType; + }(); + + /** + * Polling interface. + * + * @param {Object} opts + * @api private + */ + + function Polling(opts) { + var forceBase64 = opts && opts.forceBase64; + if (!hasXHR2 || forceBase64) { + this.supportsBinary = false; + } + Transport.call(this, opts); + } + + /** + * Inherits from Transport. + */ + + inherit(Polling, Transport); + + /** + * Transport name. + */ + + Polling.prototype.name = 'polling'; + + /** + * Opens the socket (triggers polling). We write a PING message to determine + * when the transport is open. + * + * @api private + */ + + Polling.prototype.doOpen = function () { + this.poll(); + }; + + /** + * Pauses polling. + * + * @param {Function} callback upon buffers are flushed and transport is paused + * @api private + */ + + Polling.prototype.pause = function (onPause) { + var self = this; + + this.readyState = 'pausing'; + + function pause() { + debug('paused'); + self.readyState = 'paused'; + onPause(); + } + + if (this.polling || !this.writable) { + var total = 0; + + if (this.polling) { + debug('we are currently polling - waiting to pause'); + total++; + this.once('pollComplete', function () { + debug('pre-pause polling complete'); + --total || pause(); + }); + } + + if (!this.writable) { + debug('we are currently writing - waiting to pause'); + total++; + this.once('drain', function () { + debug('pre-pause writing complete'); + --total || pause(); + }); + } + } else { + pause(); + } + }; + + /** + * Starts polling cycle. + * + * @api public + */ + + Polling.prototype.poll = function () { + debug('polling'); + this.polling = true; + this.doPoll(); + this.emit('poll'); + }; + + /** + * Overloads onData to detect payloads. + * + * @api private + */ + + Polling.prototype.onData = function (data) { + var self = this; + debug('polling got data %s', data); + var callback = function callback(packet, index, total) { + // if its the first message we consider the transport open + if ('opening' === self.readyState) { + self.onOpen(); + } + + // if its a close packet, we close the ongoing requests + if ('close' === packet.type) { + self.onClose(); + return false; + } + + // otherwise bypass onData and handle the message + self.onPacket(packet); + }; + + // decode payload + parser.decodePayload(data, this.socket.binaryType, callback); + + // if an event did not trigger closing + if ('closed' !== this.readyState) { + // if we got data we're not polling + this.polling = false; + this.emit('pollComplete'); + + if ('open' === this.readyState) { + this.poll(); + } else { + debug('ignoring poll - transport state "%s"', this.readyState); + } + } + }; + + /** + * For polling, send a close packet. + * + * @api private + */ + + Polling.prototype.doClose = function () { + var self = this; + + function close() { + debug('writing close packet'); + self.write([{ type: 'close' }]); + } + + if ('open' === this.readyState) { + debug('transport open - closing'); + close(); + } else { + // in case we're trying to close while + // handshaking is in progress (GH-164) + debug('transport not open - deferring close'); + this.once('open', close); + } + }; + + /** + * Writes a packets payload. + * + * @param {Array} data packets + * @param {Function} drain callback + * @api private + */ + + Polling.prototype.write = function (packets) { + var self = this; + this.writable = false; + var callbackfn = function callbackfn() { + self.writable = true; + self.emit('drain'); + }; + + parser.encodePayload(packets, this.supportsBinary, function (data) { + self.doWrite(data, callbackfn); + }); + }; + + /** + * Generates uri for connection. + * + * @api private + */ + + Polling.prototype.uri = function () { + var query = this.query || {}; + var schema = this.secure ? 'https' : 'http'; + var port = ''; + + // cache busting is forced + if (false !== this.timestampRequests) { + query[this.timestampParam] = yeast(); + } + + if (!this.supportsBinary && !query.sid) { + query.b64 = 1; + } + + query = parseqs.encode(query); + + // avoid port if default for schema + if (this.port && ('https' === schema && Number(this.port) !== 443 || 'http' === schema && Number(this.port) !== 80)) { + port = ':' + this.port; + } + + // prepend ? to query + if (query.length) { + query = '?' + query; + } + + var ipv6 = this.hostname.indexOf(':') !== -1; + return schema + '://' + (ipv6 ? '[' + this.hostname + ']' : this.hostname) + port + this.path + query; + }; + +/***/ }, +/* 7 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + /** + * Module dependencies. + */ + + var parser = __webpack_require__(8); + var Emitter = __webpack_require__(18); + + /** + * Module exports. + */ + + module.exports = Transport; + + /** + * Transport abstract constructor. + * + * @param {Object} options. + * @api private + */ + + function Transport(opts) { + this.path = opts.path; + this.hostname = opts.hostname; + this.port = opts.port; + this.secure = opts.secure; + this.query = opts.query; + this.timestampParam = opts.timestampParam; + this.timestampRequests = opts.timestampRequests; + this.readyState = ''; + this.agent = opts.agent || false; + this.socket = opts.socket; + this.enablesXDR = opts.enablesXDR; + + // SSL options for Node.js client + this.pfx = opts.pfx; + this.key = opts.key; + this.passphrase = opts.passphrase; + this.cert = opts.cert; + this.ca = opts.ca; + this.ciphers = opts.ciphers; + this.rejectUnauthorized = opts.rejectUnauthorized; + this.forceNode = opts.forceNode; + + // other options for Node.js client + this.extraHeaders = opts.extraHeaders; + this.localAddress = opts.localAddress; + } + + /** + * Mix in `Emitter`. + */ + + Emitter(Transport.prototype); + + /** + * Emits an error. + * + * @param {String} str + * @return {Transport} for chaining + * @api public + */ + + Transport.prototype.onError = function (msg, desc) { + var err = new Error(msg); + err.type = 'TransportError'; + err.description = desc; + this.emit('error', err); + return this; + }; + + /** + * Opens the transport. + * + * @api public + */ + + Transport.prototype.open = function () { + if ('closed' === this.readyState || '' === this.readyState) { + this.readyState = 'opening'; + this.doOpen(); + } + + return this; + }; + + /** + * Closes the transport. + * + * @api private + */ + + Transport.prototype.close = function () { + if ('opening' === this.readyState || 'open' === this.readyState) { + this.doClose(); + this.onClose(); + } + + return this; + }; + + /** + * Sends multiple packets. + * + * @param {Array} packets + * @api private + */ + + Transport.prototype.send = function (packets) { + if ('open' === this.readyState) { + this.write(packets); + } else { + throw new Error('Transport not open'); + } + }; + + /** + * Called upon open + * + * @api private + */ + + Transport.prototype.onOpen = function () { + this.readyState = 'open'; + this.writable = true; + this.emit('open'); + }; + + /** + * Called with data. + * + * @param {String} data + * @api private + */ + + Transport.prototype.onData = function (data) { + var packet = parser.decodePacket(data, this.socket.binaryType); + this.onPacket(packet); + }; + + /** + * Called with a decoded packet. + */ + + Transport.prototype.onPacket = function (packet) { + this.emit('packet', packet); + }; + + /** + * Called upon close. + * + * @api private + */ + + Transport.prototype.onClose = function () { + this.readyState = 'closed'; + this.emit('close'); + }; + +/***/ }, +/* 8 */ +/***/ function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(global) {/** + * Module dependencies. + */ + + var keys = __webpack_require__(9); + var hasBinary = __webpack_require__(10); + var sliceBuffer = __webpack_require__(12); + var after = __webpack_require__(13); + var utf8 = __webpack_require__(14); + + var base64encoder; + if (global && global.ArrayBuffer) { + base64encoder = __webpack_require__(16); + } + + /** + * Check if we are running an android browser. That requires us to use + * ArrayBuffer with polling transports... + * + * http://ghinda.net/jpeg-blob-ajax-android/ + */ + + var isAndroid = typeof navigator !== 'undefined' && /Android/i.test(navigator.userAgent); + + /** + * Check if we are running in PhantomJS. + * Uploading a Blob with PhantomJS does not work correctly, as reported here: + * https://github.com/ariya/phantomjs/issues/11395 + * @type boolean + */ + var isPhantomJS = typeof navigator !== 'undefined' && /PhantomJS/i.test(navigator.userAgent); + + /** + * When true, avoids using Blobs to encode payloads. + * @type boolean + */ + var dontSendBlobs = isAndroid || isPhantomJS; + + /** + * Current protocol version. + */ + + exports.protocol = 3; + + /** + * Packet types. + */ + + var packets = exports.packets = { + open: 0 // non-ws + , close: 1 // non-ws + , ping: 2 + , pong: 3 + , message: 4 + , upgrade: 5 + , noop: 6 + }; + + var packetslist = keys(packets); + + /** + * Premade error packet. + */ + + var err = { type: 'error', data: 'parser error' }; + + /** + * Create a blob api even for blob builder when vendor prefixes exist + */ + + var Blob = __webpack_require__(17); + + /** + * Encodes a packet. + * + * [ ] + * + * Example: + * + * 5hello world + * 3 + * 4 + * + * Binary is encoded in an identical principle + * + * @api private + */ + + exports.encodePacket = function (packet, supportsBinary, utf8encode, callback) { + if (typeof supportsBinary === 'function') { + callback = supportsBinary; + supportsBinary = false; + } + + if (typeof utf8encode === 'function') { + callback = utf8encode; + utf8encode = null; + } + + var data = (packet.data === undefined) + ? undefined + : packet.data.buffer || packet.data; + + if (global.ArrayBuffer && data instanceof ArrayBuffer) { + return encodeArrayBuffer(packet, supportsBinary, callback); + } else if (Blob && data instanceof global.Blob) { + return encodeBlob(packet, supportsBinary, callback); + } + + // might be an object with { base64: true, data: dataAsBase64String } + if (data && data.base64) { + return encodeBase64Object(packet, callback); + } + + // Sending data as a utf-8 string + var encoded = packets[packet.type]; + + // data fragment is optional + if (undefined !== packet.data) { + encoded += utf8encode ? utf8.encode(String(packet.data), { strict: false }) : String(packet.data); + } + + return callback('' + encoded); + + }; + + function encodeBase64Object(packet, callback) { + // packet data is an object { base64: true, data: dataAsBase64String } + var message = 'b' + exports.packets[packet.type] + packet.data.data; + return callback(message); + } + + /** + * Encode packet helpers for binary types + */ + + function encodeArrayBuffer(packet, supportsBinary, callback) { + if (!supportsBinary) { + return exports.encodeBase64Packet(packet, callback); + } + + var data = packet.data; + var contentArray = new Uint8Array(data); + var resultBuffer = new Uint8Array(1 + data.byteLength); + + resultBuffer[0] = packets[packet.type]; + for (var i = 0; i < contentArray.length; i++) { + resultBuffer[i+1] = contentArray[i]; + } + + return callback(resultBuffer.buffer); + } + + function encodeBlobAsArrayBuffer(packet, supportsBinary, callback) { + if (!supportsBinary) { + return exports.encodeBase64Packet(packet, callback); + } + + var fr = new FileReader(); + fr.onload = function() { + packet.data = fr.result; + exports.encodePacket(packet, supportsBinary, true, callback); + }; + return fr.readAsArrayBuffer(packet.data); + } + + function encodeBlob(packet, supportsBinary, callback) { + if (!supportsBinary) { + return exports.encodeBase64Packet(packet, callback); + } + + if (dontSendBlobs) { + return encodeBlobAsArrayBuffer(packet, supportsBinary, callback); + } + + var length = new Uint8Array(1); + length[0] = packets[packet.type]; + var blob = new Blob([length.buffer, packet.data]); + + return callback(blob); + } + + /** + * Encodes a packet with binary data in a base64 string + * + * @param {Object} packet, has `type` and `data` + * @return {String} base64 encoded message + */ + + exports.encodeBase64Packet = function(packet, callback) { + var message = 'b' + exports.packets[packet.type]; + if (Blob && packet.data instanceof global.Blob) { + var fr = new FileReader(); + fr.onload = function() { + var b64 = fr.result.split(',')[1]; + callback(message + b64); + }; + return fr.readAsDataURL(packet.data); + } + + var b64data; + try { + b64data = String.fromCharCode.apply(null, new Uint8Array(packet.data)); + } catch (e) { + // iPhone Safari doesn't let you apply with typed arrays + var typed = new Uint8Array(packet.data); + var basic = new Array(typed.length); + for (var i = 0; i < typed.length; i++) { + basic[i] = typed[i]; + } + b64data = String.fromCharCode.apply(null, basic); + } + message += global.btoa(b64data); + return callback(message); + }; + + /** + * Decodes a packet. Changes format to Blob if requested. + * + * @return {Object} with `type` and `data` (if any) + * @api private + */ + + exports.decodePacket = function (data, binaryType, utf8decode) { + if (data === undefined) { + return err; + } + // String data + if (typeof data === 'string') { + if (data.charAt(0) === 'b') { + return exports.decodeBase64Packet(data.substr(1), binaryType); + } + + if (utf8decode) { + data = tryDecode(data); + if (data === false) { + return err; + } + } + var type = data.charAt(0); + + if (Number(type) != type || !packetslist[type]) { + return err; + } + + if (data.length > 1) { + return { type: packetslist[type], data: data.substring(1) }; + } else { + return { type: packetslist[type] }; + } + } + + var asArray = new Uint8Array(data); + var type = asArray[0]; + var rest = sliceBuffer(data, 1); + if (Blob && binaryType === 'blob') { + rest = new Blob([rest]); + } + return { type: packetslist[type], data: rest }; + }; + + function tryDecode(data) { + try { + data = utf8.decode(data, { strict: false }); + } catch (e) { + return false; + } + return data; + } + + /** + * Decodes a packet encoded in a base64 string + * + * @param {String} base64 encoded message + * @return {Object} with `type` and `data` (if any) + */ + + exports.decodeBase64Packet = function(msg, binaryType) { + var type = packetslist[msg.charAt(0)]; + if (!base64encoder) { + return { type: type, data: { base64: true, data: msg.substr(1) } }; + } + + var data = base64encoder.decode(msg.substr(1)); + + if (binaryType === 'blob' && Blob) { + data = new Blob([data]); + } + + return { type: type, data: data }; + }; + + /** + * Encodes multiple messages (payload). + * + * :data + * + * Example: + * + * 11:hello world2:hi + * + * If any contents are binary, they will be encoded as base64 strings. Base64 + * encoded strings are marked with a b before the length specifier + * + * @param {Array} packets + * @api private + */ + + exports.encodePayload = function (packets, supportsBinary, callback) { + if (typeof supportsBinary === 'function') { + callback = supportsBinary; + supportsBinary = null; + } + + var isBinary = hasBinary(packets); + + if (supportsBinary && isBinary) { + if (Blob && !dontSendBlobs) { + return exports.encodePayloadAsBlob(packets, callback); + } + + return exports.encodePayloadAsArrayBuffer(packets, callback); + } + + if (!packets.length) { + return callback('0:'); + } + + function setLengthHeader(message) { + return message.length + ':' + message; + } + + function encodeOne(packet, doneCallback) { + exports.encodePacket(packet, !isBinary ? false : supportsBinary, false, function(message) { + doneCallback(null, setLengthHeader(message)); + }); + } + + map(packets, encodeOne, function(err, results) { + return callback(results.join('')); + }); + }; + + /** + * Async array map using after + */ + + function map(ary, each, done) { + var result = new Array(ary.length); + var next = after(ary.length, done); + + var eachWithIndex = function(i, el, cb) { + each(el, function(error, msg) { + result[i] = msg; + cb(error, result); + }); + }; + + for (var i = 0; i < ary.length; i++) { + eachWithIndex(i, ary[i], next); + } + } + + /* + * Decodes data when a payload is maybe expected. Possible binary contents are + * decoded from their base64 representation + * + * @param {String} data, callback method + * @api public + */ + + exports.decodePayload = function (data, binaryType, callback) { + if (typeof data !== 'string') { + return exports.decodePayloadAsBinary(data, binaryType, callback); + } + + if (typeof binaryType === 'function') { + callback = binaryType; + binaryType = null; + } + + var packet; + if (data === '') { + // parser error - ignoring payload + return callback(err, 0, 1); + } + + var length = '', n, msg; + + for (var i = 0, l = data.length; i < l; i++) { + var chr = data.charAt(i); + + if (chr !== ':') { + length += chr; + continue; + } + + if (length === '' || (length != (n = Number(length)))) { + // parser error - ignoring payload + return callback(err, 0, 1); + } + + msg = data.substr(i + 1, n); + + if (length != msg.length) { + // parser error - ignoring payload + return callback(err, 0, 1); + } + + if (msg.length) { + packet = exports.decodePacket(msg, binaryType, false); + + if (err.type === packet.type && err.data === packet.data) { + // parser error in individual packet - ignoring payload + return callback(err, 0, 1); + } + + var ret = callback(packet, i + n, l); + if (false === ret) return; + } + + // advance cursor + i += n; + length = ''; + } + + if (length !== '') { + // parser error - ignoring payload + return callback(err, 0, 1); + } + + }; + + /** + * Encodes multiple messages (payload) as binary. + * + * <1 = binary, 0 = string>[...] + * + * Example: + * 1 3 255 1 2 3, if the binary contents are interpreted as 8 bit integers + * + * @param {Array} packets + * @return {ArrayBuffer} encoded payload + * @api private + */ + + exports.encodePayloadAsArrayBuffer = function(packets, callback) { + if (!packets.length) { + return callback(new ArrayBuffer(0)); + } + + function encodeOne(packet, doneCallback) { + exports.encodePacket(packet, true, true, function(data) { + return doneCallback(null, data); + }); + } + + map(packets, encodeOne, function(err, encodedPackets) { + var totalLength = encodedPackets.reduce(function(acc, p) { + var len; + if (typeof p === 'string'){ + len = p.length; + } else { + len = p.byteLength; + } + return acc + len.toString().length + len + 2; // string/binary identifier + separator = 2 + }, 0); + + var resultArray = new Uint8Array(totalLength); + + var bufferIndex = 0; + encodedPackets.forEach(function(p) { + var isString = typeof p === 'string'; + var ab = p; + if (isString) { + var view = new Uint8Array(p.length); + for (var i = 0; i < p.length; i++) { + view[i] = p.charCodeAt(i); + } + ab = view.buffer; + } + + if (isString) { // not true binary + resultArray[bufferIndex++] = 0; + } else { // true binary + resultArray[bufferIndex++] = 1; + } + + var lenStr = ab.byteLength.toString(); + for (var i = 0; i < lenStr.length; i++) { + resultArray[bufferIndex++] = parseInt(lenStr[i]); + } + resultArray[bufferIndex++] = 255; + + var view = new Uint8Array(ab); + for (var i = 0; i < view.length; i++) { + resultArray[bufferIndex++] = view[i]; + } + }); + + return callback(resultArray.buffer); + }); + }; + + /** + * Encode as Blob + */ + + exports.encodePayloadAsBlob = function(packets, callback) { + function encodeOne(packet, doneCallback) { + exports.encodePacket(packet, true, true, function(encoded) { + var binaryIdentifier = new Uint8Array(1); + binaryIdentifier[0] = 1; + if (typeof encoded === 'string') { + var view = new Uint8Array(encoded.length); + for (var i = 0; i < encoded.length; i++) { + view[i] = encoded.charCodeAt(i); + } + encoded = view.buffer; + binaryIdentifier[0] = 0; + } + + var len = (encoded instanceof ArrayBuffer) + ? encoded.byteLength + : encoded.size; + + var lenStr = len.toString(); + var lengthAry = new Uint8Array(lenStr.length + 1); + for (var i = 0; i < lenStr.length; i++) { + lengthAry[i] = parseInt(lenStr[i]); + } + lengthAry[lenStr.length] = 255; + + if (Blob) { + var blob = new Blob([binaryIdentifier.buffer, lengthAry.buffer, encoded]); + doneCallback(null, blob); + } + }); + } + + map(packets, encodeOne, function(err, results) { + return callback(new Blob(results)); + }); + }; + + /* + * Decodes data when a payload is maybe expected. Strings are decoded by + * interpreting each byte as a key code for entries marked to start with 0. See + * description of encodePayloadAsBinary + * + * @param {ArrayBuffer} data, callback method + * @api public + */ + + exports.decodePayloadAsBinary = function (data, binaryType, callback) { + if (typeof binaryType === 'function') { + callback = binaryType; + binaryType = null; + } + + var bufferTail = data; + var buffers = []; + + while (bufferTail.byteLength > 0) { + var tailArray = new Uint8Array(bufferTail); + var isString = tailArray[0] === 0; + var msgLength = ''; + + for (var i = 1; ; i++) { + if (tailArray[i] === 255) break; + + // 310 = char length of Number.MAX_VALUE + if (msgLength.length > 310) { + return callback(err, 0, 1); + } + + msgLength += tailArray[i]; + } + + bufferTail = sliceBuffer(bufferTail, 2 + msgLength.length); + msgLength = parseInt(msgLength); + + var msg = sliceBuffer(bufferTail, 0, msgLength); + if (isString) { + try { + msg = String.fromCharCode.apply(null, new Uint8Array(msg)); + } catch (e) { + // iPhone Safari doesn't let you apply to typed arrays + var typed = new Uint8Array(msg); + msg = ''; + for (var i = 0; i < typed.length; i++) { + msg += String.fromCharCode(typed[i]); + } + } + } + + buffers.push(msg); + bufferTail = sliceBuffer(bufferTail, msgLength); + } + + var total = buffers.length; + buffers.forEach(function(buffer, i) { + callback(exports.decodePacket(buffer, binaryType, true), i, total); + }); + }; + + /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) + +/***/ }, +/* 9 */ +/***/ function(module, exports) { + + + /** + * Gets the keys for an object. + * + * @return {Array} keys + * @api private + */ + + module.exports = Object.keys || function keys (obj){ + var arr = []; + var has = Object.prototype.hasOwnProperty; + + for (var i in obj) { + if (has.call(obj, i)) { + arr.push(i); + } + } + return arr; + }; + + +/***/ }, +/* 10 */ +/***/ function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(global) {/* global Blob File */ + + /* + * Module requirements. + */ + + var isArray = __webpack_require__(11); + + var toString = Object.prototype.toString; + var withNativeBlob = typeof global.Blob === 'function' || toString.call(global.Blob) === '[object BlobConstructor]'; + var withNativeFile = typeof global.File === 'function' || toString.call(global.File) === '[object FileConstructor]'; + + /** + * Module exports. + */ + + module.exports = hasBinary; + + /** + * Checks for binary data. + * + * Supports Buffer, ArrayBuffer, Blob and File. + * + * @param {Object} anything + * @api public + */ + + function hasBinary (obj) { + if (!obj || typeof obj !== 'object') { + return false; + } + + if (isArray(obj)) { + for (var i = 0, l = obj.length; i < l; i++) { + if (hasBinary(obj[i])) { + return true; + } + } + return false; + } + + if ((typeof global.Buffer === 'function' && global.Buffer.isBuffer && global.Buffer.isBuffer(obj)) || + (typeof global.ArrayBuffer === 'function' && obj instanceof ArrayBuffer) || + (withNativeBlob && obj instanceof Blob) || + (withNativeFile && obj instanceof File) + ) { + return true; + } + + // see: https://github.com/Automattic/has-binary/pull/4 + if (obj.toJSON && typeof obj.toJSON === 'function' && arguments.length === 1) { + return hasBinary(obj.toJSON(), true); + } + + for (var key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key) && hasBinary(obj[key])) { + return true; + } + } + + return false; + } + + /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) + +/***/ }, +/* 11 */ +/***/ function(module, exports) { + + var toString = {}.toString; + + module.exports = Array.isArray || function (arr) { + return toString.call(arr) == '[object Array]'; + }; + + +/***/ }, +/* 12 */ +/***/ function(module, exports) { + + /** + * An abstraction for slicing an arraybuffer even when + * ArrayBuffer.prototype.slice is not supported + * + * @api public + */ + + module.exports = function(arraybuffer, start, end) { + var bytes = arraybuffer.byteLength; + start = start || 0; + end = end || bytes; + + if (arraybuffer.slice) { return arraybuffer.slice(start, end); } + + if (start < 0) { start += bytes; } + if (end < 0) { end += bytes; } + if (end > bytes) { end = bytes; } + + if (start >= bytes || start >= end || bytes === 0) { + return new ArrayBuffer(0); + } + + var abv = new Uint8Array(arraybuffer); + var result = new Uint8Array(end - start); + for (var i = start, ii = 0; i < end; i++, ii++) { + result[ii] = abv[i]; + } + return result.buffer; + }; + + +/***/ }, +/* 13 */ +/***/ function(module, exports) { + + module.exports = after + + function after(count, callback, err_cb) { + var bail = false + err_cb = err_cb || noop + proxy.count = count + + return (count === 0) ? callback() : proxy + + function proxy(err, result) { + if (proxy.count <= 0) { + throw new Error('after called too many times') + } + --proxy.count + + // after first error, rest are passed to err_cb + if (err) { + bail = true + callback(err) + // future error callbacks will go to error handler + callback = err_cb + } else if (proxy.count === 0 && !bail) { + callback(null, result) + } + } + } + + function noop() {} + + +/***/ }, +/* 14 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/*! https://mths.be/utf8js v2.1.2 by @mathias */ + ;(function(root) { + + // Detect free variables `exports` + var freeExports = typeof exports == 'object' && exports; + + // Detect free variable `module` + var freeModule = typeof module == 'object' && module && + module.exports == freeExports && module; + + // Detect free variable `global`, from Node.js or Browserified code, + // and use it as `root` + var freeGlobal = typeof global == 'object' && global; + if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) { + root = freeGlobal; + } + + /*--------------------------------------------------------------------------*/ + + var stringFromCharCode = String.fromCharCode; + + // Taken from https://mths.be/punycode + function ucs2decode(string) { + var output = []; + var counter = 0; + var length = string.length; + var value; + var extra; + while (counter < length) { + value = string.charCodeAt(counter++); + if (value >= 0xD800 && value <= 0xDBFF && counter < length) { + // high surrogate, and there is a next character + extra = string.charCodeAt(counter++); + if ((extra & 0xFC00) == 0xDC00) { // low surrogate + output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); + } else { + // unmatched surrogate; only append this code unit, in case the next + // code unit is the high surrogate of a surrogate pair + output.push(value); + counter--; + } + } else { + output.push(value); + } + } + return output; + } + + // Taken from https://mths.be/punycode + function ucs2encode(array) { + var length = array.length; + var index = -1; + var value; + var output = ''; + while (++index < length) { + value = array[index]; + if (value > 0xFFFF) { + value -= 0x10000; + output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); + value = 0xDC00 | value & 0x3FF; + } + output += stringFromCharCode(value); + } + return output; + } + + function checkScalarValue(codePoint, strict) { + if (codePoint >= 0xD800 && codePoint <= 0xDFFF) { + if (strict) { + throw Error( + 'Lone surrogate U+' + codePoint.toString(16).toUpperCase() + + ' is not a scalar value' + ); + } + return false; + } + return true; + } + /*--------------------------------------------------------------------------*/ + + function createByte(codePoint, shift) { + return stringFromCharCode(((codePoint >> shift) & 0x3F) | 0x80); + } + + function encodeCodePoint(codePoint, strict) { + if ((codePoint & 0xFFFFFF80) == 0) { // 1-byte sequence + return stringFromCharCode(codePoint); + } + var symbol = ''; + if ((codePoint & 0xFFFFF800) == 0) { // 2-byte sequence + symbol = stringFromCharCode(((codePoint >> 6) & 0x1F) | 0xC0); + } + else if ((codePoint & 0xFFFF0000) == 0) { // 3-byte sequence + if (!checkScalarValue(codePoint, strict)) { + codePoint = 0xFFFD; + } + symbol = stringFromCharCode(((codePoint >> 12) & 0x0F) | 0xE0); + symbol += createByte(codePoint, 6); + } + else if ((codePoint & 0xFFE00000) == 0) { // 4-byte sequence + symbol = stringFromCharCode(((codePoint >> 18) & 0x07) | 0xF0); + symbol += createByte(codePoint, 12); + symbol += createByte(codePoint, 6); + } + symbol += stringFromCharCode((codePoint & 0x3F) | 0x80); + return symbol; + } + + function utf8encode(string, opts) { + opts = opts || {}; + var strict = false !== opts.strict; + + var codePoints = ucs2decode(string); + var length = codePoints.length; + var index = -1; + var codePoint; + var byteString = ''; + while (++index < length) { + codePoint = codePoints[index]; + byteString += encodeCodePoint(codePoint, strict); + } + return byteString; + } + + /*--------------------------------------------------------------------------*/ + + function readContinuationByte() { + if (byteIndex >= byteCount) { + throw Error('Invalid byte index'); + } + + var continuationByte = byteArray[byteIndex] & 0xFF; + byteIndex++; + + if ((continuationByte & 0xC0) == 0x80) { + return continuationByte & 0x3F; + } + + // If we end up here, it’s not a continuation byte + throw Error('Invalid continuation byte'); + } + + function decodeSymbol(strict) { + var byte1; + var byte2; + var byte3; + var byte4; + var codePoint; + + if (byteIndex > byteCount) { + throw Error('Invalid byte index'); + } + + if (byteIndex == byteCount) { + return false; + } + + // Read first byte + byte1 = byteArray[byteIndex] & 0xFF; + byteIndex++; + + // 1-byte sequence (no continuation bytes) + if ((byte1 & 0x80) == 0) { + return byte1; + } + + // 2-byte sequence + if ((byte1 & 0xE0) == 0xC0) { + byte2 = readContinuationByte(); + codePoint = ((byte1 & 0x1F) << 6) | byte2; + if (codePoint >= 0x80) { + return codePoint; + } else { + throw Error('Invalid continuation byte'); + } + } + + // 3-byte sequence (may include unpaired surrogates) + if ((byte1 & 0xF0) == 0xE0) { + byte2 = readContinuationByte(); + byte3 = readContinuationByte(); + codePoint = ((byte1 & 0x0F) << 12) | (byte2 << 6) | byte3; + if (codePoint >= 0x0800) { + return checkScalarValue(codePoint, strict) ? codePoint : 0xFFFD; + } else { + throw Error('Invalid continuation byte'); + } + } + + // 4-byte sequence + if ((byte1 & 0xF8) == 0xF0) { + byte2 = readContinuationByte(); + byte3 = readContinuationByte(); + byte4 = readContinuationByte(); + codePoint = ((byte1 & 0x07) << 0x12) | (byte2 << 0x0C) | + (byte3 << 0x06) | byte4; + if (codePoint >= 0x010000 && codePoint <= 0x10FFFF) { + return codePoint; + } + } + + throw Error('Invalid UTF-8 detected'); + } + + var byteArray; + var byteCount; + var byteIndex; + function utf8decode(byteString, opts) { + opts = opts || {}; + var strict = false !== opts.strict; + + byteArray = ucs2decode(byteString); + byteCount = byteArray.length; + byteIndex = 0; + var codePoints = []; + var tmp; + while ((tmp = decodeSymbol(strict)) !== false) { + codePoints.push(tmp); + } + return ucs2encode(codePoints); + } + + /*--------------------------------------------------------------------------*/ + + var utf8 = { + 'version': '2.1.2', + 'encode': utf8encode, + 'decode': utf8decode + }; + + // Some AMD build optimizers, like r.js, check for specific condition patterns + // like the following: + if ( + true + ) { + !(__WEBPACK_AMD_DEFINE_RESULT__ = function() { + return utf8; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + } else if (freeExports && !freeExports.nodeType) { + if (freeModule) { // in Node.js or RingoJS v0.8.0+ + freeModule.exports = utf8; + } else { // in Narwhal or RingoJS v0.7.0- + var object = {}; + var hasOwnProperty = object.hasOwnProperty; + for (var key in utf8) { + hasOwnProperty.call(utf8, key) && (freeExports[key] = utf8[key]); + } + } + } else { // in Rhino or a web browser + root.utf8 = utf8; + } + + }(this)); + + /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(15)(module), (function() { return this; }()))) + +/***/ }, +/* 15 */ +/***/ function(module, exports) { + + module.exports = function(module) { + if(!module.webpackPolyfill) { + module.deprecate = function() {}; + module.paths = []; + // module.parent = undefined by default + module.children = []; + module.webpackPolyfill = 1; + } + return module; + } + + +/***/ }, +/* 16 */ +/***/ function(module, exports) { + + /* + * base64-arraybuffer + * https://github.com/niklasvh/base64-arraybuffer + * + * Copyright (c) 2012 Niklas von Hertzen + * Licensed under the MIT license. + */ + (function(){ + "use strict"; + + var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + // Use a lookup table to find the index. + var lookup = new Uint8Array(256); + for (var i = 0; i < chars.length; i++) { + lookup[chars.charCodeAt(i)] = i; + } + + exports.encode = function(arraybuffer) { + var bytes = new Uint8Array(arraybuffer), + i, len = bytes.length, base64 = ""; + + for (i = 0; i < len; i+=3) { + base64 += chars[bytes[i] >> 2]; + base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)]; + base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)]; + base64 += chars[bytes[i + 2] & 63]; + } + + if ((len % 3) === 2) { + base64 = base64.substring(0, base64.length - 1) + "="; + } else if (len % 3 === 1) { + base64 = base64.substring(0, base64.length - 2) + "=="; + } + + return base64; + }; + + exports.decode = function(base64) { + var bufferLength = base64.length * 0.75, + len = base64.length, i, p = 0, + encoded1, encoded2, encoded3, encoded4; + + if (base64[base64.length - 1] === "=") { + bufferLength--; + if (base64[base64.length - 2] === "=") { + bufferLength--; + } + } + + var arraybuffer = new ArrayBuffer(bufferLength), + bytes = new Uint8Array(arraybuffer); + + for (i = 0; i < len; i+=4) { + encoded1 = lookup[base64.charCodeAt(i)]; + encoded2 = lookup[base64.charCodeAt(i+1)]; + encoded3 = lookup[base64.charCodeAt(i+2)]; + encoded4 = lookup[base64.charCodeAt(i+3)]; + + bytes[p++] = (encoded1 << 2) | (encoded2 >> 4); + bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2); + bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63); + } + + return arraybuffer; + }; + })(); + + +/***/ }, +/* 17 */ +/***/ function(module, exports) { + + /* WEBPACK VAR INJECTION */(function(global) {/** + * Create a blob builder even when vendor prefixes exist + */ + + var BlobBuilder = global.BlobBuilder + || global.WebKitBlobBuilder + || global.MSBlobBuilder + || global.MozBlobBuilder; + + /** + * Check if Blob constructor is supported + */ + + var blobSupported = (function() { + try { + var a = new Blob(['hi']); + return a.size === 2; + } catch(e) { + return false; + } + })(); + + /** + * Check if Blob constructor supports ArrayBufferViews + * Fails in Safari 6, so we need to map to ArrayBuffers there. + */ + + var blobSupportsArrayBufferView = blobSupported && (function() { + try { + var b = new Blob([new Uint8Array([1,2])]); + return b.size === 2; + } catch(e) { + return false; + } + })(); + + /** + * Check if BlobBuilder is supported + */ + + var blobBuilderSupported = BlobBuilder + && BlobBuilder.prototype.append + && BlobBuilder.prototype.getBlob; + + /** + * Helper function that maps ArrayBufferViews to ArrayBuffers + * Used by BlobBuilder constructor and old browsers that didn't + * support it in the Blob constructor. + */ + + function mapArrayBufferViews(ary) { + for (var i = 0; i < ary.length; i++) { + var chunk = ary[i]; + if (chunk.buffer instanceof ArrayBuffer) { + var buf = chunk.buffer; + + // if this is a subarray, make a copy so we only + // include the subarray region from the underlying buffer + if (chunk.byteLength !== buf.byteLength) { + var copy = new Uint8Array(chunk.byteLength); + copy.set(new Uint8Array(buf, chunk.byteOffset, chunk.byteLength)); + buf = copy.buffer; + } + + ary[i] = buf; + } + } + } + + function BlobBuilderConstructor(ary, options) { + options = options || {}; + + var bb = new BlobBuilder(); + mapArrayBufferViews(ary); + + for (var i = 0; i < ary.length; i++) { + bb.append(ary[i]); + } + + return (options.type) ? bb.getBlob(options.type) : bb.getBlob(); + }; + + function BlobConstructor(ary, options) { + mapArrayBufferViews(ary); + return new Blob(ary, options || {}); + }; + + module.exports = (function() { + if (blobSupported) { + return blobSupportsArrayBufferView ? global.Blob : BlobConstructor; + } else if (blobBuilderSupported) { + return BlobBuilderConstructor; + } else { + return undefined; + } + })(); + + /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) + +/***/ }, +/* 18 */ +/***/ function(module, exports, __webpack_require__) { + + + /** + * Expose `Emitter`. + */ + + if (true) { + module.exports = Emitter; + } + + /** + * Initialize a new `Emitter`. + * + * @api public + */ + + function Emitter(obj) { + if (obj) return mixin(obj); + }; + + /** + * Mixin the emitter properties. + * + * @param {Object} obj + * @return {Object} + * @api private + */ + + function mixin(obj) { + for (var key in Emitter.prototype) { + obj[key] = Emitter.prototype[key]; + } + return obj; + } + + /** + * Listen on the given `event` with `fn`. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + + Emitter.prototype.on = + Emitter.prototype.addEventListener = function(event, fn){ + this._callbacks = this._callbacks || {}; + (this._callbacks['$' + event] = this._callbacks['$' + event] || []) + .push(fn); + return this; + }; + + /** + * Adds an `event` listener that will be invoked a single + * time then automatically removed. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + + Emitter.prototype.once = function(event, fn){ + function on() { + this.off(event, on); + fn.apply(this, arguments); + } + + on.fn = fn; + this.on(event, on); + return this; + }; + + /** + * Remove the given callback for `event` or all + * registered callbacks. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + + Emitter.prototype.off = + Emitter.prototype.removeListener = + Emitter.prototype.removeAllListeners = + Emitter.prototype.removeEventListener = function(event, fn){ + this._callbacks = this._callbacks || {}; + + // all + if (0 == arguments.length) { + this._callbacks = {}; + return this; + } + + // specific event + var callbacks = this._callbacks['$' + event]; + if (!callbacks) return this; + + // remove all handlers + if (1 == arguments.length) { + delete this._callbacks['$' + event]; + return this; + } + + // remove specific handler + var cb; + for (var i = 0; i < callbacks.length; i++) { + cb = callbacks[i]; + if (cb === fn || cb.fn === fn) { + callbacks.splice(i, 1); + break; + } + } + return this; + }; + + /** + * Emit `event` with the given args. + * + * @param {String} event + * @param {Mixed} ... + * @return {Emitter} + */ + + Emitter.prototype.emit = function(event){ + this._callbacks = this._callbacks || {}; + var args = [].slice.call(arguments, 1) + , callbacks = this._callbacks['$' + event]; + + if (callbacks) { + callbacks = callbacks.slice(0); + for (var i = 0, len = callbacks.length; i < len; ++i) { + callbacks[i].apply(this, args); + } + } + + return this; + }; + + /** + * Return array of callbacks for `event`. + * + * @param {String} event + * @return {Array} + * @api public + */ + + Emitter.prototype.listeners = function(event){ + this._callbacks = this._callbacks || {}; + return this._callbacks['$' + event] || []; + }; + + /** + * Check if this emitter has `event` handlers. + * + * @param {String} event + * @return {Boolean} + * @api public + */ + + Emitter.prototype.hasListeners = function(event){ + return !! this.listeners(event).length; + }; + + +/***/ }, +/* 19 */ +/***/ function(module, exports) { + + /** + * Compiles a querystring + * Returns string representation of the object + * + * @param {Object} + * @api private + */ + + exports.encode = function (obj) { + var str = ''; + + for (var i in obj) { + if (obj.hasOwnProperty(i)) { + if (str.length) str += '&'; + str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]); + } + } + + return str; + }; + + /** + * Parses a simple querystring into an object + * + * @param {String} qs + * @api private + */ + + exports.decode = function(qs){ + var qry = {}; + var pairs = qs.split('&'); + for (var i = 0, l = pairs.length; i < l; i++) { + var pair = pairs[i].split('='); + qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]); + } + return qry; + }; + + +/***/ }, +/* 20 */ +/***/ function(module, exports) { + + + module.exports = function(a, b){ + var fn = function(){}; + fn.prototype = b.prototype; + a.prototype = new fn; + a.prototype.constructor = a; + }; + +/***/ }, +/* 21 */ +/***/ function(module, exports) { + + 'use strict'; + + var alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_'.split('') + , length = 64 + , map = {} + , seed = 0 + , i = 0 + , prev; + + /** + * Return a string representing the specified number. + * + * @param {Number} num The number to convert. + * @returns {String} The string representation of the number. + * @api public + */ + function encode(num) { + var encoded = ''; + + do { + encoded = alphabet[num % length] + encoded; + num = Math.floor(num / length); + } while (num > 0); + + return encoded; + } + + /** + * Return the integer value specified by the given string. + * + * @param {String} str The string to convert. + * @returns {Number} The integer value represented by the string. + * @api public + */ + function decode(str) { + var decoded = 0; + + for (i = 0; i < str.length; i++) { + decoded = decoded * length + map[str.charAt(i)]; + } + + return decoded; + } + + /** + * Yeast: A tiny growing id generator. + * + * @returns {String} A unique id. + * @api public + */ + function yeast() { + var now = encode(+new Date()); + + if (now !== prev) return seed = 0, prev = now; + return now +'.'+ encode(seed++); + } + + // + // Map each character to its index. + // + for (; i < length; i++) map[alphabet[i]] = i; + + // + // Expose the `yeast`, `encode` and `decode` functions. + // + yeast.encode = encode; + yeast.decode = decode; + module.exports = yeast; + + +/***/ }, +/* 22 */ +/***/ function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(process) {/** + * This is the web browser implementation of `debug()`. + * + * Expose `debug()` as the module. + */ + + exports = module.exports = __webpack_require__(24); + exports.log = log; + exports.formatArgs = formatArgs; + exports.save = save; + exports.load = load; + exports.useColors = useColors; + exports.storage = 'undefined' != typeof chrome + && 'undefined' != typeof chrome.storage + ? chrome.storage.local + : localstorage(); + + /** + * Colors. + */ + + exports.colors = [ + '#0000CC', '#0000FF', '#0033CC', '#0033FF', '#0066CC', '#0066FF', '#0099CC', + '#0099FF', '#00CC00', '#00CC33', '#00CC66', '#00CC99', '#00CCCC', '#00CCFF', + '#3300CC', '#3300FF', '#3333CC', '#3333FF', '#3366CC', '#3366FF', '#3399CC', + '#3399FF', '#33CC00', '#33CC33', '#33CC66', '#33CC99', '#33CCCC', '#33CCFF', + '#6600CC', '#6600FF', '#6633CC', '#6633FF', '#66CC00', '#66CC33', '#9900CC', + '#9900FF', '#9933CC', '#9933FF', '#99CC00', '#99CC33', '#CC0000', '#CC0033', + '#CC0066', '#CC0099', '#CC00CC', '#CC00FF', '#CC3300', '#CC3333', '#CC3366', + '#CC3399', '#CC33CC', '#CC33FF', '#CC6600', '#CC6633', '#CC9900', '#CC9933', + '#CCCC00', '#CCCC33', '#FF0000', '#FF0033', '#FF0066', '#FF0099', '#FF00CC', + '#FF00FF', '#FF3300', '#FF3333', '#FF3366', '#FF3399', '#FF33CC', '#FF33FF', + '#FF6600', '#FF6633', '#FF9900', '#FF9933', '#FFCC00', '#FFCC33' + ]; + + /** + * Currently only WebKit-based Web Inspectors, Firefox >= v31, + * and the Firebug extension (any Firefox version) are known + * to support "%c" CSS customizations. + * + * TODO: add a `localStorage` variable to explicitly enable/disable colors + */ + + function useColors() { + // NB: In an Electron preload script, document will be defined but not fully + // initialized. Since we know we're in Chrome, we'll just detect this case + // explicitly + if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') { + return true; + } + + // Internet Explorer and Edge do not support colors. + if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) { + return false; + } + + // is webkit? http://stackoverflow.com/a/16459606/376773 + // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 + return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || + // is firebug? http://stackoverflow.com/a/398120/376773 + (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || + // is firefox >= v31? + // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) || + // double check webkit in userAgent just in case we are in a worker + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); + } + + /** + * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. + */ + + exports.formatters.j = function(v) { + try { + return JSON.stringify(v); + } catch (err) { + return '[UnexpectedJSONParseError]: ' + err.message; + } + }; + + + /** + * Colorize log arguments if enabled. + * + * @api public + */ + + function formatArgs(args) { + var useColors = this.useColors; + + args[0] = (useColors ? '%c' : '') + + this.namespace + + (useColors ? ' %c' : ' ') + + args[0] + + (useColors ? '%c ' : ' ') + + '+' + exports.humanize(this.diff); + + if (!useColors) return; + + var c = 'color: ' + this.color; + args.splice(1, 0, c, 'color: inherit') + + // the final "%c" is somewhat tricky, because there could be other + // arguments passed either before or after the %c, so we need to + // figure out the correct index to insert the CSS into + var index = 0; + var lastC = 0; + args[0].replace(/%[a-zA-Z%]/g, function(match) { + if ('%%' === match) return; + index++; + if ('%c' === match) { + // we only are interested in the *last* %c + // (the user may have provided their own) + lastC = index; + } + }); + + args.splice(lastC, 0, c); + } + + /** + * Invokes `console.log()` when available. + * No-op when `console.log` is not a "function". + * + * @api public + */ + + function log() { + // this hackery is required for IE8/9, where + // the `console.log` function doesn't have 'apply' + return 'object' === typeof console + && console.log + && Function.prototype.apply.call(console.log, console, arguments); + } + + /** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ + + function save(namespaces) { + try { + if (null == namespaces) { + exports.storage.removeItem('debug'); + } else { + exports.storage.debug = namespaces; + } + } catch(e) {} + } + + /** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ + + function load() { + var r; + try { + r = exports.storage.debug; + } catch(e) {} + + // If debug isn't set in LS, and we're in Electron, try to load $DEBUG + if (!r && typeof process !== 'undefined' && 'env' in process) { + r = process.env.DEBUG; + } + + return r; + } + + /** + * Enable namespaces listed in `localStorage.debug` initially. + */ + + exports.enable(load()); + + /** + * Localstorage attempts to return the localstorage. + * + * This is necessary because safari throws + * when a user disables cookies/localstorage + * and you attempt to access it. + * + * @return {LocalStorage} + * @api private + */ + + function localstorage() { + try { + return window.localStorage; + } catch (e) {} + } + + /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(23))) + +/***/ }, +/* 23 */ +/***/ function(module, exports) { + + // shim for using process in browser + var process = module.exports = {}; + + // cached from whatever global is present so that test runners that stub it + // don't break things. But we need to wrap it in a try catch in case it is + // wrapped in strict mode code which doesn't define any globals. It's inside a + // function because try/catches deoptimize in certain engines. + + var cachedSetTimeout; + var cachedClearTimeout; + + function defaultSetTimout() { + throw new Error('setTimeout has not been defined'); + } + function defaultClearTimeout () { + throw new Error('clearTimeout has not been defined'); + } + (function () { + try { + if (typeof setTimeout === 'function') { + cachedSetTimeout = setTimeout; + } else { + cachedSetTimeout = defaultSetTimout; + } + } catch (e) { + cachedSetTimeout = defaultSetTimout; + } + try { + if (typeof clearTimeout === 'function') { + cachedClearTimeout = clearTimeout; + } else { + cachedClearTimeout = defaultClearTimeout; + } + } catch (e) { + cachedClearTimeout = defaultClearTimeout; + } + } ()) + function runTimeout(fun) { + if (cachedSetTimeout === setTimeout) { + //normal enviroments in sane situations + return setTimeout(fun, 0); + } + // if setTimeout wasn't available but was latter defined + if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { + cachedSetTimeout = setTimeout; + return setTimeout(fun, 0); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedSetTimeout(fun, 0); + } catch(e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedSetTimeout.call(null, fun, 0); + } catch(e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error + return cachedSetTimeout.call(this, fun, 0); + } + } + + + } + function runClearTimeout(marker) { + if (cachedClearTimeout === clearTimeout) { + //normal enviroments in sane situations + return clearTimeout(marker); + } + // if clearTimeout wasn't available but was latter defined + if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { + cachedClearTimeout = clearTimeout; + return clearTimeout(marker); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedClearTimeout(marker); + } catch (e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedClearTimeout.call(null, marker); + } catch (e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. + // Some versions of I.E. have different rules for clearTimeout vs setTimeout + return cachedClearTimeout.call(this, marker); + } + } + + + + } + var queue = []; + var draining = false; + var currentQueue; + var queueIndex = -1; + + function cleanUpNextTick() { + if (!draining || !currentQueue) { + return; + } + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } + } + + function drainQueue() { + if (draining) { + return; + } + var timeout = runTimeout(cleanUpNextTick); + draining = true; + + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } + } + queueIndex = -1; + len = queue.length; + } + currentQueue = null; + draining = false; + runClearTimeout(timeout); + } + + process.nextTick = function (fun) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + runTimeout(drainQueue); + } + }; + + // v8 likes predictible objects + function Item(fun, array) { + this.fun = fun; + this.array = array; + } + Item.prototype.run = function () { + this.fun.apply(null, this.array); + }; + process.title = 'browser'; + process.browser = true; + process.env = {}; + process.argv = []; + process.version = ''; // empty string to avoid regexp issues + process.versions = {}; + + function noop() {} + + process.on = noop; + process.addListener = noop; + process.once = noop; + process.off = noop; + process.removeListener = noop; + process.removeAllListeners = noop; + process.emit = noop; + process.prependListener = noop; + process.prependOnceListener = noop; + + process.listeners = function (name) { return [] } + + process.binding = function (name) { + throw new Error('process.binding is not supported'); + }; + + process.cwd = function () { return '/' }; + process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); + }; + process.umask = function() { return 0; }; + + +/***/ }, +/* 24 */ +/***/ function(module, exports, __webpack_require__) { + + + /** + * This is the common logic for both the Node.js and web browser + * implementations of `debug()`. + * + * Expose `debug()` as the module. + */ + + exports = module.exports = createDebug.debug = createDebug['default'] = createDebug; + exports.coerce = coerce; + exports.disable = disable; + exports.enable = enable; + exports.enabled = enabled; + exports.humanize = __webpack_require__(25); + + /** + * Active `debug` instances. + */ + exports.instances = []; + + /** + * The currently active debug mode names, and names to skip. + */ + + exports.names = []; + exports.skips = []; + + /** + * Map of special "%n" handling functions, for the debug "format" argument. + * + * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". + */ + + exports.formatters = {}; + + /** + * Select a color. + * @param {String} namespace + * @return {Number} + * @api private + */ + + function selectColor(namespace) { + var hash = 0, i; + + for (i in namespace) { + hash = ((hash << 5) - hash) + namespace.charCodeAt(i); + hash |= 0; // Convert to 32bit integer + } + + return exports.colors[Math.abs(hash) % exports.colors.length]; + } + + /** + * Create a debugger with the given `namespace`. + * + * @param {String} namespace + * @return {Function} + * @api public + */ + + function createDebug(namespace) { + + var prevTime; + + function debug() { + // disabled? + if (!debug.enabled) return; + + var self = debug; + + // set `diff` timestamp + var curr = +new Date(); + var ms = curr - (prevTime || curr); + self.diff = ms; + self.prev = prevTime; + self.curr = curr; + prevTime = curr; + + // turn the `arguments` into a proper Array + var args = new Array(arguments.length); + for (var i = 0; i < args.length; i++) { + args[i] = arguments[i]; + } + + args[0] = exports.coerce(args[0]); + + if ('string' !== typeof args[0]) { + // anything else let's inspect with %O + args.unshift('%O'); + } + + // apply any `formatters` transformations + var index = 0; + args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) { + // if we encounter an escaped % then don't increase the array index + if (match === '%%') return match; + index++; + var formatter = exports.formatters[format]; + if ('function' === typeof formatter) { + var val = args[index]; + match = formatter.call(self, val); + + // now we need to remove `args[index]` since it's inlined in the `format` + args.splice(index, 1); + index--; + } + return match; + }); + + // apply env-specific formatting (colors, etc.) + exports.formatArgs.call(self, args); + + var logFn = debug.log || exports.log || console.log.bind(console); + logFn.apply(self, args); + } + + debug.namespace = namespace; + debug.enabled = exports.enabled(namespace); + debug.useColors = exports.useColors(); + debug.color = selectColor(namespace); + debug.destroy = destroy; + + // env-specific initialization logic for debug instances + if ('function' === typeof exports.init) { + exports.init(debug); + } + + exports.instances.push(debug); + + return debug; + } + + function destroy () { + var index = exports.instances.indexOf(this); + if (index !== -1) { + exports.instances.splice(index, 1); + return true; + } else { + return false; + } + } + + /** + * Enables a debug mode by namespaces. This can include modes + * separated by a colon and wildcards. + * + * @param {String} namespaces + * @api public + */ + + function enable(namespaces) { + exports.save(namespaces); + + exports.names = []; + exports.skips = []; + + var i; + var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); + var len = split.length; + + for (i = 0; i < len; i++) { + if (!split[i]) continue; // ignore empty strings + namespaces = split[i].replace(/\*/g, '.*?'); + if (namespaces[0] === '-') { + exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); + } else { + exports.names.push(new RegExp('^' + namespaces + '$')); + } + } + + for (i = 0; i < exports.instances.length; i++) { + var instance = exports.instances[i]; + instance.enabled = exports.enabled(instance.namespace); + } + } + + /** + * Disable debug output. + * + * @api public + */ + + function disable() { + exports.enable(''); + } + + /** + * Returns true if the given mode name is enabled, false otherwise. + * + * @param {String} name + * @return {Boolean} + * @api public + */ + + function enabled(name) { + if (name[name.length - 1] === '*') { + return true; + } + var i, len; + for (i = 0, len = exports.skips.length; i < len; i++) { + if (exports.skips[i].test(name)) { + return false; + } + } + for (i = 0, len = exports.names.length; i < len; i++) { + if (exports.names[i].test(name)) { + return true; + } + } + return false; + } + + /** + * Coerce `val`. + * + * @param {Mixed} val + * @return {Mixed} + * @api private + */ + + function coerce(val) { + if (val instanceof Error) return val.stack || val.message; + return val; + } + + +/***/ }, +/* 25 */ +/***/ function(module, exports) { + + /** + * Helpers. + */ + + var s = 1000; + var m = s * 60; + var h = m * 60; + var d = h * 24; + var y = d * 365.25; + + /** + * Parse or format the given `val`. + * + * Options: + * + * - `long` verbose formatting [false] + * + * @param {String|Number} val + * @param {Object} [options] + * @throws {Error} throw an error if val is not a non-empty string or a number + * @return {String|Number} + * @api public + */ + + module.exports = function(val, options) { + options = options || {}; + var type = typeof val; + if (type === 'string' && val.length > 0) { + return parse(val); + } else if (type === 'number' && isNaN(val) === false) { + return options.long ? fmtLong(val) : fmtShort(val); + } + throw new Error( + 'val is not a non-empty string or a valid number. val=' + + JSON.stringify(val) + ); + }; + + /** + * Parse the given `str` and return milliseconds. + * + * @param {String} str + * @return {Number} + * @api private + */ + + function parse(str) { + str = String(str); + if (str.length > 100) { + return; + } + var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec( + str + ); + if (!match) { + return; + } + var n = parseFloat(match[1]); + var type = (match[2] || 'ms').toLowerCase(); + switch (type) { + case 'years': + case 'year': + case 'yrs': + case 'yr': + case 'y': + return n * y; + case 'days': + case 'day': + case 'd': + return n * d; + case 'hours': + case 'hour': + case 'hrs': + case 'hr': + case 'h': + return n * h; + case 'minutes': + case 'minute': + case 'mins': + case 'min': + case 'm': + return n * m; + case 'seconds': + case 'second': + case 'secs': + case 'sec': + case 's': + return n * s; + case 'milliseconds': + case 'millisecond': + case 'msecs': + case 'msec': + case 'ms': + return n; + default: + return undefined; + } + } + + /** + * Short format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + + function fmtShort(ms) { + if (ms >= d) { + return Math.round(ms / d) + 'd'; + } + if (ms >= h) { + return Math.round(ms / h) + 'h'; + } + if (ms >= m) { + return Math.round(ms / m) + 'm'; + } + if (ms >= s) { + return Math.round(ms / s) + 's'; + } + return ms + 'ms'; + } + + /** + * Long format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + + function fmtLong(ms) { + return plural(ms, d, 'day') || + plural(ms, h, 'hour') || + plural(ms, m, 'minute') || + plural(ms, s, 'second') || + ms + ' ms'; + } + + /** + * Pluralization helper. + */ + + function plural(ms, n, name) { + if (ms < n) { + return; + } + if (ms < n * 1.5) { + return Math.floor(ms / n) + ' ' + name; + } + return Math.ceil(ms / n) + ' ' + name + 's'; + } + + +/***/ }, +/* 26 */ +/***/ function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(global) {'use strict'; + + /** + * Module requirements. + */ + + var Polling = __webpack_require__(6); + var inherit = __webpack_require__(20); + + /** + * Module exports. + */ + + module.exports = JSONPPolling; + + /** + * Cached regular expressions. + */ + + var rNewline = /\n/g; + var rEscapedNewline = /\\n/g; + + /** + * Global JSONP callbacks. + */ + + var callbacks; + + /** + * Noop. + */ + + function empty() {} + + /** + * JSONP Polling constructor. + * + * @param {Object} opts. + * @api public + */ + + function JSONPPolling(opts) { + Polling.call(this, opts); + + this.query = this.query || {}; + + // define global callbacks array if not present + // we do this here (lazily) to avoid unneeded global pollution + if (!callbacks) { + // we need to consider multiple engines in the same page + if (!global.___eio) global.___eio = []; + callbacks = global.___eio; + } + + // callback identifier + this.index = callbacks.length; + + // add callback to jsonp global + var self = this; + callbacks.push(function (msg) { + self.onData(msg); + }); + + // append to query string + this.query.j = this.index; + + // prevent spurious errors from being emitted when the window is unloaded + if (global.document && global.addEventListener) { + global.addEventListener('beforeunload', function () { + if (self.script) self.script.onerror = empty; + }, false); + } + } + + /** + * Inherits from Polling. + */ + + inherit(JSONPPolling, Polling); + + /* + * JSONP only supports binary as base64 encoded strings + */ + + JSONPPolling.prototype.supportsBinary = false; + + /** + * Closes the socket. + * + * @api private + */ + + JSONPPolling.prototype.doClose = function () { + if (this.script) { + this.script.parentNode.removeChild(this.script); + this.script = null; + } + + if (this.form) { + this.form.parentNode.removeChild(this.form); + this.form = null; + this.iframe = null; + } + + Polling.prototype.doClose.call(this); + }; + + /** + * Starts a poll cycle. + * + * @api private + */ + + JSONPPolling.prototype.doPoll = function () { + var self = this; + var script = document.createElement('script'); + + if (this.script) { + this.script.parentNode.removeChild(this.script); + this.script = null; + } + + script.async = true; + script.src = this.uri(); + script.onerror = function (e) { + self.onError('jsonp poll error', e); + }; + + var insertAt = document.getElementsByTagName('script')[0]; + if (insertAt) { + insertAt.parentNode.insertBefore(script, insertAt); + } else { + (document.head || document.body).appendChild(script); + } + this.script = script; + + var isUAgecko = 'undefined' !== typeof navigator && /gecko/i.test(navigator.userAgent); + + if (isUAgecko) { + setTimeout(function () { + var iframe = document.createElement('iframe'); + document.body.appendChild(iframe); + document.body.removeChild(iframe); + }, 100); + } + }; + + /** + * Writes with a hidden iframe. + * + * @param {String} data to send + * @param {Function} called upon flush. + * @api private + */ + + JSONPPolling.prototype.doWrite = function (data, fn) { + var self = this; + + if (!this.form) { + var form = document.createElement('form'); + var area = document.createElement('textarea'); + var id = this.iframeId = 'eio_iframe_' + this.index; + var iframe; + + form.className = 'socketio'; + form.style.position = 'absolute'; + form.style.top = '-1000px'; + form.style.left = '-1000px'; + form.target = id; + form.method = 'POST'; + form.setAttribute('accept-charset', 'utf-8'); + area.name = 'd'; + form.appendChild(area); + document.body.appendChild(form); + + this.form = form; + this.area = area; + } + + this.form.action = this.uri(); + + function complete() { + initIframe(); + fn(); + } + + function initIframe() { + if (self.iframe) { + try { + self.form.removeChild(self.iframe); + } catch (e) { + self.onError('jsonp polling iframe removal error', e); + } + } + + try { + // ie6 dynamic iframes with target="" support (thanks Chris Lambacher) + var html = '