From a0bc2d79de628b435dd30de9718ed9121f6bcad9 Mon Sep 17 00:00:00 2001 From: Captain Nick Lucifer* Date: Fri, 10 Mar 2023 23:21:16 +0545 Subject: [PATCH] dot.dot.dot.exampol --- README.md | 7 + lnsocket.js | 449 ++ lnsocket.wasm | Bin 0 -> 140936 bytes node.js | 17 + node_modules/.bin/nopt | 1 + node_modules/.bin/tap | 1 + node_modules/.bin/uglifyjs | 1 + node_modules/.package-lock.json | 195 + node_modules/abbrev/LICENSE | 46 + node_modules/abbrev/README.md | 23 + node_modules/abbrev/abbrev.js | 61 + node_modules/abbrev/package.json | 21 + node_modules/buffer-equal/.travis.yml | 4 + node_modules/buffer-equal/LICENSE | 18 + node_modules/buffer-equal/README.markdown | 62 + node_modules/buffer-equal/example/eq.js | 14 + node_modules/buffer-equal/index.js | 14 + node_modules/buffer-equal/package.json | 33 + node_modules/buffer-equal/test/eq.js | 35 + node_modules/bunker/.npmignore | 1 + node_modules/bunker/.travis.yml | 4 + node_modules/bunker/README.markdown | 82 + node_modules/bunker/example/prof.js | 51 + node_modules/bunker/example/tiny.js | 18 + node_modules/bunker/example/top/run.js | 31 + node_modules/bunker/example/top/src.js | 18 + node_modules/bunker/index.js | 116 + node_modules/bunker/package.json | 35 + node_modules/bunker/test/cover.js | 36 + node_modules/bunker/test/return.js | 29 + node_modules/bunker/test/src/cover.js | 6 + node_modules/burrito/.npmignore | 1 + node_modules/burrito/.travis.yml | 4 + node_modules/burrito/README.markdown | 187 + node_modules/burrito/example/microwave.js | 8 + node_modules/burrito/example/web/bs.js | 4832 +++++++++++++++++ node_modules/burrito/example/web/index.html | 14 + node_modules/burrito/example/web/main.js | 17 + node_modules/burrito/example/web/server.js | 12 + node_modules/burrito/example/wrap.js | 7 + node_modules/burrito/index.js | 208 + .../burrito/node_modules/traverse/.npmignore | 1 + .../burrito/node_modules/traverse/LICENSE | 24 + .../node_modules/traverse/README.markdown | 237 + .../node_modules/traverse/examples/json.js | 16 + .../node_modules/traverse/examples/leaves.js | 15 + .../traverse/examples/negative.js | 8 + .../node_modules/traverse/examples/scrub.js | 10 + .../traverse/examples/stringify.js | 38 + .../burrito/node_modules/traverse/index.js | 267 + .../burrito/node_modules/traverse/main.js | 10 + .../node_modules/traverse/package.json | 18 + .../node_modules/traverse/test/circular.js | 115 + .../node_modules/traverse/test/date.js | 35 + .../node_modules/traverse/test/equal.js | 220 + .../node_modules/traverse/test/instance.js | 17 + .../node_modules/traverse/test/interface.js | 42 + .../node_modules/traverse/test/json.js | 47 + .../node_modules/traverse/test/keys.js | 29 + .../node_modules/traverse/test/leaves.js | 21 + .../traverse/test/lib/deep_equal.js | 92 + .../node_modules/traverse/test/mutability.js | 252 + .../node_modules/traverse/test/negative.js | 20 + .../burrito/node_modules/traverse/test/obj.js | 15 + .../node_modules/traverse/test/siblings.js | 35 + .../node_modules/traverse/test/stop.js | 41 + .../node_modules/traverse/test/stringify.js | 36 + .../node_modules/traverse/test/subexpr.js | 34 + .../node_modules/traverse/test/super_deep.js | 55 + node_modules/burrito/package.json | 43 + node_modules/burrito/test/ast.js | 31 + node_modules/burrito/test/err.js | 52 + node_modules/burrito/test/fail.js | 9 + node_modules/burrito/test/fail/src.js | 60 + node_modules/burrito/test/label.js | 92 + node_modules/burrito/test/microwave.js | 34 + node_modules/burrito/test/parent.js | 27 + node_modules/burrito/test/wrap.js | 159 + node_modules/charm/README.markdown | 216 + node_modules/charm/example/256.js | 17 + node_modules/charm/example/column.js | 11 + node_modules/charm/example/cursor.js | 22 + node_modules/charm/example/http_spin.js | 36 + node_modules/charm/example/lucky.js | 24 + node_modules/charm/example/position.js | 7 + node_modules/charm/example/progress.js | 18 + node_modules/charm/example/resize.js | 62 + node_modules/charm/example/spin.js | 23 + node_modules/charm/index.js | 305 ++ node_modules/charm/lib/encode.js | 18 + node_modules/charm/package.json | 32 + node_modules/deep-equal/README.markdown | 55 + node_modules/deep-equal/example/cmp.js | 11 + node_modules/deep-equal/index.js | 84 + node_modules/deep-equal/package.json | 33 + node_modules/deep-equal/test/cmp.js | 18 + node_modules/deep-is/.travis.yml | 5 + node_modules/deep-is/LICENSE | 22 + node_modules/deep-is/README.markdown | 70 + node_modules/deep-is/example/cmp.js | 11 + node_modules/deep-is/index.js | 102 + node_modules/deep-is/package.json | 58 + node_modules/deep-is/test/NaN.js | 16 + node_modules/deep-is/test/cmp.js | 23 + node_modules/deep-is/test/neg-vs-pos-0.js | 15 + node_modules/difflet/.travis.yml | 4 + node_modules/difflet/README.markdown | 116 + node_modules/difflet/example/cmp_array.js | 6 + node_modules/difflet/example/cmp_object.js | 6 + node_modules/difflet/example/colors.js | 18 + node_modules/difflet/example/comma_first.js | 12 + node_modules/difflet/example/diff.js | 15 + node_modules/difflet/example/html.js | 34 + node_modules/difflet/example/string.js | 4 + node_modules/difflet/index.js | 377 ++ node_modules/difflet/package.json | 41 + node_modules/difflet/test/diffing-NaN.js | 17 + node_modules/difflet/test/html.js | 80 + node_modules/lnsocket/.envrc | 6 + node_modules/lnsocket/.gitmodules | 3 + node_modules/lnsocket/LICENSE | 22 + node_modules/lnsocket/Makefile | 210 + node_modules/lnsocket/README.md | 82 + node_modules/lnsocket/TODO | 7 + node_modules/lnsocket/bech32.c | 211 + node_modules/lnsocket/bech32.h | 134 + node_modules/lnsocket/bigsize.c | 140 + node_modules/lnsocket/bigsize.h | 31 + node_modules/lnsocket/commando.c | 36 + node_modules/lnsocket/commando.h | 14 + node_modules/lnsocket/compiler.h | 85 + node_modules/lnsocket/configurator.c | 1110 ++++ node_modules/lnsocket/crypto.c | 239 + node_modules/lnsocket/crypto.h | 55 + node_modules/lnsocket/cursor.h | 393 ++ node_modules/lnsocket/dist/node/lnsocket.js | 391 ++ node_modules/lnsocket/dist/node/lnsocket.wasm | Bin 0 -> 144934 bytes node_modules/lnsocket/endian.h | 385 ++ node_modules/lnsocket/error.c | 49 + node_modules/lnsocket/error.h | 32 + node_modules/lnsocket/examples/README.md | 7 + node_modules/lnsocket/examples/node.js | 24 + node_modules/lnsocket/examples/package.json | 18 + .../lnsocket/examples/websockets.html | 16 + node_modules/lnsocket/examples/websockets.js | 16 + node_modules/lnsocket/export.h | 12 + node_modules/lnsocket/go/go.mod | 37 + node_modules/lnsocket/go/go.sum | 1009 ++++ node_modules/lnsocket/go/lnsocket.go | 190 + node_modules/lnsocket/handshake.c | 481 ++ node_modules/lnsocket/handshake.h | 147 + node_modules/lnsocket/hkdf.c | 98 + node_modules/lnsocket/hkdf.h | 22 + node_modules/lnsocket/hmac.c | 278 + node_modules/lnsocket/hmac.h | 116 + node_modules/lnsocket/index.js | 11 + node_modules/lnsocket/lnrpc.c | 114 + node_modules/lnsocket/lnsocket.c | 632 +++ node_modules/lnsocket/lnsocket.h | 95 + node_modules/lnsocket/lnsocket_internal.h | 26 + node_modules/lnsocket/lnsocket_lib.js | 370 ++ node_modules/lnsocket/lnsocket_pre.js | 24 + node_modules/lnsocket/lnsocket_wasm.c | 39 + node_modules/lnsocket/package.json | 13 + node_modules/lnsocket/sha256.c | 302 ++ node_modules/lnsocket/sha256.h | 155 + node_modules/lnsocket/sha512.c | 261 + node_modules/lnsocket/sha512.h | 138 + node_modules/lnsocket/shell.nix | 5 + node_modules/lnsocket/test.c | 59 + ...configure-customizable-AR-and-RANLIB.patch | 67 + .../lnsocket/tools/refresh-submodules.sh | 42 + node_modules/lnsocket/tools/secp-ios.sh | 74 + node_modules/lnsocket/tools/secp-wasm.sh | 27 + node_modules/lnsocket/typedefs.h | 13 + node_modules/lnsocket/varint.c | 75 + node_modules/lnsocket/varint.h | 14 + node_modules/mkdirp/.npmignore | 2 + node_modules/mkdirp/.travis.yml | 5 + node_modules/mkdirp/LICENSE | 21 + node_modules/mkdirp/examples/pow.js | 6 + node_modules/mkdirp/index.js | 82 + node_modules/mkdirp/package.json | 22 + node_modules/mkdirp/readme.markdown | 63 + node_modules/mkdirp/test/chmod.js | 38 + node_modules/mkdirp/test/clobber.js | 37 + node_modules/mkdirp/test/mkdirp.js | 28 + node_modules/mkdirp/test/perm.js | 32 + node_modules/mkdirp/test/perm_sync.js | 39 + node_modules/mkdirp/test/race.js | 41 + node_modules/mkdirp/test/rel.js | 32 + node_modules/mkdirp/test/return.js | 25 + node_modules/mkdirp/test/return_sync.js | 24 + node_modules/mkdirp/test/root.js | 18 + node_modules/mkdirp/test/sync.js | 32 + node_modules/mkdirp/test/umask.js | 28 + node_modules/mkdirp/test/umask_sync.js | 32 + node_modules/nopt/.npmignore | 1 + node_modules/nopt/LICENSE | 23 + node_modules/nopt/README.md | 210 + node_modules/nopt/bin/nopt.js | 51 + node_modules/nopt/examples/my-program.js | 30 + node_modules/nopt/lib/nopt.js | 412 ++ node_modules/nopt/package.json | 22 + node_modules/nopt/test/basic.js | 243 + node_modules/runforcover/README.markdown | 56 + node_modules/runforcover/index.js | 127 + node_modules/runforcover/package.json | 32 + node_modules/runforcover/test/index.js | 1 + node_modules/runforcover/test/interface.js | 50 + node_modules/runforcover/test/src/coverage.js | 7 + node_modules/slide/LICENSE | 15 + node_modules/slide/README.md | 143 + node_modules/slide/index.js | 1 + node_modules/slide/lib/async-map-ordered.js | 65 + node_modules/slide/lib/async-map.js | 54 + node_modules/slide/lib/bind-actor.js | 16 + node_modules/slide/lib/chain.js | 20 + node_modules/slide/lib/slide.js | 3 + node_modules/slide/package.json | 20 + node_modules/tap/.npmignore | 0 node_modules/tap/AUTHORS | 8 + node_modules/tap/LICENSE | 23 + node_modules/tap/README.md | 82 + node_modules/tap/bin/tap-http.js | 19 + node_modules/tap/bin/tap-reader.js | 33 + node_modules/tap/bin/tap.js | 127 + node_modules/tap/coverage-example/lib/bar.js | 15 + node_modules/tap/coverage-example/lib/foo.js | 15 + .../tap/coverage-example/test/bar.test.js | 20 + .../tap/coverage-example/test/baz.test.js | 29 + .../tap/coverage-example/test/foo.test.js | 20 + node_modules/tap/example/lib/math.js | 1 + node_modules/tap/example/test/test-example.js | 237 + node_modules/tap/lib/main.js | 16 + node_modules/tap/lib/tap-assert.js | 442 ++ node_modules/tap/lib/tap-browser-harness.js | 63 + node_modules/tap/lib/tap-consumer.js | 243 + node_modules/tap/lib/tap-cov-html.js | 78 + node_modules/tap/lib/tap-global-harness.js | 68 + node_modules/tap/lib/tap-harness.js | 219 + node_modules/tap/lib/tap-producer.js | 130 + node_modules/tap/lib/tap-results.js | 71 + node_modules/tap/lib/tap-runner.js | 434 ++ node_modules/tap/lib/tap-test.js | 109 + .../tap/node_modules/inherits/LICENSE | 14 + .../tap/node_modules/inherits/README.md | 51 + .../tap/node_modules/inherits/inherits-old.js | 40 + .../tap/node_modules/inherits/inherits.js | 29 + .../tap/node_modules/inherits/package.json | 8 + node_modules/tap/node_modules/yamlish/LICENSE | 19 + .../tap/node_modules/yamlish/README.md | 20 + .../tap/node_modules/yamlish/package.json | 9 + .../tap/node_modules/yamlish/yamlish.js | 260 + node_modules/tap/package.json | 41 + node_modules/tap/test-disabled/bailout.js | 36 + node_modules/tap/test-disabled/foo.js | 1 + node_modules/tap/test-disabled/t.js | 16 + node_modules/tap/test/buffer_compare.js | 11 + node_modules/tap/test/common.js | 32 + node_modules/tap/test/deep.js | 43 + node_modules/tap/test/independent-timeouts.js | 16 + node_modules/tap/test/isolated-conf-test.js | 16 + node_modules/tap/test/meta-test.js | 73 + node_modules/tap/test/nested-test.js | 23 + node_modules/tap/test/non-tap-output.js | 12 + node_modules/tap/test/result-trap.js | 25 + .../tap/test/simple-harness-test-with-plan.js | 16 + node_modules/tap/test/simple-harness-test.js | 13 + node_modules/tap/test/test-test.js | 91 + node_modules/tap/test/timeout.js | 33 + node_modules/tap/test/trivial-success.js | 0 node_modules/traverse/.eslintrc | 33 + node_modules/traverse/.github/FUNDING.yml | 12 + node_modules/traverse/CHANGELOG.md | 432 ++ node_modules/traverse/LICENSE | 24 + node_modules/traverse/README.md | 228 + node_modules/traverse/examples/json.js | 18 + node_modules/traverse/examples/leaves.js | 17 + node_modules/traverse/examples/negative.js | 10 + node_modules/traverse/examples/scrub.js | 12 + node_modules/traverse/examples/stringify.js | 37 + node_modules/traverse/index.js | 311 ++ node_modules/traverse/package.json | 93 + node_modules/traverse/test/circular.js | 118 + node_modules/traverse/test/date.js | 39 + node_modules/traverse/test/equal.js | 238 + node_modules/traverse/test/error.js | 13 + node_modules/traverse/test/has.js | 17 + node_modules/traverse/test/instance.js | 17 + node_modules/traverse/test/interface.js | 46 + node_modules/traverse/test/json.js | 55 + node_modules/traverse/test/keys.js | 33 + node_modules/traverse/test/leaves.js | 24 + node_modules/traverse/test/lib/deep_equal.js | 87 + node_modules/traverse/test/mutability.js | 276 + node_modules/traverse/test/negative.js | 25 + node_modules/traverse/test/obj.js | 13 + node_modules/traverse/test/siblings.js | 39 + node_modules/traverse/test/stop.js | 46 + node_modules/traverse/test/stringify.js | 35 + node_modules/traverse/test/subexpr.js | 41 + node_modules/traverse/test/super_deep.js | 56 + node_modules/uglify-js/.npmignore | 4 + node_modules/uglify-js/README.html | 1026 ++++ node_modules/uglify-js/README.org | 571 ++ node_modules/uglify-js/bin/uglifyjs | 317 ++ node_modules/uglify-js/docstyle.css | 75 + node_modules/uglify-js/lib/object-ast.js | 75 + node_modules/uglify-js/lib/parse-js.js | 1339 +++++ node_modules/uglify-js/lib/process.js | 2001 +++++++ node_modules/uglify-js/lib/squeeze-more.js | 51 + node_modules/uglify-js/package.json | 24 + node_modules/uglify-js/package.json~ | 24 + node_modules/uglify-js/test/beautify.js | 28 + node_modules/uglify-js/test/testparser.js | 403 ++ .../test/unit/compress/expected/array1.js | 1 + .../test/unit/compress/expected/array2.js | 1 + .../test/unit/compress/expected/array3.js | 1 + .../test/unit/compress/expected/array4.js | 1 + .../test/unit/compress/expected/assignment.js | 1 + .../unit/compress/expected/concatstring.js | 1 + .../test/unit/compress/expected/const.js | 1 + .../unit/compress/expected/empty-blocks.js | 1 + .../unit/compress/expected/forstatement.js | 1 + .../test/unit/compress/expected/if.js | 1 + .../test/unit/compress/expected/ifreturn.js | 1 + .../test/unit/compress/expected/ifreturn2.js | 1 + .../test/unit/compress/expected/issue10.js | 1 + .../test/unit/compress/expected/issue11.js | 1 + .../test/unit/compress/expected/issue13.js | 1 + .../test/unit/compress/expected/issue14.js | 1 + .../test/unit/compress/expected/issue16.js | 1 + .../test/unit/compress/expected/issue17.js | 1 + .../test/unit/compress/expected/issue20.js | 1 + .../test/unit/compress/expected/issue21.js | 1 + .../test/unit/compress/expected/issue25.js | 1 + .../test/unit/compress/expected/issue27.js | 1 + .../test/unit/compress/expected/issue28.js | 1 + .../test/unit/compress/expected/issue29.js | 1 + .../test/unit/compress/expected/issue30.js | 1 + .../test/unit/compress/expected/issue34.js | 1 + .../test/unit/compress/expected/issue4.js | 1 + .../test/unit/compress/expected/issue48.js | 1 + .../test/unit/compress/expected/issue50.js | 1 + .../test/unit/compress/expected/issue53.js | 1 + .../test/unit/compress/expected/issue54.1.js | 1 + .../test/unit/compress/expected/issue68.js | 1 + .../test/unit/compress/expected/issue69.js | 1 + .../test/unit/compress/expected/issue9.js | 1 + .../test/unit/compress/expected/mangle.js | 1 + .../unit/compress/expected/null_string.js | 1 + .../unit/compress/expected/strict-equals.js | 1 + .../test/unit/compress/expected/var.js | 1 + .../test/unit/compress/expected/whitespace.js | 1 + .../test/unit/compress/expected/with.js | 1 + .../test/unit/compress/test/array1.js | 3 + .../test/unit/compress/test/array2.js | 4 + .../test/unit/compress/test/array3.js | 4 + .../test/unit/compress/test/array4.js | 6 + .../test/unit/compress/test/assignment.js | 20 + .../test/unit/compress/test/concatstring.js | 3 + .../test/unit/compress/test/const.js | 5 + .../test/unit/compress/test/empty-blocks.js | 4 + .../test/unit/compress/test/forstatement.js | 10 + .../uglify-js/test/unit/compress/test/if.js | 6 + .../test/unit/compress/test/ifreturn.js | 9 + .../test/unit/compress/test/ifreturn2.js | 16 + .../test/unit/compress/test/issue10.js | 1 + .../test/unit/compress/test/issue11.js | 3 + .../test/unit/compress/test/issue13.js | 1 + .../test/unit/compress/test/issue14.js | 1 + .../test/unit/compress/test/issue16.js | 1 + .../test/unit/compress/test/issue17.js | 4 + .../test/unit/compress/test/issue20.js | 1 + .../test/unit/compress/test/issue21.js | 6 + .../test/unit/compress/test/issue25.js | 7 + .../test/unit/compress/test/issue27.js | 1 + .../test/unit/compress/test/issue28.js | 3 + .../test/unit/compress/test/issue29.js | 1 + .../test/unit/compress/test/issue30.js | 3 + .../test/unit/compress/test/issue34.js | 3 + .../test/unit/compress/test/issue4.js | 3 + .../test/unit/compress/test/issue48.js | 1 + .../test/unit/compress/test/issue50.js | 9 + .../test/unit/compress/test/issue53.js | 1 + .../test/unit/compress/test/issue54.1.js | 3 + .../test/unit/compress/test/issue68.js | 5 + .../test/unit/compress/test/issue69.js | 1 + .../test/unit/compress/test/issue9.js | 4 + .../test/unit/compress/test/mangle.js | 5 + .../test/unit/compress/test/null_string.js | 1 + .../test/unit/compress/test/strict-equals.js | 3 + .../uglify-js/test/unit/compress/test/var.js | 3 + .../test/unit/compress/test/whitespace.js | 21 + .../uglify-js/test/unit/compress/test/with.js | 2 + node_modules/uglify-js/test/unit/scripts.js | 55 + node_modules/uglify-js/tmp/hoist.js | 33 + node_modules/uglify-js/tmp/instrument.js | 97 + node_modules/uglify-js/tmp/instrument2.js | 138 + node_modules/uglify-js/tmp/test.js | 30 + node_modules/uglify-js/uglify-js.js | 17 + package-lock.json | 205 + package.json | 18 + websockets.html | 16 + websockets.js | 16 + 406 files changed, 34577 insertions(+) create mode 100644 README.md create mode 100644 lnsocket.js create mode 100755 lnsocket.wasm create mode 100644 node.js create mode 120000 node_modules/.bin/nopt create mode 120000 node_modules/.bin/tap create mode 120000 node_modules/.bin/uglifyjs create mode 100644 node_modules/.package-lock.json create mode 100644 node_modules/abbrev/LICENSE create mode 100644 node_modules/abbrev/README.md create mode 100644 node_modules/abbrev/abbrev.js create mode 100644 node_modules/abbrev/package.json create mode 100644 node_modules/buffer-equal/.travis.yml create mode 100644 node_modules/buffer-equal/LICENSE create mode 100644 node_modules/buffer-equal/README.markdown create mode 100644 node_modules/buffer-equal/example/eq.js create mode 100644 node_modules/buffer-equal/index.js create mode 100644 node_modules/buffer-equal/package.json create mode 100644 node_modules/buffer-equal/test/eq.js create mode 100644 node_modules/bunker/.npmignore create mode 100644 node_modules/bunker/.travis.yml create mode 100644 node_modules/bunker/README.markdown create mode 100644 node_modules/bunker/example/prof.js create mode 100644 node_modules/bunker/example/tiny.js create mode 100644 node_modules/bunker/example/top/run.js create mode 100644 node_modules/bunker/example/top/src.js create mode 100644 node_modules/bunker/index.js create mode 100644 node_modules/bunker/package.json create mode 100644 node_modules/bunker/test/cover.js create mode 100644 node_modules/bunker/test/return.js create mode 100644 node_modules/bunker/test/src/cover.js create mode 100644 node_modules/burrito/.npmignore create mode 100644 node_modules/burrito/.travis.yml create mode 100644 node_modules/burrito/README.markdown create mode 100644 node_modules/burrito/example/microwave.js create mode 100644 node_modules/burrito/example/web/bs.js create mode 100644 node_modules/burrito/example/web/index.html create mode 100644 node_modules/burrito/example/web/main.js create mode 100644 node_modules/burrito/example/web/server.js create mode 100644 node_modules/burrito/example/wrap.js create mode 100644 node_modules/burrito/index.js create mode 100644 node_modules/burrito/node_modules/traverse/.npmignore create mode 100644 node_modules/burrito/node_modules/traverse/LICENSE create mode 100644 node_modules/burrito/node_modules/traverse/README.markdown create mode 100755 node_modules/burrito/node_modules/traverse/examples/json.js create mode 100755 node_modules/burrito/node_modules/traverse/examples/leaves.js create mode 100755 node_modules/burrito/node_modules/traverse/examples/negative.js create mode 100755 node_modules/burrito/node_modules/traverse/examples/scrub.js create mode 100755 node_modules/burrito/node_modules/traverse/examples/stringify.js create mode 100644 node_modules/burrito/node_modules/traverse/index.js create mode 100755 node_modules/burrito/node_modules/traverse/main.js create mode 100644 node_modules/burrito/node_modules/traverse/package.json create mode 100644 node_modules/burrito/node_modules/traverse/test/circular.js create mode 100644 node_modules/burrito/node_modules/traverse/test/date.js create mode 100644 node_modules/burrito/node_modules/traverse/test/equal.js create mode 100644 node_modules/burrito/node_modules/traverse/test/instance.js create mode 100644 node_modules/burrito/node_modules/traverse/test/interface.js create mode 100644 node_modules/burrito/node_modules/traverse/test/json.js create mode 100644 node_modules/burrito/node_modules/traverse/test/keys.js create mode 100644 node_modules/burrito/node_modules/traverse/test/leaves.js create mode 100644 node_modules/burrito/node_modules/traverse/test/lib/deep_equal.js create mode 100644 node_modules/burrito/node_modules/traverse/test/mutability.js create mode 100644 node_modules/burrito/node_modules/traverse/test/negative.js create mode 100644 node_modules/burrito/node_modules/traverse/test/obj.js create mode 100644 node_modules/burrito/node_modules/traverse/test/siblings.js create mode 100644 node_modules/burrito/node_modules/traverse/test/stop.js create mode 100644 node_modules/burrito/node_modules/traverse/test/stringify.js create mode 100644 node_modules/burrito/node_modules/traverse/test/subexpr.js create mode 100644 node_modules/burrito/node_modules/traverse/test/super_deep.js create mode 100644 node_modules/burrito/package.json create mode 100644 node_modules/burrito/test/ast.js create mode 100644 node_modules/burrito/test/err.js create mode 100644 node_modules/burrito/test/fail.js create mode 100644 node_modules/burrito/test/fail/src.js create mode 100644 node_modules/burrito/test/label.js create mode 100644 node_modules/burrito/test/microwave.js create mode 100644 node_modules/burrito/test/parent.js create mode 100644 node_modules/burrito/test/wrap.js create mode 100644 node_modules/charm/README.markdown create mode 100644 node_modules/charm/example/256.js create mode 100644 node_modules/charm/example/column.js create mode 100644 node_modules/charm/example/cursor.js create mode 100644 node_modules/charm/example/http_spin.js create mode 100644 node_modules/charm/example/lucky.js create mode 100644 node_modules/charm/example/position.js create mode 100644 node_modules/charm/example/progress.js create mode 100644 node_modules/charm/example/resize.js create mode 100644 node_modules/charm/example/spin.js create mode 100644 node_modules/charm/index.js create mode 100644 node_modules/charm/lib/encode.js create mode 100644 node_modules/charm/package.json create mode 100644 node_modules/deep-equal/README.markdown create mode 100644 node_modules/deep-equal/example/cmp.js create mode 100644 node_modules/deep-equal/index.js create mode 100644 node_modules/deep-equal/package.json create mode 100644 node_modules/deep-equal/test/cmp.js create mode 100644 node_modules/deep-is/.travis.yml create mode 100644 node_modules/deep-is/LICENSE create mode 100644 node_modules/deep-is/README.markdown create mode 100644 node_modules/deep-is/example/cmp.js create mode 100644 node_modules/deep-is/index.js create mode 100644 node_modules/deep-is/package.json create mode 100644 node_modules/deep-is/test/NaN.js create mode 100644 node_modules/deep-is/test/cmp.js create mode 100644 node_modules/deep-is/test/neg-vs-pos-0.js create mode 100644 node_modules/difflet/.travis.yml create mode 100644 node_modules/difflet/README.markdown create mode 100644 node_modules/difflet/example/cmp_array.js create mode 100644 node_modules/difflet/example/cmp_object.js create mode 100644 node_modules/difflet/example/colors.js create mode 100644 node_modules/difflet/example/comma_first.js create mode 100644 node_modules/difflet/example/diff.js create mode 100644 node_modules/difflet/example/html.js create mode 100644 node_modules/difflet/example/string.js create mode 100644 node_modules/difflet/index.js create mode 100644 node_modules/difflet/package.json create mode 100644 node_modules/difflet/test/diffing-NaN.js create mode 100644 node_modules/difflet/test/html.js create mode 100644 node_modules/lnsocket/.envrc create mode 100644 node_modules/lnsocket/.gitmodules create mode 100644 node_modules/lnsocket/LICENSE create mode 100644 node_modules/lnsocket/Makefile create mode 100644 node_modules/lnsocket/README.md create mode 100644 node_modules/lnsocket/TODO create mode 100644 node_modules/lnsocket/bech32.c create mode 100644 node_modules/lnsocket/bech32.h create mode 100644 node_modules/lnsocket/bigsize.c create mode 100644 node_modules/lnsocket/bigsize.h create mode 100644 node_modules/lnsocket/commando.c create mode 100644 node_modules/lnsocket/commando.h create mode 100644 node_modules/lnsocket/compiler.h create mode 100644 node_modules/lnsocket/configurator.c create mode 100644 node_modules/lnsocket/crypto.c create mode 100644 node_modules/lnsocket/crypto.h create mode 100644 node_modules/lnsocket/cursor.h create mode 100644 node_modules/lnsocket/dist/node/lnsocket.js create mode 100755 node_modules/lnsocket/dist/node/lnsocket.wasm create mode 100644 node_modules/lnsocket/endian.h create mode 100644 node_modules/lnsocket/error.c create mode 100644 node_modules/lnsocket/error.h create mode 100644 node_modules/lnsocket/examples/README.md create mode 100644 node_modules/lnsocket/examples/node.js create mode 100644 node_modules/lnsocket/examples/package.json create mode 100644 node_modules/lnsocket/examples/websockets.html create mode 100644 node_modules/lnsocket/examples/websockets.js create mode 100644 node_modules/lnsocket/export.h create mode 100644 node_modules/lnsocket/go/go.mod create mode 100644 node_modules/lnsocket/go/go.sum create mode 100644 node_modules/lnsocket/go/lnsocket.go create mode 100644 node_modules/lnsocket/handshake.c create mode 100644 node_modules/lnsocket/handshake.h create mode 100644 node_modules/lnsocket/hkdf.c create mode 100644 node_modules/lnsocket/hkdf.h create mode 100644 node_modules/lnsocket/hmac.c create mode 100644 node_modules/lnsocket/hmac.h create mode 100644 node_modules/lnsocket/index.js create mode 100644 node_modules/lnsocket/lnrpc.c create mode 100644 node_modules/lnsocket/lnsocket.c create mode 100644 node_modules/lnsocket/lnsocket.h create mode 100644 node_modules/lnsocket/lnsocket_internal.h create mode 100644 node_modules/lnsocket/lnsocket_lib.js create mode 100644 node_modules/lnsocket/lnsocket_pre.js create mode 100644 node_modules/lnsocket/lnsocket_wasm.c create mode 100644 node_modules/lnsocket/package.json create mode 100644 node_modules/lnsocket/sha256.c create mode 100644 node_modules/lnsocket/sha256.h create mode 100644 node_modules/lnsocket/sha512.c create mode 100644 node_modules/lnsocket/sha512.h create mode 100644 node_modules/lnsocket/shell.nix create mode 100644 node_modules/lnsocket/test.c create mode 100644 node_modules/lnsocket/tools/0001-configure-customizable-AR-and-RANLIB.patch create mode 100755 node_modules/lnsocket/tools/refresh-submodules.sh create mode 100755 node_modules/lnsocket/tools/secp-ios.sh create mode 100755 node_modules/lnsocket/tools/secp-wasm.sh create mode 100644 node_modules/lnsocket/typedefs.h create mode 100644 node_modules/lnsocket/varint.c create mode 100644 node_modules/lnsocket/varint.h create mode 100644 node_modules/mkdirp/.npmignore create mode 100644 node_modules/mkdirp/.travis.yml create mode 100644 node_modules/mkdirp/LICENSE create mode 100644 node_modules/mkdirp/examples/pow.js create mode 100644 node_modules/mkdirp/index.js create mode 100644 node_modules/mkdirp/package.json create mode 100644 node_modules/mkdirp/readme.markdown create mode 100644 node_modules/mkdirp/test/chmod.js create mode 100644 node_modules/mkdirp/test/clobber.js create mode 100644 node_modules/mkdirp/test/mkdirp.js create mode 100644 node_modules/mkdirp/test/perm.js create mode 100644 node_modules/mkdirp/test/perm_sync.js create mode 100644 node_modules/mkdirp/test/race.js create mode 100644 node_modules/mkdirp/test/rel.js create mode 100644 node_modules/mkdirp/test/return.js create mode 100644 node_modules/mkdirp/test/return_sync.js create mode 100644 node_modules/mkdirp/test/root.js create mode 100644 node_modules/mkdirp/test/sync.js create mode 100644 node_modules/mkdirp/test/umask.js create mode 100644 node_modules/mkdirp/test/umask_sync.js create mode 100644 node_modules/nopt/.npmignore create mode 100644 node_modules/nopt/LICENSE create mode 100644 node_modules/nopt/README.md create mode 100755 node_modules/nopt/bin/nopt.js create mode 100755 node_modules/nopt/examples/my-program.js create mode 100644 node_modules/nopt/lib/nopt.js create mode 100644 node_modules/nopt/package.json create mode 100644 node_modules/nopt/test/basic.js create mode 100644 node_modules/runforcover/README.markdown create mode 100644 node_modules/runforcover/index.js create mode 100644 node_modules/runforcover/package.json create mode 100644 node_modules/runforcover/test/index.js create mode 100644 node_modules/runforcover/test/interface.js create mode 100644 node_modules/runforcover/test/src/coverage.js create mode 100644 node_modules/slide/LICENSE create mode 100644 node_modules/slide/README.md create mode 100644 node_modules/slide/index.js create mode 100644 node_modules/slide/lib/async-map-ordered.js create mode 100644 node_modules/slide/lib/async-map.js create mode 100644 node_modules/slide/lib/bind-actor.js create mode 100644 node_modules/slide/lib/chain.js create mode 100644 node_modules/slide/lib/slide.js create mode 100644 node_modules/slide/package.json create mode 100644 node_modules/tap/.npmignore create mode 100644 node_modules/tap/AUTHORS create mode 100644 node_modules/tap/LICENSE create mode 100644 node_modules/tap/README.md create mode 100644 node_modules/tap/bin/tap-http.js create mode 100755 node_modules/tap/bin/tap-reader.js create mode 100755 node_modules/tap/bin/tap.js create mode 100644 node_modules/tap/coverage-example/lib/bar.js create mode 100644 node_modules/tap/coverage-example/lib/foo.js create mode 100644 node_modules/tap/coverage-example/test/bar.test.js create mode 100644 node_modules/tap/coverage-example/test/baz.test.js create mode 100644 node_modules/tap/coverage-example/test/foo.test.js create mode 100644 node_modules/tap/example/lib/math.js create mode 100644 node_modules/tap/example/test/test-example.js create mode 100644 node_modules/tap/lib/main.js create mode 100644 node_modules/tap/lib/tap-assert.js create mode 100644 node_modules/tap/lib/tap-browser-harness.js create mode 100644 node_modules/tap/lib/tap-consumer.js create mode 100644 node_modules/tap/lib/tap-cov-html.js create mode 100644 node_modules/tap/lib/tap-global-harness.js create mode 100644 node_modules/tap/lib/tap-harness.js create mode 100644 node_modules/tap/lib/tap-producer.js create mode 100644 node_modules/tap/lib/tap-results.js create mode 100644 node_modules/tap/lib/tap-runner.js create mode 100644 node_modules/tap/lib/tap-test.js create mode 100644 node_modules/tap/node_modules/inherits/LICENSE create mode 100644 node_modules/tap/node_modules/inherits/README.md create mode 100644 node_modules/tap/node_modules/inherits/inherits-old.js create mode 100644 node_modules/tap/node_modules/inherits/inherits.js create mode 100644 node_modules/tap/node_modules/inherits/package.json create mode 100644 node_modules/tap/node_modules/yamlish/LICENSE create mode 100644 node_modules/tap/node_modules/yamlish/README.md create mode 100644 node_modules/tap/node_modules/yamlish/package.json create mode 100644 node_modules/tap/node_modules/yamlish/yamlish.js create mode 100644 node_modules/tap/package.json create mode 100644 node_modules/tap/test-disabled/bailout.js create mode 100644 node_modules/tap/test-disabled/foo.js create mode 100644 node_modules/tap/test-disabled/t.js create mode 100644 node_modules/tap/test/buffer_compare.js create mode 100644 node_modules/tap/test/common.js create mode 100644 node_modules/tap/test/deep.js create mode 100644 node_modules/tap/test/independent-timeouts.js create mode 100644 node_modules/tap/test/isolated-conf-test.js create mode 100644 node_modules/tap/test/meta-test.js create mode 100644 node_modules/tap/test/nested-test.js create mode 100644 node_modules/tap/test/non-tap-output.js create mode 100644 node_modules/tap/test/result-trap.js create mode 100644 node_modules/tap/test/simple-harness-test-with-plan.js create mode 100644 node_modules/tap/test/simple-harness-test.js create mode 100644 node_modules/tap/test/test-test.js create mode 100644 node_modules/tap/test/timeout.js create mode 100644 node_modules/tap/test/trivial-success.js create mode 100644 node_modules/traverse/.eslintrc create mode 100644 node_modules/traverse/.github/FUNDING.yml create mode 100644 node_modules/traverse/CHANGELOG.md create mode 100644 node_modules/traverse/LICENSE create mode 100644 node_modules/traverse/README.md create mode 100755 node_modules/traverse/examples/json.js create mode 100755 node_modules/traverse/examples/leaves.js create mode 100755 node_modules/traverse/examples/negative.js create mode 100755 node_modules/traverse/examples/scrub.js create mode 100755 node_modules/traverse/examples/stringify.js create mode 100644 node_modules/traverse/index.js create mode 100644 node_modules/traverse/package.json create mode 100644 node_modules/traverse/test/circular.js create mode 100644 node_modules/traverse/test/date.js create mode 100644 node_modules/traverse/test/equal.js create mode 100644 node_modules/traverse/test/error.js create mode 100644 node_modules/traverse/test/has.js create mode 100644 node_modules/traverse/test/instance.js create mode 100644 node_modules/traverse/test/interface.js create mode 100644 node_modules/traverse/test/json.js create mode 100644 node_modules/traverse/test/keys.js create mode 100644 node_modules/traverse/test/leaves.js create mode 100644 node_modules/traverse/test/lib/deep_equal.js create mode 100644 node_modules/traverse/test/mutability.js create mode 100644 node_modules/traverse/test/negative.js create mode 100644 node_modules/traverse/test/obj.js create mode 100644 node_modules/traverse/test/siblings.js create mode 100644 node_modules/traverse/test/stop.js create mode 100644 node_modules/traverse/test/stringify.js create mode 100644 node_modules/traverse/test/subexpr.js create mode 100644 node_modules/traverse/test/super_deep.js create mode 100644 node_modules/uglify-js/.npmignore create mode 100644 node_modules/uglify-js/README.html create mode 100644 node_modules/uglify-js/README.org create mode 100755 node_modules/uglify-js/bin/uglifyjs create mode 100644 node_modules/uglify-js/docstyle.css create mode 100644 node_modules/uglify-js/lib/object-ast.js create mode 100644 node_modules/uglify-js/lib/parse-js.js create mode 100644 node_modules/uglify-js/lib/process.js create mode 100644 node_modules/uglify-js/lib/squeeze-more.js create mode 100644 node_modules/uglify-js/package.json create mode 100644 node_modules/uglify-js/package.json~ create mode 100755 node_modules/uglify-js/test/beautify.js create mode 100755 node_modules/uglify-js/test/testparser.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/array1.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/array2.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/array3.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/array4.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/assignment.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/concatstring.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/const.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/empty-blocks.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/forstatement.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/if.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/ifreturn.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/ifreturn2.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/issue10.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/issue11.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/issue13.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/issue14.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/issue16.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/issue17.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/issue20.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/issue21.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/issue25.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/issue27.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/issue28.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/issue29.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/issue30.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/issue34.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/issue4.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/issue48.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/issue50.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/issue53.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/issue54.1.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/issue68.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/issue69.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/issue9.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/mangle.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/null_string.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/strict-equals.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/var.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/whitespace.js create mode 100644 node_modules/uglify-js/test/unit/compress/expected/with.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/array1.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/array2.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/array3.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/array4.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/assignment.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/concatstring.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/const.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/empty-blocks.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/forstatement.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/if.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/ifreturn.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/ifreturn2.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/issue10.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/issue11.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/issue13.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/issue14.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/issue16.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/issue17.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/issue20.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/issue21.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/issue25.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/issue27.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/issue28.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/issue29.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/issue30.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/issue34.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/issue4.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/issue48.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/issue50.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/issue53.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/issue54.1.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/issue68.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/issue69.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/issue9.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/mangle.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/null_string.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/strict-equals.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/var.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/whitespace.js create mode 100644 node_modules/uglify-js/test/unit/compress/test/with.js create mode 100644 node_modules/uglify-js/test/unit/scripts.js create mode 100644 node_modules/uglify-js/tmp/hoist.js create mode 100644 node_modules/uglify-js/tmp/instrument.js create mode 100644 node_modules/uglify-js/tmp/instrument2.js create mode 100755 node_modules/uglify-js/tmp/test.js create mode 100644 node_modules/uglify-js/uglify-js.js create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 websockets.html create mode 100644 websockets.js diff --git a/README.md b/README.md new file mode 100644 index 0000000..65aa733 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ + +# Examples + +## nodejs + + $ npm install + $ node node.js diff --git a/lnsocket.js b/lnsocket.js new file mode 100644 index 0000000..737b5be --- /dev/null +++ b/lnsocket.js @@ -0,0 +1,449 @@ + +var Module = (() => { + var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; + if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename; + return ( +function(Module) { + Module = Module || {}; + +var Module=typeof Module!="undefined"?Module:{};var readyPromiseResolve,readyPromiseReject;Module["ready"]=new Promise(function(resolve,reject){readyPromiseResolve=resolve;readyPromiseReject=reject});Module.getRandomValue=function(){const window_="object"===typeof window?window:this;const crypto_=typeof window_.crypto!=="undefined"?window_.crypto:window_.msCrypto;let randomBytesNode;let fn;if(!crypto_){randomBytesNode=require("crypto").randomBytes;fn=randomValuesNode}else{fn=randomValuesStandard}function randomValuesNode(){return randomBytesNode(1)[0]>>>0}function randomValuesStandard(){var buf=new Uint32Array(1);crypto_.getRandomValues(buf);return buf[0]>>>0}return fn}();var moduleOverrides=Object.assign({},Module);var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var ENVIRONMENT_IS_WEB=typeof window=="object";var ENVIRONMENT_IS_WORKER=typeof importScripts=="function";var ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string";var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;function logExceptionOnExit(e){if(e instanceof ExitStatus)return;let toLog=e;err("exiting due to exception: "+toLog)}var fs;var nodePath;var requireNodeFS;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=require("path").dirname(scriptDirectory)+"/"}else{scriptDirectory=__dirname+"/"}requireNodeFS=(()=>{if(!nodePath){fs=require("fs");nodePath=require("path")}});read_=function shell_read(filename,binary){requireNodeFS();filename=nodePath["normalize"](filename);return fs.readFileSync(filename,binary?undefined:"utf8")};readBinary=(filename=>{var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}return ret});readAsync=((filename,onload,onerror)=>{requireNodeFS();filename=nodePath["normalize"](filename);fs.readFile(filename,function(err,data){if(err)onerror(err);else onload(data.buffer)})});if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/")}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",function(reason){throw reason});quit_=((status,toThrow)=>{if(keepRuntimeAlive()){process["exitCode"]=status;throw toThrow}logExceptionOnExit(toThrow);process["exit"](status)});Module["inspect"]=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(_scriptDir){scriptDirectory=_scriptDir}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,"").lastIndexOf("/")+1)}else{scriptDirectory=""}{read_=(url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText});if(ENVIRONMENT_IS_WORKER){readBinary=(url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)})}readAsync=((url,onload,onerror)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=(()=>{if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()});xhr.onerror=onerror;xhr.send(null)})}setWindowTitle=(title=>document.title=title)}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);Object.assign(Module,moduleOverrides);moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime=Module["noExitRuntime"]||true;if(typeof WebAssembly!="object"){abort("no native wasm support detected")}var wasmMemory;var ABORT=false;var EXITSTATUS;function getCFunc(ident){var func=Module["_"+ident];return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len)}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i=endIdx))++endPtr;if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023)}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf)}var INITIAL_MEMORY=Module["INITIAL_MEMORY"]||16777216;var wasmTable;var __ATPRERUN__=[];var __ATINIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;function keepRuntimeAlive(){return noExitRuntime}function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnInit(cb){__ATINIT__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){{if(Module["onAbort"]){Module["onAbort"](what)}}what="Aborted("+what+")";err(what);ABORT=true;EXITSTATUS=1;what+=". Build with -s ASSERTIONS=1 for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject(e);throw e}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return filename.startsWith(dataURIPrefix)}function isFileURI(filename){return filename.startsWith("file://")}var wasmBinaryFile;wasmBinaryFile="lnsocket.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}function getBinary(file){try{if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}else{throw"both async and sync fetching of the wasm failed"}}catch(err){abort(err)}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)){if(typeof fetch=="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw"failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary(wasmBinaryFile)})}else{if(readAsync){return new Promise(function(resolve,reject){readAsync(wasmBinaryFile,function(response){resolve(new Uint8Array(response))},reject)})}}}return Promise.resolve().then(function(){return getBinary(wasmBinaryFile)})}function createWasm(){var info={"a":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmMemory=Module["asm"]["i"];updateGlobalBufferAndViews(wasmMemory.buffer);wasmTable=Module["asm"]["m"];addOnInit(Module["asm"]["j"]);removeRunDependency("wasm-instantiate")}addRunDependency("wasm-instantiate");function receiveInstantiationResult(result){receiveInstance(result["instance"])}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(function(instance){return instance}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason)})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming=="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch=="function"){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiationResult,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(receiveInstantiationResult)})})}else{return instantiateArrayBuffer(receiveInstantiationResult)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync().catch(readyPromiseReject);return{}}var ASM_CONSTS={70236:function(){return Module.getRandomValue()},70272:function(){if(Module.getRandomValue===undefined){try{var window_="object"===typeof window?window:self;var crypto_=typeof window_.crypto!=="undefined"?window_.crypto:window_.msCrypto;var randomValuesStandard=function(){var buf=new Uint32Array(1);crypto_.getRandomValues(buf);return buf[0]>>>0};randomValuesStandard();Module.getRandomValue=randomValuesStandard}catch(e){try{var crypto=require("crypto");var randomValueNodeJS=function(){var buf=crypto["randomBytes"](4);return(buf[0]<<24|buf[1]<<16|buf[2]<<8|buf[3])>>>0};randomValueNodeJS();Module.getRandomValue=randomValueNodeJS}catch(e){throw"No secure random number generator found"}}}}};function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func=="number"){if(callback.arg===undefined){getWasmTableEntry(func)()}else{getWasmTableEntry(func)(callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}function getWasmTableEntry(funcPtr){return wasmTable.get(funcPtr)}function ___assert_fail(condition,filename,line,func){abort("Assertion failed: "+UTF8ToString(condition)+", at: "+[filename?UTF8ToString(filename):"unknown filename",line,func?UTF8ToString(func):"unknown function"])}function _abort(){abort("")}var readAsmConstArgsArray=[];function readAsmConstArgs(sigPtr,buf){readAsmConstArgsArray.length=0;var ch;buf>>=2;while(ch=HEAPU8[sigPtr++]){var readAsmConstArgsDouble=ch<105;if(readAsmConstArgsDouble&&buf&1)buf++;readAsmConstArgsArray.push(readAsmConstArgsDouble?HEAPF64[buf++>>1]:HEAP32[buf]);++buf}return readAsmConstArgsArray}function _emscripten_asm_const_int(code,sigPtr,argbuf){var args=readAsmConstArgs(sigPtr,argbuf);return ASM_CONSTS[code].apply(null,args)}function _emscripten_memcpy_big(dest,src,num){HEAPU8.copyWithin(dest,src,src+num)}function abortOnCannotGrowMemory(requestedSize){abort("OOM")}function _emscripten_resize_heap(requestedSize){var oldSize=HEAPU8.length;requestedSize=requestedSize>>>0;abortOnCannotGrowMemory(requestedSize)}var SYSCALLS={buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0}else{buffer.push(curr)}},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},get64:function(low,high){return low}};function _fd_close(fd){return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){}function _fd_write(fd,iov,iovcnt,pnum){var num=0;for(var i=0;i>2];var len=HEAP32[iov+4>>2];iov+=8;for(var j=0;j>2]=num;return 0}var asmLibraryArg={"a":___assert_fail,"b":_abort,"h":_emscripten_asm_const_int,"g":_emscripten_memcpy_big,"c":_emscripten_resize_heap,"f":_fd_close,"d":_fd_seek,"e":_fd_write};var asm=createWasm();var ___wasm_call_ctors=Module["___wasm_call_ctors"]=function(){return(___wasm_call_ctors=Module["___wasm_call_ctors"]=Module["asm"]["j"]).apply(null,arguments)};var _malloc=Module["_malloc"]=function(){return(_malloc=Module["_malloc"]=Module["asm"]["k"]).apply(null,arguments)};var _free=Module["_free"]=function(){return(_free=Module["_free"]=Module["asm"]["l"]).apply(null,arguments)};var _lnsocket_make_default_initmsg=Module["_lnsocket_make_default_initmsg"]=function(){return(_lnsocket_make_default_initmsg=Module["_lnsocket_make_default_initmsg"]=Module["asm"]["n"]).apply(null,arguments)};var _lnsocket_encrypt=Module["_lnsocket_encrypt"]=function(){return(_lnsocket_encrypt=Module["_lnsocket_encrypt"]=Module["asm"]["o"]).apply(null,arguments)};var _lnsocket_decrypt=Module["_lnsocket_decrypt"]=function(){return(_lnsocket_decrypt=Module["_lnsocket_decrypt"]=Module["asm"]["p"]).apply(null,arguments)};var _lnsocket_decrypt_header=Module["_lnsocket_decrypt_header"]=function(){return(_lnsocket_decrypt_header=Module["_lnsocket_decrypt_header"]=Module["asm"]["q"]).apply(null,arguments)};var _lnsocket_make_ping_msg=Module["_lnsocket_make_ping_msg"]=function(){return(_lnsocket_make_ping_msg=Module["_lnsocket_make_ping_msg"]=Module["asm"]["r"]).apply(null,arguments)};var _lnsocket_msgbuf=Module["_lnsocket_msgbuf"]=function(){return(_lnsocket_msgbuf=Module["_lnsocket_msgbuf"]=Module["asm"]["s"]).apply(null,arguments)};var _lnsocket_create=Module["_lnsocket_create"]=function(){return(_lnsocket_create=Module["_lnsocket_create"]=Module["asm"]["t"]).apply(null,arguments)};var _lnsocket_destroy=Module["_lnsocket_destroy"]=function(){return(_lnsocket_destroy=Module["_lnsocket_destroy"]=Module["asm"]["u"]).apply(null,arguments)};var _lnsocket_secp=Module["_lnsocket_secp"]=function(){return(_lnsocket_secp=Module["_lnsocket_secp"]=Module["asm"]["v"]).apply(null,arguments)};var _lnsocket_genkey=Module["_lnsocket_genkey"]=function(){return(_lnsocket_genkey=Module["_lnsocket_genkey"]=Module["asm"]["w"]).apply(null,arguments)};var _lnsocket_setkey=Module["_lnsocket_setkey"]=function(){return(_lnsocket_setkey=Module["_lnsocket_setkey"]=Module["asm"]["x"]).apply(null,arguments)};var _lnsocket_print_errors=Module["_lnsocket_print_errors"]=function(){return(_lnsocket_print_errors=Module["_lnsocket_print_errors"]=Module["asm"]["y"]).apply(null,arguments)};var _lnsocket_act_two=Module["_lnsocket_act_two"]=function(){return(_lnsocket_act_two=Module["_lnsocket_act_two"]=Module["asm"]["z"]).apply(null,arguments)};var _commando_make_rpc_msg=Module["_commando_make_rpc_msg"]=function(){return(_commando_make_rpc_msg=Module["_commando_make_rpc_msg"]=Module["asm"]["A"]).apply(null,arguments)};var _lnsocket_act_one=Module["_lnsocket_act_one"]=function(){return(_lnsocket_act_one=Module["_lnsocket_act_one"]=Module["asm"]["B"]).apply(null,arguments)};var stackSave=Module["stackSave"]=function(){return(stackSave=Module["stackSave"]=Module["asm"]["C"]).apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){return(stackRestore=Module["stackRestore"]=Module["asm"]["D"]).apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){return(stackAlloc=Module["stackAlloc"]=Module["asm"]["E"]).apply(null,arguments)};Module["ccall"]=ccall;Module["cwrap"]=cwrap;var calledRun;function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(args){args=args||arguments_;if(runDependencies>0){return}preRun();if(runDependencies>0){return}function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();readyPromiseResolve(Module);if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}Module["run"]=run;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}run(); + + + return Module.ready +} +); +})(); +if (typeof exports === 'object' && typeof module === 'object') + module.exports = Module; +else if (typeof define === 'function' && define['amd']) + define([], function() { return Module; }); +else if (typeof exports === 'object') + exports["Module"] = Module; + +async function lnsocket_init() { + const module = await Module() + + function SocketImpl(host) { + if (!(this instanceof SocketImpl)) + return new SocketImpl(host) + + if (typeof WebSocket !== 'undefined') { + console.log("WebSocket", typeof WebSocket) + const ok = host.startsWith("ws://") || host.startsWith("wss://") + if (!ok) + throw new Error("host must start with ws:// or wss://") + const ws = new WebSocket(host) + ws.ondata = function(fn) { + ws.onmessage = (v) => { + const data = v.data.arrayBuffer() + fn(data) + } + } + return ws + } + + // + // we're in nodejs + // + const net = require('net') + let [hostname,port] = host.split(":") + port = +port || 9735 + const socket = net.createConnection(port, hostname, () => { + socket.emit("open") + }) + socket.addEventListener = socket.on.bind(socket) + + if (socket.onmessage) + throw new Error("socket already has onmessage?") + + socket.ondata = (fn) => { + socket.on('data', fn) + } + + socket.close = () => { + socket.destroy() + } + + if (socket.send) + throw new Error("socket already has send?") + + socket.send = function socket_send(data) { + return new Promise((resolve, reject) => { + socket.write(data, resolve) + }); + } + + return socket + } + + const ACT_ONE_SIZE = 50 + const ACT_TWO_SIZE = 50 + const ACT_THREE_SIZE = 66 + const DEFAULT_TIMEOUT = 15000 + + const COMMANDO_REPLY_CONTINUES = 0x594b + const COMMANDO_REPLY_TERM = 0x594d + + const lnsocket_create = module.cwrap("lnsocket_create", "number") + const lnsocket_destroy = module.cwrap("lnsocket_destroy", "number") + const lnsocket_encrypt = module.cwrap("lnsocket_encrypt", "number", ["int", "array", "int", "int"]) + const lnsocket_decrypt = module.cwrap("lnsocket_decrypt", "number", ["int", "array", "int"]) + const lnsocket_decrypt_header = module.cwrap("lnsocket_decrypt_header", "number", ["number", "array"]) + const lnsocket_msgbuf = module.cwrap("lnsocket_msgbuf", "number", ["int"]) + const lnsocket_act_one = module.cwrap("lnsocket_act_one", "number", ["number", "string"]) + const lnsocket_act_two = module.cwrap("lnsocket_act_two", "number", ["number", "array"]) + const lnsocket_print_errors = module.cwrap("lnsocket_print_errors", "int") + const lnsocket_genkey = module.cwrap("lnsocket_genkey", null, ["number"]) + const lnsocket_setkey = module.cwrap("lnsocket_setkey", "number", ["number", "array"]) + const lnsocket_make_default_initmsg = module.cwrap("lnsocket_make_default_initmsg", "int", ["int", "int"]) + const lnsocket_make_ping_msg = module.cwrap("lnsocket_make_ping_msg", "int", ["int", "int", "int", "int"]) + const commando_make_rpc_msg = module.cwrap("commando_make_rpc_msg", "int", ["string", "string", "string", "number", "int", "int"]) + + function concat_u8_arrays(arrays) { + // sum of individual array lengths + let totalLength = arrays.reduce((acc, value) => + acc + (value.length || value.byteLength) + , 0); + + if (!arrays.length) return null; + + let result = new Uint8Array(totalLength); + + let length = 0; + for (let array of arrays) { + if (array instanceof ArrayBuffer) + result.set(new Uint8Array(array), length); + else + result.set(array, length); + + length += (array.length || array.byteLength); + } + + return result; + } + + function parse_msgtype(buf) { + return buf[0] << 8 | buf[1] + } + + function wasm_free(buf) { + module._free(buf); + } + + function char_to_hex(cstr) { + const c = cstr.charCodeAt(0) + // c >= 0 && c <= 9 + if (c >= 48 && c <= 57) { + return c - 48; + } + // c >= a && c <= f + if (c >= 97 && c <= 102) { + return c - 97 + 10; + } + // c >= A && c <= F + if (c >= 65 && c <= 70) { + return c - 65 + 10; + } + return -1; + } + + + function hex_decode(str, buflen) + { + let bufsize = buflen || 33 + let c1, c2 + let i = 0 + let j = 0 + let buf = new Uint8Array(bufsize) + let slen = str.length + while (slen > 1) { + if (-1==(c1 = char_to_hex(str[j])) || -1==(c2 = char_to_hex(str[j+1]))) + return null; + if (!bufsize) + return null; + j += 2 + slen -= 2 + buf[i++] = (c1 << 4) | c2 + bufsize--; + } + + return buf + } + + function wasm_alloc(len) { + const buf = module._malloc(len); + module.HEAPU8.set(Uint8Array, buf); + return buf + } + + function wasm_mem(ptr, size) { + return new Uint8Array(module.HEAPU8.buffer, ptr, size); + } + + function LNSocket(opts) { + if (!(this instanceof LNSocket)) + return new LNSocket(opts) + + this.opts = opts || { + timeout: DEFAULT_TIMEOUT + } + this.queue = [] + this.ln = lnsocket_create() + } + + LNSocket.prototype.queue_recv = function() { + let self = this + return new Promise((resolve, reject) => { + const checker = setInterval(() => { + const val = self.queue.shift() + if (val) { + clearInterval(checker) + resolve(val) + } else if (!self.connected) { + clearInterval(checker) + reject() + } + }, 5); + }) + } + + LNSocket.prototype.print_errors = function _lnsocket_print_errors() { + lnsocket_print_errors(this.ln) + } + + LNSocket.prototype.genkey = function _lnsocket_genkey() { + lnsocket_genkey(this.ln) + } + + LNSocket.prototype.setkeyraw = function lnsocket_setkeyraw(rawkey) { + return lnsocket_setkey(this.ln, rawkey) + } + + LNSocket.prototype.setkey = function _lnsocket_setkey(key) { + const rawkey = hex_decode(key) + return this.setkeyraw(rawkey) + } + + LNSocket.prototype.act_one_data = function _lnsocket_act_one(node_id) { + const act_one_ptr = lnsocket_act_one(this.ln, node_id) + if (act_one_ptr === 0) + return null + return wasm_mem(act_one_ptr, ACT_ONE_SIZE) + } + + LNSocket.prototype.act_two = function _lnsocket_act_two(act2) { + const act_three_ptr = lnsocket_act_two(this.ln, new Uint8Array(act2)) + if (act_three_ptr === 0) { + this.print_errors() + return null + } + return wasm_mem(act_three_ptr, ACT_THREE_SIZE) + } + + LNSocket.prototype.connect = async function lnsocket_connect(node_id, host) { + await handle_connect(this, node_id, host) + + const act1 = this.act_one_data(node_id) + this.ws.send(act1) + const act2 = await this.read_all(ACT_TWO_SIZE) + if (act2.length != ACT_TWO_SIZE) { + throw new Error(`expected act2 to be ${ACT_TWO_SIZE} long, got ${act2.length}`) + } + const act3 = this.act_two(act2) + this.ws.send(act3) + } + + LNSocket.prototype.connect_and_init = async function _connect_and_init(node_id, host) { + await this.connect(node_id, host) + await this.perform_init() + } + + LNSocket.prototype.read_all = async function read_all(n) { + let count = 0 + let chunks = [] + if (!this.connected) + throw new Error("read_all: not connected") + while (true) { + let res = await this.queue_recv() + + const remaining = n - count + + if (res.byteLength > remaining) { + chunks.push(res.slice(0, remaining)) + this.queue.unshift(res.slice(remaining)) + break + } else if (res.byteLength === remaining) { + chunks.push(res) + break + } + + chunks.push(res) + count += res.byteLength + } + + return concat_u8_arrays(chunks) + } + + LNSocket.prototype.read_header = async function read_header() { + const header = await this.read_all(18) + if (header.length != 18) + throw new Error("Failed to read header") + return lnsocket_decrypt_header(this.ln, header) + } + + LNSocket.prototype.rpc = async function lnsocket_rpc(opts) { + const msg = this.make_commando_msg(opts) + this.write(msg) + const res = await this.read_all_rpc() + return JSON.parse(res) + } + + LNSocket.prototype.recv = async function lnsocket_recv() { + const msg = await this.read() + const msgtype = parse_msgtype(msg.slice(0,2)) + const res = [msgtype, msg.slice(2)] + return res + } + + LNSocket.prototype.read_all_rpc = async function read_all_rpc() { + let chunks = [] + while (true) { + const [typ, msg] = await this.recv() + switch (typ) { + case COMMANDO_REPLY_TERM: + chunks.push(msg.slice(8)) + return new TextDecoder().decode(concat_u8_arrays(chunks)); + case COMMANDO_REPLY_CONTINUES: + chunks.push(msg.slice(8)) + break + default: + console.log("got unknown type", typ) + continue + } + } + } + + LNSocket.prototype.make_commando_msg = function _lnsocket_make_commando_msg(opts) { + const buflen = 4096 + let len = 0; + const buf = wasm_alloc(buflen); + + const params = JSON.stringify(opts.params||{}) + if (!(len = commando_make_rpc_msg(opts.method, params, opts.rune, + 0, buf, buflen))) { + throw new Error("couldn't make commando msg"); + } + + const dat = wasm_mem(buf, len) + wasm_free(buf); + return dat + } + + LNSocket.prototype.make_ping_msg = function _lnsocket_make_ping_msg(num_pong_bytes=1, ignored_bytes=1) { + const buflen = 32 + let len = 0; + const buf = wasm_alloc(buflen) + + if (!(len = lnsocket_make_ping_msg(buf, buflen, num_pong_bytes, ignored_bytes))) + throw new Error("couldn't make ping msg"); + + const dat = wasm_mem(buf, len) + wasm_free(buf); + return dat + } + + LNSocket.prototype.encrypt = function _lnsocket_encrypt(dat) { + const len = lnsocket_encrypt(this.ln, dat, dat.length) + if (len === 0) { + this.print_errors() + throw new Error("encrypt error") + } + const enc = wasm_mem(lnsocket_msgbuf(this.ln), len) + return enc + } + + LNSocket.prototype.decrypt = function _lnsocket_decrypt(dat) { + const len = lnsocket_decrypt(this.ln, dat, dat.length) + if (len === 0) { + this.print_errors() + throw new Error("decrypt error") + } + return wasm_mem(lnsocket_msgbuf(this.ln), len) + } + + LNSocket.prototype.write = function _lnsocket_write(dat) { + this.ws.send(this.encrypt(dat)) + } + + LNSocket.prototype.read = async function _lnsocket_read() { + const size = await this.read_header() + const enc = await this.read_all(size+16) + return this.decrypt(enc) + } + + LNSocket.prototype.make_default_initmsg = function _lnsocket_make_default_initmsg() { + const buflen = 1024 + let len = 0; + const buf = module._malloc(buflen); + module.HEAPU8.set(Uint8Array, buf); + + if (!(len = lnsocket_make_default_initmsg(buf, buflen))) + throw new Error("couldn't make initmsg"); + + const dat = wasm_mem(buf, len) + module._free(buf); + return dat + } + + LNSocket.prototype.perform_init = async function lnsocket_connect() { + await this.read() + const our_init = this.make_default_initmsg() + this.write(our_init) + } + + LNSocket.prototype.ping_pong = async function lnsocket_ping_pong() { + const pingmsg = this.make_ping_msg() + this.write(pingmsg) + return await this.read() + } + + LNSocket.prototype.disconnect = function lnsocket_disconnect() { + if (this.connected === true && this.ws) { + this.ws.close() + return true + } + return false + } + + LNSocket.prototype.destroy = function _lnsocket_destroy() { + this.disconnect() + lnsocket_destroy(this.ln) + } + + function handle_connect(ln, node_id, host) { + const ws = new SocketImpl(host) + return new Promise((resolve, reject) => { + const timeout = ln.opts.timeout || DEFAULT_TIMEOUT + const timer = setTimeout(reject, timeout); + + ws.ondata((v) => { + ln.queue.push(v) + }); + + ws.addEventListener('open', function(ev) { + ln.ws = ws + ln.connected = true + clearTimeout(timer) + resolve(ws) + }); + + ws.addEventListener('close', function(ev) { + ln.connected = false + }); + }) + } + + return LNSocket +} + +Module.init = Module.lnsocket_init = lnsocket_init diff --git a/lnsocket.wasm b/lnsocket.wasm new file mode 100755 index 0000000000000000000000000000000000000000..5a20010f1a2dfa1816d9fb01f8d38dad82abfa52 GIT binary patch literal 140936 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 I8Hv*W0O@QP9{>OV literal 0 HcmV?d00001 diff --git a/node.js b/node.js new file mode 100644 index 0000000..67e986c --- /dev/null +++ b/node.js @@ -0,0 +1,17 @@ +const LNSocket = require('../') + +async function go() { + const ln = await LNSocket() + + ln.genkey() + await ln.connect_and_init("03f3c108ccd536b8526841f0a5c58212bb9e6584a1eb493080e7c1cc34f82dad71", "24.84.152.187") + + const rune = "uQux-hID66AX5rFUpkt1p9CU_7DsTMyUC4G5yq7-dcw9MTMmbWV0aG9kPWdldGluZm8=" + const res = await ln.rpc({ method: "getinfo", rune }) + + ln.destroy() + console.log(res) + return res +} + +go() diff --git a/node_modules/.bin/nopt b/node_modules/.bin/nopt new file mode 120000 index 0000000..6b6566e --- /dev/null +++ b/node_modules/.bin/nopt @@ -0,0 +1 @@ +../nopt/bin/nopt.js \ No newline at end of file diff --git a/node_modules/.bin/tap b/node_modules/.bin/tap new file mode 120000 index 0000000..999914b --- /dev/null +++ b/node_modules/.bin/tap @@ -0,0 +1 @@ +../tap/bin/tap.js \ No newline at end of file diff --git a/node_modules/.bin/uglifyjs b/node_modules/.bin/uglifyjs new file mode 120000 index 0000000..fef3468 --- /dev/null +++ b/node_modules/.bin/uglifyjs @@ -0,0 +1 @@ +../uglify-js/bin/uglifyjs \ No newline at end of file diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json new file mode 100644 index 0000000..886ee5a --- /dev/null +++ b/node_modules/.package-lock.json @@ -0,0 +1,195 @@ +{ + "name": "examples", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "node_modules/buffer-equal": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.2.tgz", + "integrity": "sha512-4hr0gS7+NK47X6WbA/okVFrN5qGh3WLT7N3hMRv7+hlkXnbUIdU2u05n6r0RQv6cq6xke06nVl70r0NW0WM2OQ==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/bunker": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/bunker/-/bunker-0.1.2.tgz", + "integrity": "sha512-YnahkcXBNT522S46k5LUA9P18lzvgkunbMl0qIJQ8oeRMQ+dAg3YI3k32q5TnO+AAUErFHO6R768To6jslgYmQ==", + "dev": true, + "dependencies": { + "burrito": ">=0.2.5 <0.3" + }, + "engines": { + "node": "*" + } + }, + "node_modules/burrito": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/burrito/-/burrito-0.2.12.tgz", + "integrity": "sha512-ZhhT5iVTAgzQ+s8rily7m45Swxe/cU3dVCHTzqmHVWD/cc0Ds3W4Q4MExbkevY+fm0Me3lEwpehIy6TH7p+ehw==", + "dev": true, + "dependencies": { + "traverse": "~0.5.1", + "uglify-js": "~1.1.1" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/burrito/node_modules/traverse": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.5.2.tgz", + "integrity": "sha512-PUBVcfB3RqgLpzgTRGNiqK4duqrDbgGa1bobbUtzUwLiBNAjZ7vd5eCOdBxqZ/Fgezagr9o69IxP2fZp41RGFA==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/charm": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/charm/-/charm-0.1.2.tgz", + "integrity": "sha512-syedaZ9cPe7r3hoQA9twWYKu5AIyCswN5+szkmPBe9ccdLrj4bYaCnLVPTLd2kgVRc7+zoX4tyPgRnFKCj5YjQ==", + "dev": true + }, + "node_modules/deep-equal": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.0.0.tgz", + "integrity": "sha512-p1bI/kkDPT6auUI0U+WLuIIrzmDIDo80I406J8tT4y6I4ZGtBuMeTudrKDtBdMJFAcxqrQdx27gosqPVyY3IvQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/difflet": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/difflet/-/difflet-0.2.6.tgz", + "integrity": "sha512-ruldDDRmY1t678UOAJBng6sL77f62SqjHj0498YC0EJhxIe2yKkqJn2qEchwG3eU/dqJ/RxPZkAnYjePS4pDCw==", + "dev": true, + "dependencies": { + "charm": "0.1.x", + "deep-is": "0.1.x", + "traverse": "0.6.x" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/lnsocket": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/lnsocket/-/lnsocket-0.2.5.tgz", + "integrity": "sha512-gGmxaG9+w1IV3D5qRc/HX0WOBs8H5Osg00OBAOEdbP3UXjyU1/3JQgGOqrCoplbUu4BXUWKbX1IrROrhq2VQYw==" + }, + "node_modules/mkdirp": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha512-8OCq0De/h9ZxseqzCH8Kw/Filf5pF/vMI6+BH7Lu0jXz2pqYCjTAQRolSxRIi+Ax+oCCjlxoJMP0YQ4XlrQNHg==", + "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", + "dev": true + }, + "node_modules/nopt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-2.2.1.tgz", + "integrity": "sha512-gIOTA/uJuhPwFqp+spY7VQ1satbnGlD+iQVZxI18K6hs8Evq4sX81Ml7BB5byP/LsbR2yBVtmvdEmhi7evJ6Aw==", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + } + }, + "node_modules/runforcover": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/runforcover/-/runforcover-0.0.2.tgz", + "integrity": "sha512-yarCIK2HcAOadqnKW419+FA38qpWDCKcOr5RZU+jnyLL/hn3No9BHZY+YJDEzvQ0k8Oyl7ffLjZv9ZUxvyKoLQ==", + "dev": true, + "dependencies": { + "bunker": "0.1.X" + }, + "engines": { + "node": "*" + } + }, + "node_modules/slide": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", + "integrity": "sha512-NwrtjCg+lZoqhFU8fOwl4ay2ei8PaqCBOUV3/ektPY9trO1yQ1oXEfmHAhKArUVUr/hOHvy5f6AdP17dCM0zMw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/tap": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/tap/-/tap-0.2.6.tgz", + "integrity": "sha512-uLvaKbh3+A4nh+P3SrfX52kWGkVvP37UYI7LxKjRkd6Bjdqbyc7MARaPFGl7SdwyNwWtZHlUxQX3w9pVNf3FKQ==", + "bundleDependencies": [ + "inherits", + "tap-consumer", + "yamlish" + ], + "dev": true, + "dependencies": { + "buffer-equal": "~0.0.0", + "deep-equal": "~0.0.0", + "difflet": "~0.2.0", + "inherits": "*", + "mkdirp": "~0.3", + "nopt": "~2", + "runforcover": "~0.0.2", + "slide": "*", + "yamlish": "*" + }, + "bin": { + "tap": "bin/tap.js" + } + }, + "node_modules/tap/node_modules/inherits": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "WTFPL2" + }, + "node_modules/tap/node_modules/yamlish": { + "version": "0.0.5", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/traverse": { + "version": "0.6.7", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.7.tgz", + "integrity": "sha512-/y956gpUo9ZNCb99YjxG7OaslxZWHfCHAUUfshwqOXmxUIvqLjVO581BT+gM59+QV9tFe6/CGG53tsA1Y7RSdg==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/uglify-js": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-1.1.1.tgz", + "integrity": "sha512-YYY9Dle1leC+btgrHnAR05eq0aRdcPJsXlYYD+SYw2lqc5HFuFNHg3wWEW4SNE0iXXEUl0fz43gTQ3r1YK76rg==", + "dev": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": "*" + } + } + } +} diff --git a/node_modules/abbrev/LICENSE b/node_modules/abbrev/LICENSE new file mode 100644 index 0000000..9bcfa9d --- /dev/null +++ b/node_modules/abbrev/LICENSE @@ -0,0 +1,46 @@ +This software is dual-licensed under the ISC and MIT licenses. +You may use this software under EITHER of the following licenses. + +---------- + +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +---------- + +Copyright Isaac Z. Schlueter and Contributors +All rights reserved. + +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/abbrev/README.md b/node_modules/abbrev/README.md new file mode 100644 index 0000000..99746fe --- /dev/null +++ b/node_modules/abbrev/README.md @@ -0,0 +1,23 @@ +# abbrev-js + +Just like [ruby's Abbrev](http://apidock.com/ruby/Abbrev). + +Usage: + + var abbrev = require("abbrev"); + abbrev("foo", "fool", "folding", "flop"); + + // returns: + { fl: 'flop' + , flo: 'flop' + , flop: 'flop' + , fol: 'folding' + , fold: 'folding' + , foldi: 'folding' + , foldin: 'folding' + , folding: 'folding' + , foo: 'foo' + , fool: 'fool' + } + +This is handy for command-line scripts, or other cases where you want to be able to accept shorthands. diff --git a/node_modules/abbrev/abbrev.js b/node_modules/abbrev/abbrev.js new file mode 100644 index 0000000..7b1dc5d --- /dev/null +++ b/node_modules/abbrev/abbrev.js @@ -0,0 +1,61 @@ +module.exports = exports = abbrev.abbrev = abbrev + +abbrev.monkeyPatch = monkeyPatch + +function monkeyPatch () { + Object.defineProperty(Array.prototype, 'abbrev', { + value: function () { return abbrev(this) }, + enumerable: false, configurable: true, writable: true + }) + + Object.defineProperty(Object.prototype, 'abbrev', { + value: function () { return abbrev(Object.keys(this)) }, + enumerable: false, configurable: true, writable: true + }) +} + +function abbrev (list) { + if (arguments.length !== 1 || !Array.isArray(list)) { + list = Array.prototype.slice.call(arguments, 0) + } + for (var i = 0, l = list.length, args = [] ; i < l ; i ++) { + args[i] = typeof list[i] === "string" ? list[i] : String(list[i]) + } + + // sort them lexicographically, so that they're next to their nearest kin + args = args.sort(lexSort) + + // walk through each, seeing how much it has in common with the next and previous + var abbrevs = {} + , prev = "" + for (var i = 0, l = args.length ; i < l ; i ++) { + var current = args[i] + , next = args[i + 1] || "" + , nextMatches = true + , prevMatches = true + if (current === next) continue + for (var j = 0, cl = current.length ; j < cl ; j ++) { + var curChar = current.charAt(j) + nextMatches = nextMatches && curChar === next.charAt(j) + prevMatches = prevMatches && curChar === prev.charAt(j) + if (!nextMatches && !prevMatches) { + j ++ + break + } + } + prev = current + if (j === cl) { + abbrevs[current] = current + continue + } + for (var a = current.substr(0, j) ; j <= cl ; j ++) { + abbrevs[a] = current + a += current.charAt(j) + } + } + return abbrevs +} + +function lexSort (a, b) { + return a === b ? 0 : a > b ? 1 : -1 +} diff --git a/node_modules/abbrev/package.json b/node_modules/abbrev/package.json new file mode 100644 index 0000000..bf4e801 --- /dev/null +++ b/node_modules/abbrev/package.json @@ -0,0 +1,21 @@ +{ + "name": "abbrev", + "version": "1.1.1", + "description": "Like ruby's abbrev module, but in js", + "author": "Isaac Z. Schlueter ", + "main": "abbrev.js", + "scripts": { + "test": "tap test.js --100", + "preversion": "npm test", + "postversion": "npm publish", + "postpublish": "git push origin --all; git push origin --tags" + }, + "repository": "http://github.com/isaacs/abbrev-js", + "license": "ISC", + "devDependencies": { + "tap": "^10.1" + }, + "files": [ + "abbrev.js" + ] +} diff --git a/node_modules/buffer-equal/.travis.yml b/node_modules/buffer-equal/.travis.yml new file mode 100644 index 0000000..dad2273 --- /dev/null +++ b/node_modules/buffer-equal/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.8 + - "0.10" diff --git a/node_modules/buffer-equal/LICENSE b/node_modules/buffer-equal/LICENSE new file mode 100644 index 0000000..ee27ba4 --- /dev/null +++ b/node_modules/buffer-equal/LICENSE @@ -0,0 +1,18 @@ +This software is released under the MIT license: + +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/buffer-equal/README.markdown b/node_modules/buffer-equal/README.markdown new file mode 100644 index 0000000..8c062fd --- /dev/null +++ b/node_modules/buffer-equal/README.markdown @@ -0,0 +1,62 @@ +buffer-equal +============ + +Return whether two buffers are equal. + +[![build status](https://secure.travis-ci.org/substack/node-buffer-equal.png)](http://travis-ci.org/substack/node-buffer-equal) + +example +======= + +``` js +var bufferEqual = require('buffer-equal'); + +console.dir(bufferEqual( + new Buffer([253,254,255]), + new Buffer([253,254,255]) +)); +console.dir(bufferEqual( + new Buffer('abc'), + new Buffer('abcd') +)); +console.dir(bufferEqual( + new Buffer('abc'), + 'abc' +)); +``` + +output: + +``` +true +false +undefined +``` + +methods +======= + +``` js +var bufferEqual = require('buffer-equal') +``` + +bufferEqual(a, b) +----------------- + +Return whether the two buffers `a` and `b` are equal. + +If `a` or `b` is not a buffer, return `undefined`. + +install +======= + +With [npm](http://npmjs.org) do: + +``` +npm install buffer-equal +``` + +license +======= + +MIT diff --git a/node_modules/buffer-equal/example/eq.js b/node_modules/buffer-equal/example/eq.js new file mode 100644 index 0000000..1eb0509 --- /dev/null +++ b/node_modules/buffer-equal/example/eq.js @@ -0,0 +1,14 @@ +var bufferEqual = require('../'); + +console.dir(bufferEqual( + new Buffer([253,254,255]), + new Buffer([253,254,255]) +)); +console.dir(bufferEqual( + new Buffer('abc'), + new Buffer('abcd') +)); +console.dir(bufferEqual( + new Buffer('abc'), + 'abc' +)); diff --git a/node_modules/buffer-equal/index.js b/node_modules/buffer-equal/index.js new file mode 100644 index 0000000..e640d4e --- /dev/null +++ b/node_modules/buffer-equal/index.js @@ -0,0 +1,14 @@ +var Buffer = require('buffer').Buffer; // for use with browserify + +module.exports = function (a, b) { + if (!Buffer.isBuffer(a)) return undefined; + if (!Buffer.isBuffer(b)) return undefined; + if (typeof a.equals === 'function') return a.equals(b); + if (a.length !== b.length) return false; + + for (var i = 0; i < a.length; i++) { + if (a[i] !== b[i]) return false; + } + + return true; +}; diff --git a/node_modules/buffer-equal/package.json b/node_modules/buffer-equal/package.json new file mode 100644 index 0000000..3642209 --- /dev/null +++ b/node_modules/buffer-equal/package.json @@ -0,0 +1,33 @@ +{ + "name" : "buffer-equal", + "description" : "return whether two buffers are equal", + "version" : "0.0.2", + "repository" : { + "type" : "git", + "url" : "git://github.com/substack/node-buffer-equal.git" + }, + "main" : "index.js", + "keywords" : [ + "buffer", + "equal" + ], + "directories" : { + "example" : "example", + "test" : "test" + }, + "scripts" : { + "test" : "tap test/*.js" + }, + "devDependencies" : { + "tap" : "0.2.4" + }, + "engines" : { + "node" : ">=0.4.0" + }, + "license" : "MIT", + "author" : { + "name" : "James Halliday", + "email" : "mail@substack.net", + "url" : "http://substack.net" + } +} diff --git a/node_modules/buffer-equal/test/eq.js b/node_modules/buffer-equal/test/eq.js new file mode 100644 index 0000000..3d34006 --- /dev/null +++ b/node_modules/buffer-equal/test/eq.js @@ -0,0 +1,35 @@ +var bufferEqual = require('../'); +var test = require('tap').test; + +test('equal', function (t) { + var eq = bufferEqual( + new Buffer([253,254,255]), + new Buffer([253,254,255]) + ); + t.strictEqual(eq, true); + t.end(); +}); + +test('not equal', function (t) { + var eq = bufferEqual( + new Buffer('abc'), + new Buffer('abcd') + ); + t.strictEqual(eq, false); + t.end(); +}); + +test('not equal not buffer', function (t) { + var eq = bufferEqual( + new Buffer('abc'), + 'abc' + ); + t.strictEqual(eq, undefined); + t.end(); +}); + +test('equal not buffer', function (t) { + var eq = bufferEqual('abc', 'abc'); + t.strictEqual(eq, undefined); + t.end(); +}); diff --git a/node_modules/bunker/.npmignore b/node_modules/bunker/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/node_modules/bunker/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/bunker/.travis.yml b/node_modules/bunker/.travis.yml new file mode 100644 index 0000000..f1d0f13 --- /dev/null +++ b/node_modules/bunker/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.4 + - 0.6 diff --git a/node_modules/bunker/README.markdown b/node_modules/bunker/README.markdown new file mode 100644 index 0000000..0d0c387 --- /dev/null +++ b/node_modules/bunker/README.markdown @@ -0,0 +1,82 @@ +bunker +====== + +Bunker is a module to calculate code coverage using native javascript +[burrito](https://github.com/substack/node-burrito) AST trickery. + +[![build status](https://secure.travis-ci.org/substack/node-bunker.png)](http://travis-ci.org/substack/node-bunker) + +![code coverage](http://substack.net/images/code_coverage.png) + +examples +======== + +tiny +---- + +````javascript +var bunker = require('bunker'); +var b = bunker('var x = 0; for (var i = 0; i < 30; i++) { x++ }'); + +var counts = {}; + +b.on('node', function (node) { + if (!counts[node.id]) { + counts[node.id] = { times : 0, node : node }; + } + counts[node.id].times ++; +}); + +b.run(); + +Object.keys(counts).forEach(function (key) { + var count = counts[key]; + console.log(count.times + ' : ' + count.node.source()); +}); +```` + +output: + + $ node example/tiny.js + 1 : var x=0; + 31 : i<30 + 30 : i++ + 30 : x++; + 30 : x++ + +methods +======= + +var bunker = require('bunker'); + +var b = bunker(src) +------------------- + +Create a new bunker code coverageifier with some source `src`. + +The bunker object `b` is an `EventEmitter` that emits `'node'` events with two +parameters: + +* `node` - the [burrito](https://github.com/substack/node-burrito) node object +* `stack` - the stack, [stackedy](https://github.com/substack/node-stackedy) style + +b.include(src) +-------------- + +Include some source into the bunker. + +b.compile() +----------- + +Return the source wrapped with burrito. + +b.assign(context={}) +-------------------- + +Assign the statement-tracking functions into `context`. + +b.run(context={}) +----------------- + +Run the source using `vm.runInNewContext()` with some `context`. +The statement-tracking functions will be added to `context` by `assign()`. diff --git a/node_modules/bunker/example/prof.js b/node_modules/bunker/example/prof.js new file mode 100644 index 0000000..5cac4cc --- /dev/null +++ b/node_modules/bunker/example/prof.js @@ -0,0 +1,51 @@ +var bunker = require('bunker'); +var b = bunker('(' + function () { + function beep () { + var x = 0; + for (var i = 0; i < 1000; i++) { + for (var j = 0; j < 100; j++) { + x += j; + } + } + return x; + } + + beep(); + +} + ')()'); + +var counts = {}; + +b.on('node', function (node) { + if (!counts[node.id]) { + counts[node.id] = { times : 0, node : node, elapsed : 0 }; + } + counts[node.id].times ++; + + var now = Date.now(); + + if (last.id !== undefined) { + counts[last.id].elapsed += last. + } + + if (node.name === 'call') { + var start = now; + + last.id = node.id; + counts[node.id].elapsed += Date.now() - start; + } + else { + counts[node.id].elapsed += now - last; + last = now; + } +}); + +b.run(); + +Object.keys(counts).forEach(function (key) { + var count = counts[key]; + console.log( + [ count.times, count.node.source(), count.elapsed ] + .join(' : ') + ); +}); diff --git a/node_modules/bunker/example/tiny.js b/node_modules/bunker/example/tiny.js new file mode 100644 index 0000000..aa5b034 --- /dev/null +++ b/node_modules/bunker/example/tiny.js @@ -0,0 +1,18 @@ +var bunker = require('bunker'); +var b = bunker('var x = 0; for (var i = 0; i < 30; i++) { x++ }'); + +var counts = {}; + +b.on('node', function (node) { + if (!counts[node.id]) { + counts[node.id] = { times : 0, node : node }; + } + counts[node.id].times ++; +}); + +b.run(); + +Object.keys(counts).forEach(function (key) { + var count = counts[key]; + console.log(count.times + ' : ' + count.node.source()); +}); diff --git a/node_modules/bunker/example/top/run.js b/node_modules/bunker/example/top/run.js new file mode 100644 index 0000000..d9eaa10 --- /dev/null +++ b/node_modules/bunker/example/top/run.js @@ -0,0 +1,31 @@ +var bunker = require('bunker'); +var fs = require('fs'); +var src = fs.readFileSync(__dirname + '/src.js', 'utf8'); + +var counts = {}; + +var b = bunker(src); +b.on('node', function (node) { + if (!counts[node.id]) { + counts[node.id] = { times : 0, node : node }; + } + counts[node.id].times ++; +}); + +b.run({ + setInterval : setInterval, + clearInterval : clearInterval, + end : function () { + Object.keys(counts) + .sort(function (a, b) { + return counts[b].times - counts[a].times + }) + .forEach(function (key) { + var count = counts[key]; + console.log( + count.times + ' : ' + count.node.source() + ); + }) + ; + } +}); diff --git a/node_modules/bunker/example/top/src.js b/node_modules/bunker/example/top/src.js new file mode 100644 index 0000000..0c92e48 --- /dev/null +++ b/node_modules/bunker/example/top/src.js @@ -0,0 +1,18 @@ +function boop () { + for (var i = 0; i < 30; i++) { + nop(); + } +} + +function nop () { + return undefined; +} + +var times = 0; +var iv = setInterval(function () { + if (++times === 10) { + clearInterval(iv); + end(); + } + else boop() +}, 100); diff --git a/node_modules/bunker/index.js b/node_modules/bunker/index.js new file mode 100644 index 0000000..ed5d437 --- /dev/null +++ b/node_modules/bunker/index.js @@ -0,0 +1,116 @@ +var burrito = require('burrito'); +var vm = require('vm'); +var EventEmitter = require('events').EventEmitter; + +module.exports = function (src) { + var b = new Bunker(); + if (src) b.include(src); + return b; +}; + +function Bunker () { + this.sources = []; + this.nodes = []; + + this.names = { + call : burrito.generateName(6), + expr : burrito.generateName(6), + stat : burrito.generateName(6), + return : burrito.generateName(6) + }; +} + +Bunker.prototype = new EventEmitter; + +Bunker.prototype.include = function (src) { + this.sources.push(src); + this.source = null; + return this; +}; + +Bunker.prototype.compile = function () { + var src = this.sources.join('\n'); + var nodes = this.nodes; + var names = this.names; + + return burrito(src, function (node) { + var i = nodes.length; + + if (node.name === 'call') { + nodes.push(node); + node.wrap(names.call + '(' + i + ')(%s)'); + } + else if (node.name === 'stat' || node.name === 'throw' + || node.name === 'var') { + nodes.push(node); + node.wrap('{' + names.stat + '(' + i + ');%s}'); + } + else if (node.name === 'return') { + nodes.push(node); + // We need to wrap the new source in a function definition + // so that UglifyJS will allow the presence of return + var stat = names.stat + '(' + i + ');'; + var wrapped = 'function ' + names.return + '() {' + + stat + node.source() + +'}' + ; + var parsed = burrito.parse(wrapped); + // Remove the function definition from the AST + parsed[1] = parsed[1][0][3]; + node.state.update(parsed, true); + } + else if (node.name === 'binary') { + nodes.push(node); + node.wrap(names.expr + '(' + i + ')(%s)'); + } + else if (node.name === 'unary-postfix' || node.name === 'unary-prefix') { + nodes.push(node); + node.wrap(names.expr + '(' + i + ')(%s)'); + } + + if (i !== nodes.length) { + node.id = i; + } + }); +}; + +Bunker.prototype.assign = function (context) { + if (!context) context = {}; + + var self = this; + var stack = []; + + context[self.names.call] = function (i) { + var node = self.nodes[i]; + stack.unshift(node); + self.emit('node', node, stack); + + return function (expr) { + stack.shift(); + return expr; + }; + }; + + context[self.names.expr] = function (i) { + var node = self.nodes[i]; + self.emit('node', node, stack); + + return function (expr) { + return expr; + }; + }; + + context[self.names.stat] = function (i) { + var node = self.nodes[i]; + self.emit('node', node, stack); + }; + + return context; +}; + +Bunker.prototype.run = function (context) { + var src = this.compile(); + vm.runInNewContext(src, this.assign(context)); + + return this; +}; diff --git a/node_modules/bunker/package.json b/node_modules/bunker/package.json new file mode 100644 index 0000000..e7bf398 --- /dev/null +++ b/node_modules/bunker/package.json @@ -0,0 +1,35 @@ +{ + "name" : "bunker", + "version" : "0.1.2", + "description" : "code coverage in native javascript", + "main" : "index.js", + "directories" : { + "lib" : ".", + "example" : "example", + "test" : "test" + }, + "dependencies" : { + "burrito" : ">=0.2.5 <0.3" + }, + "devDependencies" : { + "tap" : "~0.2.4" + }, + "scripts" : { + "test" : "tap test/*.js" + }, + "repository" : { + "type" : "git", + "url" : "http://github.com/substack/node-bunker.git" + }, + "keywords" : [ + "code", + "coverage" + ], + "author" : { + "name" : "James Halliday", + "email" : "mail@substack.net", + "url" : "http://substack.net" + }, + "license" : "MIT/X11", + "engine" : { "node" : ">=0.4" } +} diff --git a/node_modules/bunker/test/cover.js b/node_modules/bunker/test/cover.js new file mode 100644 index 0000000..b04795d --- /dev/null +++ b/node_modules/bunker/test/cover.js @@ -0,0 +1,36 @@ +var test = require('tap').test; +var bunker = require('../'); +var fs = require('fs'); + +var src = fs.readdirSync(__dirname + '/src').reduce(function (acc, file) { + acc[file] = fs.readFileSync(__dirname + '/src/' + file, 'utf8'); + return acc; +}, {}); + +test('cover', function (t) { + t.plan(1); + + var b = bunker(src['cover.js']); + var counts = {}; + + b.on('node', function (node) { + counts[node.name] = (counts[node.name] || 0) + 1; + }); + + b.run({ + setInterval : setInterval, + clearInterval : function () { + process.nextTick(function () { + t.same(counts, { + binary : 11, + 'unary-postfix' : 11, + 'var' : 2, + call : 2, // setInterval and clearInterval + stat : 1, // clearInterval + }); + }); + + return clearInterval.apply(this, arguments); + }, + }); +}); diff --git a/node_modules/bunker/test/return.js b/node_modules/bunker/test/return.js new file mode 100644 index 0000000..9be1700 --- /dev/null +++ b/node_modules/bunker/test/return.js @@ -0,0 +1,29 @@ +var test = require('tap').test; +var bunker = require('../'); + +test('cover', function (t) { + t.plan(1); + + var b = bunker('(' + function () { + function foo () {} + function bar () {} + + (function () { + return foo(); + })(); + } + ')()'); + var counts = {}; + + b.on('node', function (node) { + counts[node.name] = (counts[node.name] || 0) + 1; + }); + b.run(); + + process.nextTick(function () { + t.same(counts, { + stat : 2, + call : 2, + return : 1, + }); + }); +}); diff --git a/node_modules/bunker/test/src/cover.js b/node_modules/bunker/test/src/cover.js new file mode 100644 index 0000000..e640151 --- /dev/null +++ b/node_modules/bunker/test/src/cover.js @@ -0,0 +1,6 @@ +var i = 0; +var iv = setInterval(function () { + if (i++ === 10) { + clearInterval(iv); + } +}, 10); diff --git a/node_modules/burrito/.npmignore b/node_modules/burrito/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/node_modules/burrito/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/burrito/.travis.yml b/node_modules/burrito/.travis.yml new file mode 100644 index 0000000..f1d0f13 --- /dev/null +++ b/node_modules/burrito/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.4 + - 0.6 diff --git a/node_modules/burrito/README.markdown b/node_modules/burrito/README.markdown new file mode 100644 index 0000000..7c9097c --- /dev/null +++ b/node_modules/burrito/README.markdown @@ -0,0 +1,187 @@ +burrito +======= + +Burrito makes it easy to do crazy stuff with the javascript AST. + +This is super useful if you want to roll your own stack traces or build a code +coverage tool. + +[![build status](https://secure.travis-ci.org/substack/node-burrito.png)](http://travis-ci.org/substack/node-burrito) + +![node.wrap("burrito")](http://substack.net/images/burrito.png) + +examples +======== + +microwave +--------- + +examples/microwave.js + +````javascript +var burrito = require('burrito'); + +var res = burrito.microwave('Math.sin(2)', function (node) { + if (node.name === 'num') node.wrap('Math.PI / %s'); +}); + +console.log(res); // sin(pi / 2) == 1 +```` + +output: + + 1 + +wrap +---- + +examples/wrap.js + +````javascript +var burrito = require('burrito'); + +var src = burrito('f() && g(h())\nfoo()', function (node) { + if (node.name === 'call') node.wrap('qqq(%s)'); +}); + +console.log(src); +```` + +output: + + qqq(f()) && qqq(g(qqq(h()))); + + qqq(foo()); + +methods +======= + + var burrito = require('burrito'); + +burrito(code, cb) +----------------- + +Given some source `code` and a function `trace`, walk the ast by expression. + +The `cb` gets called with a node object described below. + +If `code` is an Array then it is assumbed to be an AST which you can generate +yourself with `burrito.parse()`. The AST must be annotated, so make sure to +`burrito.parse(src, false, true)`. + +burrito.microwave(code, context={}, cb) +--------------------------------------- + +Like `burrito()` except the result is run using +`vm.runInNewContext(res, context)`. + +node object +=========== + +node.name +--------- + +Name is a string that contains the type of the expression as named by uglify. + +node.wrap(s) +------------ + +Wrap the current expression in `s`. + +If `s` is a string, `"%s"` will be replaced with the stringified current +expression. + +If `s` is a function, it is called with the stringified current expression and +should return a new stringified expression. + +If the `node.name === "binary"`, you get the subterms "%a" and "%b" to play with +too. These subterms are applied if `s` is a function too: `s(expr, a, b)`. + +Protip: to insert multiple statements you can use javascript's lesser-known block +syntax that it gets from C: + +````javascript +if (node.name === 'stat') node.wrap('{ foo(); %s }') +```` + +node.node +--------- + +raw ast data generated by uglify + +node.value +---------- + +`node.node.slice(1)` to skip the annotations + +node.start +---------- + +The start location of the expression, like this: + +````javascript +{ type: 'name', + value: 'b', + line: 0, + col: 3, + pos: 3, + nlb: false, + comments_before: [] } +```` + +node.end +-------- + +The end location of the expression, formatted the same as `node.start`. + +node.state +---------- + +The state of the traversal using traverse. + +node.source() +------------- + +Returns a stringified version of the expression. + +node.parent() +------------- + +Returns the parent `node` or `null` if the node is the root element. + +node.label() +------------ + +Return the label of the present node or `null` if there is no label. + +Labels are returned for "call", "var", "defun", and "function" nodes. + +Returns an array for "var" nodes since `var` statements can +contain multiple labels in assignment. + +install +======= + +With [npm](http://npmjs.org) you can just: + + npm install burrito + +in the browser +============== + +Burrito works in browser with +[browserify](https://github.com/substack/node-browserify). + +It has been tested against: + +* Internet Explorer 5.5, 6.0, 7.0, 8.0, 9.0 +* Firefox 3.5 +* Chrome 6.0 +* Opera 10.6 +* Safari 5.0 + +kudos +===== + +Heavily inspired by (and previously mostly lifted outright from) isaacs's nifty +tmp/instrument.js thingy from uglify-js. diff --git a/node_modules/burrito/example/microwave.js b/node_modules/burrito/example/microwave.js new file mode 100644 index 0000000..c6fcf45 --- /dev/null +++ b/node_modules/burrito/example/microwave.js @@ -0,0 +1,8 @@ +var burrito = require('burrito'); + +var res = burrito.microwave('Math.sin(2)', function (node) { + console.dir(node); + if (node.name === 'num') node.wrap('Math.PI / %s'); +}); + +console.log(res); // sin(pi / 2) == 1 diff --git a/node_modules/burrito/example/web/bs.js b/node_modules/burrito/example/web/bs.js new file mode 100644 index 0000000..3583c7f --- /dev/null +++ b/node_modules/burrito/example/web/bs.js @@ -0,0 +1,4832 @@ +var require = function (file, cwd) { + var resolved = require.resolve(file, cwd || '/'); + var mod = require.modules[resolved]; + if (!mod) throw new Error( + 'Failed to resolve module ' + file + ', tried ' + resolved + ); + var res = mod._cached ? mod._cached : mod(); + return res; +} +var __require = require; + +require.paths = []; +require.modules = {}; +require.extensions = [".js",".coffee"]; + +require.resolve = (function () { + var core = { + 'assert': true, + 'events': true, + 'fs': true, + 'path': true, + 'vm': true + }; + + return function (x, cwd) { + if (!cwd) cwd = '/'; + + if (core[x]) return x; + var path = require.modules.path(); + var y = cwd || '.'; + + if (x.match(/^(?:\.\.?\/|\/)/)) { + var m = loadAsFileSync(path.resolve(y, x)) + || loadAsDirectorySync(path.resolve(y, x)); + if (m) return m; + } + + var n = loadNodeModulesSync(x, y); + if (n) return n; + + throw new Error("Cannot find module '" + x + "'"); + + function loadAsFileSync (x) { + if (require.modules[x]) { + return x; + } + + for (var i = 0; i < require.extensions.length; i++) { + var ext = require.extensions[i]; + if (require.modules[x + ext]) return x + ext; + } + } + + function loadAsDirectorySync (x) { + x = x.replace(/\/+$/, ''); + var pkgfile = x + '/package.json'; + if (require.modules[pkgfile]) { + var pkg = require.modules[pkgfile](); + var b = pkg.browserify; + if (typeof b === 'object' && b.main) { + var m = loadAsFileSync(path.resolve(x, b.main)); + if (m) return m; + } + else if (typeof b === 'string') { + var m = loadAsFileSync(path.resolve(x, b)); + if (m) return m; + } + else if (pkg.main) { + var m = loadAsFileSync(path.resolve(x, pkg.main)); + if (m) return m; + } + } + + return loadAsFileSync(x + '/index'); + } + + function loadNodeModulesSync (x, start) { + var dirs = nodeModulesPathsSync(start); + for (var i = 0; i < dirs.length; i++) { + var dir = dirs[i]; + var m = loadAsFileSync(dir + '/' + x); + if (m) return m; + var n = loadAsDirectorySync(dir + '/' + x); + if (n) return n; + } + + var m = loadAsFileSync(x); + if (m) return m; + } + + function nodeModulesPathsSync (start) { + var parts; + if (start === '/') parts = [ '' ]; + else parts = path.normalize(start).split('/'); + + var dirs = []; + for (var i = parts.length - 1; i >= 0; i--) { + if (parts[i] === 'node_modules') continue; + var dir = parts.slice(0, i + 1).join('/') + '/node_modules'; + dirs.push(dir); + } + + return dirs; + } + }; +})(); + +require.alias = function (from, to) { + var path = require.modules.path(); + var res = null; + try { + res = require.resolve(from + '/package.json', '/'); + } + catch (err) { + res = require.resolve(from, '/'); + } + var basedir = path.dirname(res); + + var keys = Object_keys(require.modules); + + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + if (key.slice(0, basedir.length + 1) === basedir + '/') { + var f = key.slice(basedir.length); + require.modules[to + f] = require.modules[basedir + f]; + } + else if (key === basedir) { + require.modules[to] = require.modules[basedir]; + } + } +}; + +var Object_keys = Object.keys || function (obj) { + var res = []; + for (var key in obj) res.push(key) + return res; +}; + +if (typeof process === 'undefined') process = {}; + +if (!process.nextTick) process.nextTick = function (fn) { + setTimeout(fn, 0); +}; + +if (!process.title) process.title = 'browser'; + +if (!process.binding) process.binding = function (name) { + if (name === 'evals') return require('vm') + else throw new Error('No such module') +}; + +if (!process.cwd) process.cwd = function () { return '.' }; + +require.modules["path"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "."; + var __filename = "path"; + + var require = function (file) { + return __require(file, "."); + }; + + require.resolve = function (file) { + return __require.resolve(name, "."); + }; + + require.modules = __require.modules; + __require.modules["path"]._cached = module.exports; + + (function () { + function filter (xs, fn) { + var res = []; + for (var i = 0; i < xs.length; i++) { + if (fn(xs[i], i, xs)) res.push(xs[i]); + } + return res; +} + +// resolves . and .. elements in a path array with directory names there +// must be no slashes, empty elements, or device names (c:\) in the array +// (so also no leading and trailing slashes - it does not distinguish +// relative and absolute paths) +function normalizeArray(parts, allowAboveRoot) { + // if the path tries to go above the root, `up` ends up > 0 + var up = 0; + for (var i = parts.length; i >= 0; i--) { + var last = parts[i]; + if (last == '.') { + parts.splice(i, 1); + } else if (last === '..') { + parts.splice(i, 1); + up++; + } else if (up) { + parts.splice(i, 1); + up--; + } + } + + // if the path is allowed to go above the root, restore leading ..s + if (allowAboveRoot) { + for (; up--; up) { + parts.unshift('..'); + } + } + + return parts; +} + +// Regex to split a filename into [*, dir, basename, ext] +// posix version +var splitPathRe = /^(.+\/(?!$)|\/)?((?:.+?)?(\.[^.]*)?)$/; + +// path.resolve([from ...], to) +// posix version +exports.resolve = function() { +var resolvedPath = '', + resolvedAbsolute = false; + +for (var i = arguments.length; i >= -1 && !resolvedAbsolute; i--) { + var path = (i >= 0) + ? arguments[i] + : process.cwd(); + + // Skip empty and invalid entries + if (typeof path !== 'string' || !path) { + continue; + } + + resolvedPath = path + '/' + resolvedPath; + resolvedAbsolute = path.charAt(0) === '/'; +} + +// At this point the path should be resolved to a full absolute path, but +// handle relative paths to be safe (might happen when process.cwd() fails) + +// Normalize the path +resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { + return !!p; + }), !resolvedAbsolute).join('/'); + + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; +}; + +// path.normalize(path) +// posix version +exports.normalize = function(path) { +var isAbsolute = path.charAt(0) === '/', + trailingSlash = path.slice(-1) === '/'; + +// Normalize the path +path = normalizeArray(filter(path.split('/'), function(p) { + return !!p; + }), !isAbsolute).join('/'); + + if (!path && !isAbsolute) { + path = '.'; + } + if (path && trailingSlash) { + path += '/'; + } + + return (isAbsolute ? '/' : '') + path; +}; + + +// posix version +exports.join = function() { + var paths = Array.prototype.slice.call(arguments, 0); + return exports.normalize(filter(paths, function(p, index) { + return p && typeof p === 'string'; + }).join('/')); +}; + + +exports.dirname = function(path) { + var dir = splitPathRe.exec(path)[1] || ''; + var isWindows = false; + if (!dir) { + // No dirname + return '.'; + } else if (dir.length === 1 || + (isWindows && dir.length <= 3 && dir.charAt(1) === ':')) { + // It is just a slash or a drive letter with a slash + return dir; + } else { + // It is a full dirname, strip trailing slash + return dir.substring(0, dir.length - 1); + } +}; + + +exports.basename = function(path, ext) { + var f = splitPathRe.exec(path)[2] || ''; + // TODO: make this comparison case-insensitive on windows? + if (ext && f.substr(-1 * ext.length) === ext) { + f = f.substr(0, f.length - ext.length); + } + return f; +}; + + +exports.extname = function(path) { + return splitPathRe.exec(path)[3] || ''; +}; +; + }).call(module.exports); + + __require.modules["path"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/burrito/package.json"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/burrito"; + var __filename = "/node_modules/burrito/package.json"; + + var require = function (file) { + return __require(file, "/node_modules/burrito"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/burrito"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/burrito/package.json"]._cached = module.exports; + + (function () { + module.exports = {"name":"burrito","description":"Wrap up expressions with a trace function while walking the AST with rice and beans on the side","version":"0.2.8","repository":{"type":"git","url":"git://github.com/substack/node-burrito.git"},"main":"./index.js","keywords":["trace","ast","walk","syntax","source","tree","uglify"],"directories":{"lib":".","example":"example","test":"test"},"scripts":{"test":"expresso"},"dependencies":{"traverse":">=0.5.1 <0.6","uglify-js":"1.0.4"},"devDependencies":{"expresso":"=0.7.x"},"engines":{"node":">=0.4.0"},"license":"BSD","author":{"name":"James Halliday","email":"mail@substack.net","url":"http://substack.net"}}; + }).call(module.exports); + + __require.modules["/node_modules/burrito/package.json"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/burrito/node_modules/uglify-js/package.json"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/burrito/node_modules/uglify-js"; + var __filename = "/node_modules/burrito/node_modules/uglify-js/package.json"; + + var require = function (file) { + return __require(file, "/node_modules/burrito/node_modules/uglify-js"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/burrito/node_modules/uglify-js"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/burrito/node_modules/uglify-js/package.json"]._cached = module.exports; + + (function () { + module.exports = {"name":"uglify-js","author":{"name":"Mihai Bazon","email":"mihai.bazon@gmail.com","url":"http://mihai.bazon.net/blog"},"version":"1.0.4","main":"./uglify-js.js","bin":{"uglifyjs":"./bin/uglifyjs"},"repository":{"type":"git","url":"git@github.com:mishoo/UglifyJS.git"}}; + }).call(module.exports); + + __require.modules["/node_modules/burrito/node_modules/uglify-js/package.json"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/burrito/node_modules/uglify-js/uglify-js.js"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/burrito/node_modules/uglify-js"; + var __filename = "/node_modules/burrito/node_modules/uglify-js/uglify-js.js"; + + var require = function (file) { + return __require(file, "/node_modules/burrito/node_modules/uglify-js"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/burrito/node_modules/uglify-js"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/burrito/node_modules/uglify-js/uglify-js.js"]._cached = module.exports; + + (function () { + //convienence function(src, [options]); +function uglify(orig_code, options){ + options || (options = {}); + var jsp = uglify.parser; + var pro = uglify.uglify; + + var ast = jsp.parse(orig_code, options.strict_semicolons); // parse code and get the initial AST + ast = pro.ast_mangle(ast, options.mangle_options); // get a new AST with mangled names + ast = pro.ast_squeeze(ast, options.squeeze_options); // get an AST with compression optimizations + var final_code = pro.gen_code(ast, options.gen_options); // compressed code here + return final_code; +}; + +uglify.parser = require("./lib/parse-js"); +uglify.uglify = require("./lib/process"); + +module.exports = uglify; + }).call(module.exports); + + __require.modules["/node_modules/burrito/node_modules/uglify-js/uglify-js.js"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/burrito/node_modules/uglify-js/lib/parse-js.js"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/burrito/node_modules/uglify-js/lib"; + var __filename = "/node_modules/burrito/node_modules/uglify-js/lib/parse-js.js"; + + var require = function (file) { + return __require(file, "/node_modules/burrito/node_modules/uglify-js/lib"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/burrito/node_modules/uglify-js/lib"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/burrito/node_modules/uglify-js/lib/parse-js.js"]._cached = module.exports; + + (function () { + /*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + + This version is suitable for Node.js. With minimal changes (the + exports stuff) it should work on any JS platform. + + This file contains the tokenizer/parser. It is a port to JavaScript + of parse-js [1], a JavaScript parser library written in Common Lisp + by Marijn Haverbeke. Thank you Marijn! + + [1] http://marijn.haverbeke.nl/parse-js/ + + Exported functions: + + - tokenizer(code) -- returns a function. Call the returned + function to fetch the next token. + + - parse(code) -- returns an AST of the given JavaScript code. + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2010 (c) Mihai Bazon + Based on parse-js (http://marijn.haverbeke.nl/parse-js/). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +/* -----[ Tokenizer (constants) ]----- */ + +var KEYWORDS = array_to_hash([ + "break", + "case", + "catch", + "const", + "continue", + "default", + "delete", + "do", + "else", + "finally", + "for", + "function", + "if", + "in", + "instanceof", + "new", + "return", + "switch", + "throw", + "try", + "typeof", + "var", + "void", + "while", + "with" +]); + +var RESERVED_WORDS = array_to_hash([ + "abstract", + "boolean", + "byte", + "char", + "class", + "debugger", + "double", + "enum", + "export", + "extends", + "final", + "float", + "goto", + "implements", + "import", + "int", + "interface", + "long", + "native", + "package", + "private", + "protected", + "public", + "short", + "static", + "super", + "synchronized", + "throws", + "transient", + "volatile" +]); + +var KEYWORDS_BEFORE_EXPRESSION = array_to_hash([ + "return", + "new", + "delete", + "throw", + "else", + "case" +]); + +var KEYWORDS_ATOM = array_to_hash([ + "false", + "null", + "true", + "undefined" +]); + +var OPERATOR_CHARS = array_to_hash(characters("+-*&%=<>!?|~^")); + +var RE_HEX_NUMBER = /^0x[0-9a-f]+$/i; +var RE_OCT_NUMBER = /^0[0-7]+$/; +var RE_DEC_NUMBER = /^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i; + +var OPERATORS = array_to_hash([ + "in", + "instanceof", + "typeof", + "new", + "void", + "delete", + "++", + "--", + "+", + "-", + "!", + "~", + "&", + "|", + "^", + "*", + "/", + "%", + ">>", + "<<", + ">>>", + "<", + ">", + "<=", + ">=", + "==", + "===", + "!=", + "!==", + "?", + "=", + "+=", + "-=", + "/=", + "*=", + "%=", + ">>=", + "<<=", + ">>>=", + "|=", + "^=", + "&=", + "&&", + "||" +]); + +var WHITESPACE_CHARS = array_to_hash(characters(" \u00a0\n\r\t\f\v\u200b")); + +var PUNC_BEFORE_EXPRESSION = array_to_hash(characters("[{}(,.;:")); + +var PUNC_CHARS = array_to_hash(characters("[]{}(),;:")); + +var REGEXP_MODIFIERS = array_to_hash(characters("gmsiy")); + +/* -----[ Tokenizer ]----- */ + +// regexps adapted from http://xregexp.com/plugins/#unicode +var UNICODE = { + letter: new RegExp("[\\u0041-\\u005A\\u0061-\\u007A\\u00AA\\u00B5\\u00BA\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u0523\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0621-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971\\u0972\\u097B-\\u097F\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C33\\u0C35-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D28\\u0D2A-\\u0D39\\u0D3D\\u0D60\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC\\u0EDD\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8B\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10D0-\\u10FA\\u10FC\\u1100-\\u1159\\u115F-\\u11A2\\u11A8-\\u11F9\\u1200-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u1676\\u1681-\\u169A\\u16A0-\\u16EA\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u1900-\\u191C\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19A9\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u2094\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2183\\u2184\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2C6F\\u2C71-\\u2C7D\\u2C80-\\u2CE4\\u2D00-\\u2D25\\u2D30-\\u2D65\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005\\u3006\\u3031-\\u3035\\u303B\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31B7\\u31F0-\\u31FF\\u3400\\u4DB5\\u4E00\\u9FC3\\uA000-\\uA48C\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA65F\\uA662-\\uA66E\\uA67F-\\uA697\\uA717-\\uA71F\\uA722-\\uA788\\uA78B\\uA78C\\uA7FB-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA90A-\\uA925\\uA930-\\uA946\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAC00\\uD7A3\\uF900-\\uFA2D\\uFA30-\\uFA6A\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]"), + non_spacing_mark: new RegExp("[\\u0300-\\u036F\\u0483-\\u0487\\u0591-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u05C5\\u05C7\\u0610-\\u061A\\u064B-\\u065E\\u0670\\u06D6-\\u06DC\\u06DF-\\u06E4\\u06E7\\u06E8\\u06EA-\\u06ED\\u0711\\u0730-\\u074A\\u07A6-\\u07B0\\u07EB-\\u07F3\\u0816-\\u0819\\u081B-\\u0823\\u0825-\\u0827\\u0829-\\u082D\\u0900-\\u0902\\u093C\\u0941-\\u0948\\u094D\\u0951-\\u0955\\u0962\\u0963\\u0981\\u09BC\\u09C1-\\u09C4\\u09CD\\u09E2\\u09E3\\u0A01\\u0A02\\u0A3C\\u0A41\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A51\\u0A70\\u0A71\\u0A75\\u0A81\\u0A82\\u0ABC\\u0AC1-\\u0AC5\\u0AC7\\u0AC8\\u0ACD\\u0AE2\\u0AE3\\u0B01\\u0B3C\\u0B3F\\u0B41-\\u0B44\\u0B4D\\u0B56\\u0B62\\u0B63\\u0B82\\u0BC0\\u0BCD\\u0C3E-\\u0C40\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C62\\u0C63\\u0CBC\\u0CBF\\u0CC6\\u0CCC\\u0CCD\\u0CE2\\u0CE3\\u0D41-\\u0D44\\u0D4D\\u0D62\\u0D63\\u0DCA\\u0DD2-\\u0DD4\\u0DD6\\u0E31\\u0E34-\\u0E3A\\u0E47-\\u0E4E\\u0EB1\\u0EB4-\\u0EB9\\u0EBB\\u0EBC\\u0EC8-\\u0ECD\\u0F18\\u0F19\\u0F35\\u0F37\\u0F39\\u0F71-\\u0F7E\\u0F80-\\u0F84\\u0F86\\u0F87\\u0F90-\\u0F97\\u0F99-\\u0FBC\\u0FC6\\u102D-\\u1030\\u1032-\\u1037\\u1039\\u103A\\u103D\\u103E\\u1058\\u1059\\u105E-\\u1060\\u1071-\\u1074\\u1082\\u1085\\u1086\\u108D\\u109D\\u135F\\u1712-\\u1714\\u1732-\\u1734\\u1752\\u1753\\u1772\\u1773\\u17B7-\\u17BD\\u17C6\\u17C9-\\u17D3\\u17DD\\u180B-\\u180D\\u18A9\\u1920-\\u1922\\u1927\\u1928\\u1932\\u1939-\\u193B\\u1A17\\u1A18\\u1A56\\u1A58-\\u1A5E\\u1A60\\u1A62\\u1A65-\\u1A6C\\u1A73-\\u1A7C\\u1A7F\\u1B00-\\u1B03\\u1B34\\u1B36-\\u1B3A\\u1B3C\\u1B42\\u1B6B-\\u1B73\\u1B80\\u1B81\\u1BA2-\\u1BA5\\u1BA8\\u1BA9\\u1C2C-\\u1C33\\u1C36\\u1C37\\u1CD0-\\u1CD2\\u1CD4-\\u1CE0\\u1CE2-\\u1CE8\\u1CED\\u1DC0-\\u1DE6\\u1DFD-\\u1DFF\\u20D0-\\u20DC\\u20E1\\u20E5-\\u20F0\\u2CEF-\\u2CF1\\u2DE0-\\u2DFF\\u302A-\\u302F\\u3099\\u309A\\uA66F\\uA67C\\uA67D\\uA6F0\\uA6F1\\uA802\\uA806\\uA80B\\uA825\\uA826\\uA8C4\\uA8E0-\\uA8F1\\uA926-\\uA92D\\uA947-\\uA951\\uA980-\\uA982\\uA9B3\\uA9B6-\\uA9B9\\uA9BC\\uAA29-\\uAA2E\\uAA31\\uAA32\\uAA35\\uAA36\\uAA43\\uAA4C\\uAAB0\\uAAB2-\\uAAB4\\uAAB7\\uAAB8\\uAABE\\uAABF\\uAAC1\\uABE5\\uABE8\\uABED\\uFB1E\\uFE00-\\uFE0F\\uFE20-\\uFE26]"), + space_combining_mark: new RegExp("[\\u0903\\u093E-\\u0940\\u0949-\\u094C\\u094E\\u0982\\u0983\\u09BE-\\u09C0\\u09C7\\u09C8\\u09CB\\u09CC\\u09D7\\u0A03\\u0A3E-\\u0A40\\u0A83\\u0ABE-\\u0AC0\\u0AC9\\u0ACB\\u0ACC\\u0B02\\u0B03\\u0B3E\\u0B40\\u0B47\\u0B48\\u0B4B\\u0B4C\\u0B57\\u0BBE\\u0BBF\\u0BC1\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCC\\u0BD7\\u0C01-\\u0C03\\u0C41-\\u0C44\\u0C82\\u0C83\\u0CBE\\u0CC0-\\u0CC4\\u0CC7\\u0CC8\\u0CCA\\u0CCB\\u0CD5\\u0CD6\\u0D02\\u0D03\\u0D3E-\\u0D40\\u0D46-\\u0D48\\u0D4A-\\u0D4C\\u0D57\\u0D82\\u0D83\\u0DCF-\\u0DD1\\u0DD8-\\u0DDF\\u0DF2\\u0DF3\\u0F3E\\u0F3F\\u0F7F\\u102B\\u102C\\u1031\\u1038\\u103B\\u103C\\u1056\\u1057\\u1062-\\u1064\\u1067-\\u106D\\u1083\\u1084\\u1087-\\u108C\\u108F\\u109A-\\u109C\\u17B6\\u17BE-\\u17C5\\u17C7\\u17C8\\u1923-\\u1926\\u1929-\\u192B\\u1930\\u1931\\u1933-\\u1938\\u19B0-\\u19C0\\u19C8\\u19C9\\u1A19-\\u1A1B\\u1A55\\u1A57\\u1A61\\u1A63\\u1A64\\u1A6D-\\u1A72\\u1B04\\u1B35\\u1B3B\\u1B3D-\\u1B41\\u1B43\\u1B44\\u1B82\\u1BA1\\u1BA6\\u1BA7\\u1BAA\\u1C24-\\u1C2B\\u1C34\\u1C35\\u1CE1\\u1CF2\\uA823\\uA824\\uA827\\uA880\\uA881\\uA8B4-\\uA8C3\\uA952\\uA953\\uA983\\uA9B4\\uA9B5\\uA9BA\\uA9BB\\uA9BD-\\uA9C0\\uAA2F\\uAA30\\uAA33\\uAA34\\uAA4D\\uAA7B\\uABE3\\uABE4\\uABE6\\uABE7\\uABE9\\uABEA\\uABEC]"), + connector_punctuation: new RegExp("[\\u005F\\u203F\\u2040\\u2054\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFF3F]") +}; + +function is_letter(ch) { + return UNICODE.letter.test(ch); +}; + +function is_digit(ch) { + ch = ch.charCodeAt(0); + return ch >= 48 && ch <= 57; //XXX: find out if "UnicodeDigit" means something else than 0..9 +}; + +function is_alphanumeric_char(ch) { + return is_digit(ch) || is_letter(ch); +}; + +function is_unicode_combining_mark(ch) { + return UNICODE.non_spacing_mark.test(ch) || UNICODE.space_combining_mark.test(ch); +}; + +function is_unicode_connector_punctuation(ch) { + return UNICODE.connector_punctuation.test(ch); +}; + +function is_identifier_start(ch) { + return ch == "$" || ch == "_" || is_letter(ch); +}; + +function is_identifier_char(ch) { + return is_identifier_start(ch) + || is_unicode_combining_mark(ch) + || is_digit(ch) + || is_unicode_connector_punctuation(ch) + || ch == "\u200c" // zero-width non-joiner + || ch == "\u200d" // zero-width joiner (in my ECMA-262 PDF, this is also 200c) + ; +}; + +function parse_js_number(num) { + if (RE_HEX_NUMBER.test(num)) { + return parseInt(num.substr(2), 16); + } else if (RE_OCT_NUMBER.test(num)) { + return parseInt(num.substr(1), 8); + } else if (RE_DEC_NUMBER.test(num)) { + return parseFloat(num); + } +}; + +function JS_Parse_Error(message, line, col, pos) { + this.message = message; + this.line = line; + this.col = col; + this.pos = pos; + try { + ({})(); + } catch(ex) { + this.stack = ex.stack; + }; +}; + +JS_Parse_Error.prototype.toString = function() { + return this.message + " (line: " + this.line + ", col: " + this.col + ", pos: " + this.pos + ")" + "\n\n" + this.stack; +}; + +function js_error(message, line, col, pos) { + throw new JS_Parse_Error(message, line, col, pos); +}; + +function is_token(token, type, val) { + return token.type == type && (val == null || token.value == val); +}; + +var EX_EOF = {}; + +function tokenizer($TEXT) { + + var S = { + text : $TEXT.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, ''), + pos : 0, + tokpos : 0, + line : 0, + tokline : 0, + col : 0, + tokcol : 0, + newline_before : false, + regex_allowed : false, + comments_before : [] + }; + + function peek() { return S.text.charAt(S.pos); }; + + function next(signal_eof) { + var ch = S.text.charAt(S.pos++); + if (signal_eof && !ch) + throw EX_EOF; + if (ch == "\n") { + S.newline_before = true; + ++S.line; + S.col = 0; + } else { + ++S.col; + } + return ch; + }; + + function eof() { + return !S.peek(); + }; + + function find(what, signal_eof) { + var pos = S.text.indexOf(what, S.pos); + if (signal_eof && pos == -1) throw EX_EOF; + return pos; + }; + + function start_token() { + S.tokline = S.line; + S.tokcol = S.col; + S.tokpos = S.pos; + }; + + function token(type, value, is_comment) { + S.regex_allowed = ((type == "operator" && !HOP(UNARY_POSTFIX, value)) || + (type == "keyword" && HOP(KEYWORDS_BEFORE_EXPRESSION, value)) || + (type == "punc" && HOP(PUNC_BEFORE_EXPRESSION, value))); + var ret = { + type : type, + value : value, + line : S.tokline, + col : S.tokcol, + pos : S.tokpos, + nlb : S.newline_before + }; + if (!is_comment) { + ret.comments_before = S.comments_before; + S.comments_before = []; + } + S.newline_before = false; + return ret; + }; + + function skip_whitespace() { + while (HOP(WHITESPACE_CHARS, peek())) + next(); + }; + + function read_while(pred) { + var ret = "", ch = peek(), i = 0; + while (ch && pred(ch, i++)) { + ret += next(); + ch = peek(); + } + return ret; + }; + + function parse_error(err) { + js_error(err, S.tokline, S.tokcol, S.tokpos); + }; + + function read_num(prefix) { + var has_e = false, after_e = false, has_x = false, has_dot = prefix == "."; + var num = read_while(function(ch, i){ + if (ch == "x" || ch == "X") { + if (has_x) return false; + return has_x = true; + } + if (!has_x && (ch == "E" || ch == "e")) { + if (has_e) return false; + return has_e = after_e = true; + } + if (ch == "-") { + if (after_e || (i == 0 && !prefix)) return true; + return false; + } + if (ch == "+") return after_e; + after_e = false; + if (ch == ".") { + if (!has_dot && !has_x) + return has_dot = true; + return false; + } + return is_alphanumeric_char(ch); + }); + if (prefix) + num = prefix + num; + var valid = parse_js_number(num); + if (!isNaN(valid)) { + return token("num", valid); + } else { + parse_error("Invalid syntax: " + num); + } + }; + + function read_escaped_char() { + var ch = next(true); + switch (ch) { + case "n" : return "\n"; + case "r" : return "\r"; + case "t" : return "\t"; + case "b" : return "\b"; + case "v" : return "\v"; + case "f" : return "\f"; + case "0" : return "\0"; + case "x" : return String.fromCharCode(hex_bytes(2)); + case "u" : return String.fromCharCode(hex_bytes(4)); + default : return ch; + } + }; + + function hex_bytes(n) { + var num = 0; + for (; n > 0; --n) { + var digit = parseInt(next(true), 16); + if (isNaN(digit)) + parse_error("Invalid hex-character pattern in string"); + num = (num << 4) | digit; + } + return num; + }; + + function read_string() { + return with_eof_error("Unterminated string constant", function(){ + var quote = next(), ret = ""; + for (;;) { + var ch = next(true); + if (ch == "\\") ch = read_escaped_char(); + else if (ch == quote) break; + ret += ch; + } + return token("string", ret); + }); + }; + + function read_line_comment() { + next(); + var i = find("\n"), ret; + if (i == -1) { + ret = S.text.substr(S.pos); + S.pos = S.text.length; + } else { + ret = S.text.substring(S.pos, i); + S.pos = i; + } + return token("comment1", ret, true); + }; + + function read_multiline_comment() { + next(); + return with_eof_error("Unterminated multiline comment", function(){ + var i = find("*/", true), + text = S.text.substring(S.pos, i), + tok = token("comment2", text, true); + S.pos = i + 2; + S.line += text.split("\n").length - 1; + S.newline_before = text.indexOf("\n") >= 0; + + // https://github.com/mishoo/UglifyJS/issues/#issue/100 + if (/^@cc_on/i.test(text)) { + warn("WARNING: at line " + S.line); + warn("*** Found \"conditional comment\": " + text); + warn("*** UglifyJS DISCARDS ALL COMMENTS. This means your code might no longer work properly in Internet Explorer."); + } + + return tok; + }); + }; + + function read_name() { + var backslash = false, name = "", ch; + while ((ch = peek()) != null) { + if (!backslash) { + if (ch == "\\") backslash = true, next(); + else if (is_identifier_char(ch)) name += next(); + else break; + } + else { + if (ch != "u") parse_error("Expecting UnicodeEscapeSequence -- uXXXX"); + ch = read_escaped_char(); + if (!is_identifier_char(ch)) parse_error("Unicode char: " + ch.charCodeAt(0) + " is not valid in identifier"); + name += ch; + backslash = false; + } + } + return name; + }; + + function read_regexp() { + return with_eof_error("Unterminated regular expression", function(){ + var prev_backslash = false, regexp = "", ch, in_class = false; + while ((ch = next(true))) if (prev_backslash) { + regexp += "\\" + ch; + prev_backslash = false; + } else if (ch == "[") { + in_class = true; + regexp += ch; + } else if (ch == "]" && in_class) { + in_class = false; + regexp += ch; + } else if (ch == "/" && !in_class) { + break; + } else if (ch == "\\") { + prev_backslash = true; + } else { + regexp += ch; + } + var mods = read_name(); + return token("regexp", [ regexp, mods ]); + }); + }; + + function read_operator(prefix) { + function grow(op) { + if (!peek()) return op; + var bigger = op + peek(); + if (HOP(OPERATORS, bigger)) { + next(); + return grow(bigger); + } else { + return op; + } + }; + return token("operator", grow(prefix || next())); + }; + + function handle_slash() { + next(); + var regex_allowed = S.regex_allowed; + switch (peek()) { + case "/": + S.comments_before.push(read_line_comment()); + S.regex_allowed = regex_allowed; + return next_token(); + case "*": + S.comments_before.push(read_multiline_comment()); + S.regex_allowed = regex_allowed; + return next_token(); + } + return S.regex_allowed ? read_regexp() : read_operator("/"); + }; + + function handle_dot() { + next(); + return is_digit(peek()) + ? read_num(".") + : token("punc", "."); + }; + + function read_word() { + var word = read_name(); + return !HOP(KEYWORDS, word) + ? token("name", word) + : HOP(OPERATORS, word) + ? token("operator", word) + : HOP(KEYWORDS_ATOM, word) + ? token("atom", word) + : token("keyword", word); + }; + + function with_eof_error(eof_error, cont) { + try { + return cont(); + } catch(ex) { + if (ex === EX_EOF) parse_error(eof_error); + else throw ex; + } + }; + + function next_token(force_regexp) { + if (force_regexp) + return read_regexp(); + skip_whitespace(); + start_token(); + var ch = peek(); + if (!ch) return token("eof"); + if (is_digit(ch)) return read_num(); + if (ch == '"' || ch == "'") return read_string(); + if (HOP(PUNC_CHARS, ch)) return token("punc", next()); + if (ch == ".") return handle_dot(); + if (ch == "/") return handle_slash(); + if (HOP(OPERATOR_CHARS, ch)) return read_operator(); + if (ch == "\\" || is_identifier_start(ch)) return read_word(); + parse_error("Unexpected character '" + ch + "'"); + }; + + next_token.context = function(nc) { + if (nc) S = nc; + return S; + }; + + return next_token; + +}; + +/* -----[ Parser (constants) ]----- */ + +var UNARY_PREFIX = array_to_hash([ + "typeof", + "void", + "delete", + "--", + "++", + "!", + "~", + "-", + "+" +]); + +var UNARY_POSTFIX = array_to_hash([ "--", "++" ]); + +var ASSIGNMENT = (function(a, ret, i){ + while (i < a.length) { + ret[a[i]] = a[i].substr(0, a[i].length - 1); + i++; + } + return ret; +})( + ["+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&="], + { "=": true }, + 0 +); + +var PRECEDENCE = (function(a, ret){ + for (var i = 0, n = 1; i < a.length; ++i, ++n) { + var b = a[i]; + for (var j = 0; j < b.length; ++j) { + ret[b[j]] = n; + } + } + return ret; +})( + [ + ["||"], + ["&&"], + ["|"], + ["^"], + ["&"], + ["==", "===", "!=", "!=="], + ["<", ">", "<=", ">=", "in", "instanceof"], + [">>", "<<", ">>>"], + ["+", "-"], + ["*", "/", "%"] + ], + {} +); + +var STATEMENTS_WITH_LABELS = array_to_hash([ "for", "do", "while", "switch" ]); + +var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "name" ]); + +/* -----[ Parser ]----- */ + +function NodeWithToken(str, start, end) { + this.name = str; + this.start = start; + this.end = end; +}; + +NodeWithToken.prototype.toString = function() { return this.name; }; + +function parse($TEXT, exigent_mode, embed_tokens) { + + var S = { + input : typeof $TEXT == "string" ? tokenizer($TEXT, true) : $TEXT, + token : null, + prev : null, + peeked : null, + in_function : 0, + in_loop : 0, + labels : [] + }; + + S.token = next(); + + function is(type, value) { + return is_token(S.token, type, value); + }; + + function peek() { return S.peeked || (S.peeked = S.input()); }; + + function next() { + S.prev = S.token; + if (S.peeked) { + S.token = S.peeked; + S.peeked = null; + } else { + S.token = S.input(); + } + return S.token; + }; + + function prev() { + return S.prev; + }; + + function croak(msg, line, col, pos) { + var ctx = S.input.context(); + js_error(msg, + line != null ? line : ctx.tokline, + col != null ? col : ctx.tokcol, + pos != null ? pos : ctx.tokpos); + }; + + function token_error(token, msg) { + croak(msg, token.line, token.col); + }; + + function unexpected(token) { + if (token == null) + token = S.token; + token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")"); + }; + + function expect_token(type, val) { + if (is(type, val)) { + return next(); + } + token_error(S.token, "Unexpected token " + S.token.type + ", expected " + type); + }; + + function expect(punc) { return expect_token("punc", punc); }; + + function can_insert_semicolon() { + return !exigent_mode && ( + S.token.nlb || is("eof") || is("punc", "}") + ); + }; + + function semicolon() { + if (is("punc", ";")) next(); + else if (!can_insert_semicolon()) unexpected(); + }; + + function as() { + return slice(arguments); + }; + + function parenthesised() { + expect("("); + var ex = expression(); + expect(")"); + return ex; + }; + + function add_tokens(str, start, end) { + return str instanceof NodeWithToken ? str : new NodeWithToken(str, start, end); + }; + + function maybe_embed_tokens(parser) { + if (embed_tokens) return function() { + var start = S.token; + var ast = parser.apply(this, arguments); + ast[0] = add_tokens(ast[0], start, prev()); + return ast; + }; + else return parser; + }; + + var statement = maybe_embed_tokens(function() { + if (is("operator", "/")) { + S.peeked = null; + S.token = S.input(true); // force regexp + } + switch (S.token.type) { + case "num": + case "string": + case "regexp": + case "operator": + case "atom": + return simple_statement(); + + case "name": + return is_token(peek(), "punc", ":") + ? labeled_statement(prog1(S.token.value, next, next)) + : simple_statement(); + + case "punc": + switch (S.token.value) { + case "{": + return as("block", block_()); + case "[": + case "(": + return simple_statement(); + case ";": + next(); + return as("block"); + default: + unexpected(); + } + + case "keyword": + switch (prog1(S.token.value, next)) { + case "break": + return break_cont("break"); + + case "continue": + return break_cont("continue"); + + case "debugger": + semicolon(); + return as("debugger"); + + case "do": + return (function(body){ + expect_token("keyword", "while"); + return as("do", prog1(parenthesised, semicolon), body); + })(in_loop(statement)); + + case "for": + return for_(); + + case "function": + return function_(true); + + case "if": + return if_(); + + case "return": + if (S.in_function == 0) + croak("'return' outside of function"); + return as("return", + is("punc", ";") + ? (next(), null) + : can_insert_semicolon() + ? null + : prog1(expression, semicolon)); + + case "switch": + return as("switch", parenthesised(), switch_block_()); + + case "throw": + return as("throw", prog1(expression, semicolon)); + + case "try": + return try_(); + + case "var": + return prog1(var_, semicolon); + + case "const": + return prog1(const_, semicolon); + + case "while": + return as("while", parenthesised(), in_loop(statement)); + + case "with": + return as("with", parenthesised(), statement()); + + default: + unexpected(); + } + } + }); + + function labeled_statement(label) { + S.labels.push(label); + var start = S.token, stat = statement(); + if (exigent_mode && !HOP(STATEMENTS_WITH_LABELS, stat[0])) + unexpected(start); + S.labels.pop(); + return as("label", label, stat); + }; + + function simple_statement() { + return as("stat", prog1(expression, semicolon)); + }; + + function break_cont(type) { + var name; + if (!can_insert_semicolon()) { + name = is("name") ? S.token.value : null; + } + if (name != null) { + next(); + if (!member(name, S.labels)) + croak("Label " + name + " without matching loop or statement"); + } + else if (S.in_loop == 0) + croak(type + " not inside a loop or switch"); + semicolon(); + return as(type, name); + }; + + function for_() { + expect("("); + var init = null; + if (!is("punc", ";")) { + init = is("keyword", "var") + ? (next(), var_(true)) + : expression(true, true); + if (is("operator", "in")) + return for_in(init); + } + return regular_for(init); + }; + + function regular_for(init) { + expect(";"); + var test = is("punc", ";") ? null : expression(); + expect(";"); + var step = is("punc", ")") ? null : expression(); + expect(")"); + return as("for", init, test, step, in_loop(statement)); + }; + + function for_in(init) { + var lhs = init[0] == "var" ? as("name", init[1][0]) : init; + next(); + var obj = expression(); + expect(")"); + return as("for-in", init, lhs, obj, in_loop(statement)); + }; + + var function_ = maybe_embed_tokens(function(in_statement) { + var name = is("name") ? prog1(S.token.value, next) : null; + if (in_statement && !name) + unexpected(); + expect("("); + return as(in_statement ? "defun" : "function", + name, + // arguments + (function(first, a){ + while (!is("punc", ")")) { + if (first) first = false; else expect(","); + if (!is("name")) unexpected(); + a.push(S.token.value); + next(); + } + next(); + return a; + })(true, []), + // body + (function(){ + ++S.in_function; + var loop = S.in_loop; + S.in_loop = 0; + var a = block_(); + --S.in_function; + S.in_loop = loop; + return a; + })()); + }); + + function if_() { + var cond = parenthesised(), body = statement(), belse; + if (is("keyword", "else")) { + next(); + belse = statement(); + } + return as("if", cond, body, belse); + }; + + function block_() { + expect("{"); + var a = []; + while (!is("punc", "}")) { + if (is("eof")) unexpected(); + a.push(statement()); + } + next(); + return a; + }; + + var switch_block_ = curry(in_loop, function(){ + expect("{"); + var a = [], cur = null; + while (!is("punc", "}")) { + if (is("eof")) unexpected(); + if (is("keyword", "case")) { + next(); + cur = []; + a.push([ expression(), cur ]); + expect(":"); + } + else if (is("keyword", "default")) { + next(); + expect(":"); + cur = []; + a.push([ null, cur ]); + } + else { + if (!cur) unexpected(); + cur.push(statement()); + } + } + next(); + return a; + }); + + function try_() { + var body = block_(), bcatch, bfinally; + if (is("keyword", "catch")) { + next(); + expect("("); + if (!is("name")) + croak("Name expected"); + var name = S.token.value; + next(); + expect(")"); + bcatch = [ name, block_() ]; + } + if (is("keyword", "finally")) { + next(); + bfinally = block_(); + } + if (!bcatch && !bfinally) + croak("Missing catch/finally blocks"); + return as("try", body, bcatch, bfinally); + }; + + function vardefs(no_in) { + var a = []; + for (;;) { + if (!is("name")) + unexpected(); + var name = S.token.value; + next(); + if (is("operator", "=")) { + next(); + a.push([ name, expression(false, no_in) ]); + } else { + a.push([ name ]); + } + if (!is("punc", ",")) + break; + next(); + } + return a; + }; + + function var_(no_in) { + return as("var", vardefs(no_in)); + }; + + function const_() { + return as("const", vardefs()); + }; + + function new_() { + var newexp = expr_atom(false), args; + if (is("punc", "(")) { + next(); + args = expr_list(")"); + } else { + args = []; + } + return subscripts(as("new", newexp, args), true); + }; + + var expr_atom = maybe_embed_tokens(function(allow_calls) { + if (is("operator", "new")) { + next(); + return new_(); + } + if (is("operator") && HOP(UNARY_PREFIX, S.token.value)) { + return make_unary("unary-prefix", + prog1(S.token.value, next), + expr_atom(allow_calls)); + } + if (is("punc")) { + switch (S.token.value) { + case "(": + next(); + return subscripts(prog1(expression, curry(expect, ")")), allow_calls); + case "[": + next(); + return subscripts(array_(), allow_calls); + case "{": + next(); + return subscripts(object_(), allow_calls); + } + unexpected(); + } + if (is("keyword", "function")) { + next(); + return subscripts(function_(false), allow_calls); + } + if (HOP(ATOMIC_START_TOKEN, S.token.type)) { + var atom = S.token.type == "regexp" + ? as("regexp", S.token.value[0], S.token.value[1]) + : as(S.token.type, S.token.value); + return subscripts(prog1(atom, next), allow_calls); + } + unexpected(); + }); + + function expr_list(closing, allow_trailing_comma, allow_empty) { + var first = true, a = []; + while (!is("punc", closing)) { + if (first) first = false; else expect(","); + if (allow_trailing_comma && is("punc", closing)) break; + if (is("punc", ",") && allow_empty) { + a.push([ "atom", "undefined" ]); + } else { + a.push(expression(false)); + } + } + next(); + return a; + }; + + function array_() { + return as("array", expr_list("]", !exigent_mode, true)); + }; + + function object_() { + var first = true, a = []; + while (!is("punc", "}")) { + if (first) first = false; else expect(","); + if (!exigent_mode && is("punc", "}")) + // allow trailing comma + break; + var type = S.token.type; + var name = as_property_name(); + if (type == "name" && (name == "get" || name == "set") && !is("punc", ":")) { + a.push([ as_name(), function_(false), name ]); + } else { + expect(":"); + a.push([ name, expression(false) ]); + } + } + next(); + return as("object", a); + }; + + function as_property_name() { + switch (S.token.type) { + case "num": + case "string": + return prog1(S.token.value, next); + } + return as_name(); + }; + + function as_name() { + switch (S.token.type) { + case "name": + case "operator": + case "keyword": + case "atom": + return prog1(S.token.value, next); + default: + unexpected(); + } + }; + + function subscripts(expr, allow_calls) { + if (is("punc", ".")) { + next(); + return subscripts(as("dot", expr, as_name()), allow_calls); + } + if (is("punc", "[")) { + next(); + return subscripts(as("sub", expr, prog1(expression, curry(expect, "]"))), allow_calls); + } + if (allow_calls && is("punc", "(")) { + next(); + return subscripts(as("call", expr, expr_list(")")), true); + } + if (allow_calls && is("operator") && HOP(UNARY_POSTFIX, S.token.value)) { + return prog1(curry(make_unary, "unary-postfix", S.token.value, expr), + next); + } + return expr; + }; + + function make_unary(tag, op, expr) { + if ((op == "++" || op == "--") && !is_assignable(expr)) + croak("Invalid use of " + op + " operator"); + return as(tag, op, expr); + }; + + function expr_op(left, min_prec, no_in) { + var op = is("operator") ? S.token.value : null; + if (op && op == "in" && no_in) op = null; + var prec = op != null ? PRECEDENCE[op] : null; + if (prec != null && prec > min_prec) { + next(); + var right = expr_op(expr_atom(true), prec, no_in); + return expr_op(as("binary", op, left, right), min_prec, no_in); + } + return left; + }; + + function expr_ops(no_in) { + return expr_op(expr_atom(true), 0, no_in); + }; + + function maybe_conditional(no_in) { + var expr = expr_ops(no_in); + if (is("operator", "?")) { + next(); + var yes = expression(false); + expect(":"); + return as("conditional", expr, yes, expression(false, no_in)); + } + return expr; + }; + + function is_assignable(expr) { + if (!exigent_mode) return true; + switch (expr[0]) { + case "dot": + case "sub": + case "new": + case "call": + return true; + case "name": + return expr[1] != "this"; + } + }; + + function maybe_assign(no_in) { + var left = maybe_conditional(no_in), val = S.token.value; + if (is("operator") && HOP(ASSIGNMENT, val)) { + if (is_assignable(left)) { + next(); + return as("assign", ASSIGNMENT[val], left, maybe_assign(no_in)); + } + croak("Invalid assignment"); + } + return left; + }; + + var expression = maybe_embed_tokens(function(commas, no_in) { + if (arguments.length == 0) + commas = true; + var expr = maybe_assign(no_in); + if (commas && is("punc", ",")) { + next(); + return as("seq", expr, expression(true, no_in)); + } + return expr; + }); + + function in_loop(cont) { + try { + ++S.in_loop; + return cont(); + } finally { + --S.in_loop; + } + }; + + return as("toplevel", (function(a){ + while (!is("eof")) + a.push(statement()); + return a; + })([])); + +}; + +/* -----[ Utilities ]----- */ + +function curry(f) { + var args = slice(arguments, 1); + return function() { return f.apply(this, args.concat(slice(arguments))); }; +}; + +function prog1(ret) { + if (ret instanceof Function) + ret = ret(); + for (var i = 1, n = arguments.length; --n > 0; ++i) + arguments[i](); + return ret; +}; + +function array_to_hash(a) { + var ret = {}; + for (var i = 0; i < a.length; ++i) + ret[a[i]] = true; + return ret; +}; + +function slice(a, start) { + return Array.prototype.slice.call(a, start == null ? 0 : start); +}; + +function characters(str) { + return str.split(""); +}; + +function member(name, array) { + for (var i = array.length; --i >= 0;) + if (array[i] === name) + return true; + return false; +}; + +function HOP(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +}; + +var warn = function() {}; + +/* -----[ Exports ]----- */ + +exports.tokenizer = tokenizer; +exports.parse = parse; +exports.slice = slice; +exports.curry = curry; +exports.member = member; +exports.array_to_hash = array_to_hash; +exports.PRECEDENCE = PRECEDENCE; +exports.KEYWORDS_ATOM = KEYWORDS_ATOM; +exports.RESERVED_WORDS = RESERVED_WORDS; +exports.KEYWORDS = KEYWORDS; +exports.ATOMIC_START_TOKEN = ATOMIC_START_TOKEN; +exports.OPERATORS = OPERATORS; +exports.is_alphanumeric_char = is_alphanumeric_char; +exports.set_logger = function(logger) { + warn = logger; +}; +; + }).call(module.exports); + + __require.modules["/node_modules/burrito/node_modules/uglify-js/lib/parse-js.js"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/burrito/node_modules/uglify-js/lib/process.js"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/burrito/node_modules/uglify-js/lib"; + var __filename = "/node_modules/burrito/node_modules/uglify-js/lib/process.js"; + + var require = function (file) { + return __require(file, "/node_modules/burrito/node_modules/uglify-js/lib"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/burrito/node_modules/uglify-js/lib"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/burrito/node_modules/uglify-js/lib/process.js"]._cached = module.exports; + + (function () { + /*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + + This version is suitable for Node.js. With minimal changes (the + exports stuff) it should work on any JS platform. + + This file implements some AST processors. They work on data built + by parse-js. + + Exported functions: + + - ast_mangle(ast, options) -- mangles the variable/function names + in the AST. Returns an AST. + + - ast_squeeze(ast) -- employs various optimizations to make the + final generated code even smaller. Returns an AST. + + - gen_code(ast, options) -- generates JS code from the AST. Pass + true (or an object, see the code for some options) as second + argument to get "pretty" (indented) code. + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2010 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +var jsp = require("./parse-js"), + slice = jsp.slice, + member = jsp.member, + PRECEDENCE = jsp.PRECEDENCE, + OPERATORS = jsp.OPERATORS; + +/* -----[ helper for AST traversal ]----- */ + +function ast_walker(ast) { + function _vardefs(defs) { + return [ this[0], MAP(defs, function(def){ + var a = [ def[0] ]; + if (def.length > 1) + a[1] = walk(def[1]); + return a; + }) ]; + }; + function _block(statements) { + var out = [ this[0] ]; + if (statements != null) + out.push(MAP(statements, walk)); + return out; + }; + var walkers = { + "string": function(str) { + return [ this[0], str ]; + }, + "num": function(num) { + return [ this[0], num ]; + }, + "name": function(name) { + return [ this[0], name ]; + }, + "toplevel": function(statements) { + return [ this[0], MAP(statements, walk) ]; + }, + "block": _block, + "splice": _block, + "var": _vardefs, + "const": _vardefs, + "try": function(t, c, f) { + return [ + this[0], + MAP(t, walk), + c != null ? [ c[0], MAP(c[1], walk) ] : null, + f != null ? MAP(f, walk) : null + ]; + }, + "throw": function(expr) { + return [ this[0], walk(expr) ]; + }, + "new": function(ctor, args) { + return [ this[0], walk(ctor), MAP(args, walk) ]; + }, + "switch": function(expr, body) { + return [ this[0], walk(expr), MAP(body, function(branch){ + return [ branch[0] ? walk(branch[0]) : null, + MAP(branch[1], walk) ]; + }) ]; + }, + "break": function(label) { + return [ this[0], label ]; + }, + "continue": function(label) { + return [ this[0], label ]; + }, + "conditional": function(cond, t, e) { + return [ this[0], walk(cond), walk(t), walk(e) ]; + }, + "assign": function(op, lvalue, rvalue) { + return [ this[0], op, walk(lvalue), walk(rvalue) ]; + }, + "dot": function(expr) { + return [ this[0], walk(expr) ].concat(slice(arguments, 1)); + }, + "call": function(expr, args) { + return [ this[0], walk(expr), MAP(args, walk) ]; + }, + "function": function(name, args, body) { + return [ this[0], name, args.slice(), MAP(body, walk) ]; + }, + "defun": function(name, args, body) { + return [ this[0], name, args.slice(), MAP(body, walk) ]; + }, + "if": function(conditional, t, e) { + return [ this[0], walk(conditional), walk(t), walk(e) ]; + }, + "for": function(init, cond, step, block) { + return [ this[0], walk(init), walk(cond), walk(step), walk(block) ]; + }, + "for-in": function(vvar, key, hash, block) { + return [ this[0], walk(vvar), walk(key), walk(hash), walk(block) ]; + }, + "while": function(cond, block) { + return [ this[0], walk(cond), walk(block) ]; + }, + "do": function(cond, block) { + return [ this[0], walk(cond), walk(block) ]; + }, + "return": function(expr) { + return [ this[0], walk(expr) ]; + }, + "binary": function(op, left, right) { + return [ this[0], op, walk(left), walk(right) ]; + }, + "unary-prefix": function(op, expr) { + return [ this[0], op, walk(expr) ]; + }, + "unary-postfix": function(op, expr) { + return [ this[0], op, walk(expr) ]; + }, + "sub": function(expr, subscript) { + return [ this[0], walk(expr), walk(subscript) ]; + }, + "object": function(props) { + return [ this[0], MAP(props, function(p){ + return p.length == 2 + ? [ p[0], walk(p[1]) ] + : [ p[0], walk(p[1]), p[2] ]; // get/set-ter + }) ]; + }, + "regexp": function(rx, mods) { + return [ this[0], rx, mods ]; + }, + "array": function(elements) { + return [ this[0], MAP(elements, walk) ]; + }, + "stat": function(stat) { + return [ this[0], walk(stat) ]; + }, + "seq": function() { + return [ this[0] ].concat(MAP(slice(arguments), walk)); + }, + "label": function(name, block) { + return [ this[0], name, walk(block) ]; + }, + "with": function(expr, block) { + return [ this[0], walk(expr), walk(block) ]; + }, + "atom": function(name) { + return [ this[0], name ]; + } + }; + + var user = {}; + var stack = []; + function walk(ast) { + if (ast == null) + return null; + try { + stack.push(ast); + var type = ast[0]; + var gen = user[type]; + if (gen) { + var ret = gen.apply(ast, ast.slice(1)); + if (ret != null) + return ret; + } + gen = walkers[type]; + return gen.apply(ast, ast.slice(1)); + } finally { + stack.pop(); + } + }; + + function with_walkers(walkers, cont){ + var save = {}, i; + for (i in walkers) if (HOP(walkers, i)) { + save[i] = user[i]; + user[i] = walkers[i]; + } + var ret = cont(); + for (i in save) if (HOP(save, i)) { + if (!save[i]) delete user[i]; + else user[i] = save[i]; + } + return ret; + }; + + return { + walk: walk, + with_walkers: with_walkers, + parent: function() { + return stack[stack.length - 2]; // last one is current node + }, + stack: function() { + return stack; + } + }; +}; + +/* -----[ Scope and mangling ]----- */ + +function Scope(parent) { + this.names = {}; // names defined in this scope + this.mangled = {}; // mangled names (orig.name => mangled) + this.rev_mangled = {}; // reverse lookup (mangled => orig.name) + this.cname = -1; // current mangled name + this.refs = {}; // names referenced from this scope + this.uses_with = false; // will become TRUE if with() is detected in this or any subscopes + this.uses_eval = false; // will become TRUE if eval() is detected in this or any subscopes + this.parent = parent; // parent scope + this.children = []; // sub-scopes + if (parent) { + this.level = parent.level + 1; + parent.children.push(this); + } else { + this.level = 0; + } +}; + +var base54 = (function(){ + var DIGITS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_"; + return function(num) { + var ret = ""; + do { + ret = DIGITS.charAt(num % 54) + ret; + num = Math.floor(num / 54); + } while (num > 0); + return ret; + }; +})(); + +Scope.prototype = { + has: function(name) { + for (var s = this; s; s = s.parent) + if (HOP(s.names, name)) + return s; + }, + has_mangled: function(mname) { + for (var s = this; s; s = s.parent) + if (HOP(s.rev_mangled, mname)) + return s; + }, + toJSON: function() { + return { + names: this.names, + uses_eval: this.uses_eval, + uses_with: this.uses_with + }; + }, + + next_mangled: function() { + // we must be careful that the new mangled name: + // + // 1. doesn't shadow a mangled name from a parent + // scope, unless we don't reference the original + // name from this scope OR from any sub-scopes! + // This will get slow. + // + // 2. doesn't shadow an original name from a parent + // scope, in the event that the name is not mangled + // in the parent scope and we reference that name + // here OR IN ANY SUBSCOPES! + // + // 3. doesn't shadow a name that is referenced but not + // defined (possibly global defined elsewhere). + for (;;) { + var m = base54(++this.cname), prior; + + // case 1. + prior = this.has_mangled(m); + if (prior && this.refs[prior.rev_mangled[m]] === prior) + continue; + + // case 2. + prior = this.has(m); + if (prior && prior !== this && this.refs[m] === prior && !prior.has_mangled(m)) + continue; + + // case 3. + if (HOP(this.refs, m) && this.refs[m] == null) + continue; + + // I got "do" once. :-/ + if (!is_identifier(m)) + continue; + + return m; + } + }, + set_mangle: function(name, m) { + this.rev_mangled[m] = name; + return this.mangled[name] = m; + }, + get_mangled: function(name, newMangle) { + if (this.uses_eval || this.uses_with) return name; // no mangle if eval or with is in use + var s = this.has(name); + if (!s) return name; // not in visible scope, no mangle + if (HOP(s.mangled, name)) return s.mangled[name]; // already mangled in this scope + if (!newMangle) return name; // not found and no mangling requested + return s.set_mangle(name, s.next_mangled()); + }, + define: function(name) { + if (name != null) + return this.names[name] = name; + } +}; + +function ast_add_scope(ast) { + + var current_scope = null; + var w = ast_walker(), walk = w.walk; + var having_eval = []; + + function with_new_scope(cont) { + current_scope = new Scope(current_scope); + var ret = current_scope.body = cont(); + ret.scope = current_scope; + current_scope = current_scope.parent; + return ret; + }; + + function define(name) { + return current_scope.define(name); + }; + + function reference(name) { + current_scope.refs[name] = true; + }; + + function _lambda(name, args, body) { + var is_defun = this[0] == "defun"; + return [ this[0], is_defun ? define(name) : name, args, with_new_scope(function(){ + if (!is_defun) define(name); + MAP(args, define); + return MAP(body, walk); + })]; + }; + + return with_new_scope(function(){ + // process AST + var ret = w.with_walkers({ + "function": _lambda, + "defun": _lambda, + "with": function(expr, block) { + for (var s = current_scope; s; s = s.parent) + s.uses_with = true; + }, + "var": function(defs) { + MAP(defs, function(d){ define(d[0]) }); + }, + "const": function(defs) { + MAP(defs, function(d){ define(d[0]) }); + }, + "try": function(t, c, f) { + if (c != null) return [ + this[0], + MAP(t, walk), + [ define(c[0]), MAP(c[1], walk) ], + f != null ? MAP(f, walk) : null + ]; + }, + "name": function(name) { + if (name == "eval") + having_eval.push(current_scope); + reference(name); + } + }, function(){ + return walk(ast); + }); + + // the reason why we need an additional pass here is + // that names can be used prior to their definition. + + // scopes where eval was detected and their parents + // are marked with uses_eval, unless they define the + // "eval" name. + MAP(having_eval, function(scope){ + if (!scope.has("eval")) while (scope) { + scope.uses_eval = true; + scope = scope.parent; + } + }); + + // for referenced names it might be useful to know + // their origin scope. current_scope here is the + // toplevel one. + function fixrefs(scope, i) { + // do children first; order shouldn't matter + for (i = scope.children.length; --i >= 0;) + fixrefs(scope.children[i]); + for (i in scope.refs) if (HOP(scope.refs, i)) { + // find origin scope and propagate the reference to origin + for (var origin = scope.has(i), s = scope; s; s = s.parent) { + s.refs[i] = origin; + if (s === origin) break; + } + } + }; + fixrefs(current_scope); + + return ret; + }); + +}; + +/* -----[ mangle names ]----- */ + +function ast_mangle(ast, options) { + var w = ast_walker(), walk = w.walk, scope; + options = options || {}; + + function get_mangled(name, newMangle) { + if (!options.toplevel && !scope.parent) return name; // don't mangle toplevel + if (options.except && member(name, options.except)) + return name; + return scope.get_mangled(name, newMangle); + }; + + function get_define(name) { + if (options.defines) { + // we always lookup a defined symbol for the current scope FIRST, so declared + // vars trump a DEFINE symbol, but if no such var is found, then match a DEFINE value + if (!scope.has(name)) { + if (HOP(options.defines, name)) { + return options.defines[name]; + } + } + return null; + } + }; + + function _lambda(name, args, body) { + var is_defun = this[0] == "defun", extra; + if (name) { + if (is_defun) name = get_mangled(name); + else { + extra = {}; + name = extra[name] = scope.next_mangled(); + } + } + body = with_scope(body.scope, function(){ + args = MAP(args, function(name){ return get_mangled(name) }); + return MAP(body, walk); + }, extra); + return [ this[0], name, args, body ]; + }; + + function with_scope(s, cont, extra) { + var _scope = scope; + scope = s; + if (extra) for (var i in extra) if (HOP(extra, i)) { + s.set_mangle(i, extra[i]); + } + for (var i in s.names) if (HOP(s.names, i)) { + get_mangled(i, true); + } + var ret = cont(); + ret.scope = s; + scope = _scope; + return ret; + }; + + function _vardefs(defs) { + return [ this[0], MAP(defs, function(d){ + return [ get_mangled(d[0]), walk(d[1]) ]; + }) ]; + }; + + return w.with_walkers({ + "function": _lambda, + "defun": function() { + // move function declarations to the top when + // they are not in some block. + var ast = _lambda.apply(this, arguments); + switch (w.parent()[0]) { + case "toplevel": + case "function": + case "defun": + return MAP.at_top(ast); + } + return ast; + }, + "var": _vardefs, + "const": _vardefs, + "name": function(name) { + return get_define(name) || [ this[0], get_mangled(name) ]; + }, + "try": function(t, c, f) { + return [ this[0], + MAP(t, walk), + c != null ? [ get_mangled(c[0]), MAP(c[1], walk) ] : null, + f != null ? MAP(f, walk) : null ]; + }, + "toplevel": function(body) { + var self = this; + return with_scope(self.scope, function(){ + return [ self[0], MAP(body, walk) ]; + }); + } + }, function() { + return walk(ast_add_scope(ast)); + }); +}; + +/* -----[ + - compress foo["bar"] into foo.bar, + - remove block brackets {} where possible + - join consecutive var declarations + - various optimizations for IFs: + - if (cond) foo(); else bar(); ==> cond?foo():bar(); + - if (cond) foo(); ==> cond&&foo(); + - if (foo) return bar(); else return baz(); ==> return foo?bar():baz(); // also for throw + - if (foo) return bar(); else something(); ==> {if(foo)return bar();something()} + ]----- */ + +var warn = function(){}; + +function best_of(ast1, ast2) { + return gen_code(ast1).length > gen_code(ast2[0] == "stat" ? ast2[1] : ast2).length ? ast2 : ast1; +}; + +function last_stat(b) { + if (b[0] == "block" && b[1] && b[1].length > 0) + return b[1][b[1].length - 1]; + return b; +} + +function aborts(t) { + if (t) { + t = last_stat(t); + if (t[0] == "return" || t[0] == "break" || t[0] == "continue" || t[0] == "throw") + return true; + } +}; + +function boolean_expr(expr) { + return ( (expr[0] == "unary-prefix" + && member(expr[1], [ "!", "delete" ])) || + + (expr[0] == "binary" + && member(expr[1], [ "in", "instanceof", "==", "!=", "===", "!==", "<", "<=", ">=", ">" ])) || + + (expr[0] == "binary" + && member(expr[1], [ "&&", "||" ]) + && boolean_expr(expr[2]) + && boolean_expr(expr[3])) || + + (expr[0] == "conditional" + && boolean_expr(expr[2]) + && boolean_expr(expr[3])) || + + (expr[0] == "assign" + && expr[1] === true + && boolean_expr(expr[3])) || + + (expr[0] == "seq" + && boolean_expr(expr[expr.length - 1])) + ); +}; + +function make_conditional(c, t, e) { + var make_real_conditional = function() { + if (c[0] == "unary-prefix" && c[1] == "!") { + return e ? [ "conditional", c[2], e, t ] : [ "binary", "||", c[2], t ]; + } else { + return e ? [ "conditional", c, t, e ] : [ "binary", "&&", c, t ]; + } + }; + // shortcut the conditional if the expression has a constant value + return when_constant(c, function(ast, val){ + warn_unreachable(val ? e : t); + return (val ? t : e); + }, make_real_conditional); +}; + +function empty(b) { + return !b || (b[0] == "block" && (!b[1] || b[1].length == 0)); +}; + +function is_string(node) { + return (node[0] == "string" || + node[0] == "unary-prefix" && node[1] == "typeof" || + node[0] == "binary" && node[1] == "+" && + (is_string(node[2]) || is_string(node[3]))); +}; + +var when_constant = (function(){ + + var $NOT_CONSTANT = {}; + + // this can only evaluate constant expressions. If it finds anything + // not constant, it throws $NOT_CONSTANT. + function evaluate(expr) { + switch (expr[0]) { + case "string": + case "num": + return expr[1]; + case "name": + case "atom": + switch (expr[1]) { + case "true": return true; + case "false": return false; + } + break; + case "unary-prefix": + switch (expr[1]) { + case "!": return !evaluate(expr[2]); + case "typeof": return typeof evaluate(expr[2]); + case "~": return ~evaluate(expr[2]); + case "-": return -evaluate(expr[2]); + case "+": return +evaluate(expr[2]); + } + break; + case "binary": + var left = expr[2], right = expr[3]; + switch (expr[1]) { + case "&&" : return evaluate(left) && evaluate(right); + case "||" : return evaluate(left) || evaluate(right); + case "|" : return evaluate(left) | evaluate(right); + case "&" : return evaluate(left) & evaluate(right); + case "^" : return evaluate(left) ^ evaluate(right); + case "+" : return evaluate(left) + evaluate(right); + case "*" : return evaluate(left) * evaluate(right); + case "/" : return evaluate(left) / evaluate(right); + case "-" : return evaluate(left) - evaluate(right); + case "<<" : return evaluate(left) << evaluate(right); + case ">>" : return evaluate(left) >> evaluate(right); + case ">>>" : return evaluate(left) >>> evaluate(right); + case "==" : return evaluate(left) == evaluate(right); + case "===" : return evaluate(left) === evaluate(right); + case "!=" : return evaluate(left) != evaluate(right); + case "!==" : return evaluate(left) !== evaluate(right); + case "<" : return evaluate(left) < evaluate(right); + case "<=" : return evaluate(left) <= evaluate(right); + case ">" : return evaluate(left) > evaluate(right); + case ">=" : return evaluate(left) >= evaluate(right); + case "in" : return evaluate(left) in evaluate(right); + case "instanceof" : return evaluate(left) instanceof evaluate(right); + } + } + throw $NOT_CONSTANT; + }; + + return function(expr, yes, no) { + try { + var val = evaluate(expr), ast; + switch (typeof val) { + case "string": ast = [ "string", val ]; break; + case "number": ast = [ "num", val ]; break; + case "boolean": ast = [ "name", String(val) ]; break; + default: throw new Error("Can't handle constant of type: " + (typeof val)); + } + return yes.call(expr, ast, val); + } catch(ex) { + if (ex === $NOT_CONSTANT) { + if (expr[0] == "binary" + && (expr[1] == "===" || expr[1] == "!==") + && ((is_string(expr[2]) && is_string(expr[3])) + || (boolean_expr(expr[2]) && boolean_expr(expr[3])))) { + expr[1] = expr[1].substr(0, 2); + } + else if (no && expr[0] == "binary" + && (expr[1] == "||" || expr[1] == "&&")) { + // the whole expression is not constant but the lval may be... + try { + var lval = evaluate(expr[2]); + expr = ((expr[1] == "&&" && (lval ? expr[3] : lval)) || + (expr[1] == "||" && (lval ? lval : expr[3])) || + expr); + } catch(ex2) { + // IGNORE... lval is not constant + } + } + return no ? no.call(expr, expr) : null; + } + else throw ex; + } + }; + +})(); + +function warn_unreachable(ast) { + if (!empty(ast)) + warn("Dropping unreachable code: " + gen_code(ast, true)); +}; + +function prepare_ifs(ast) { + var w = ast_walker(), walk = w.walk; + // In this first pass, we rewrite ifs which abort with no else with an + // if-else. For example: + // + // if (x) { + // blah(); + // return y; + // } + // foobar(); + // + // is rewritten into: + // + // if (x) { + // blah(); + // return y; + // } else { + // foobar(); + // } + function redo_if(statements) { + statements = MAP(statements, walk); + + for (var i = 0; i < statements.length; ++i) { + var fi = statements[i]; + if (fi[0] != "if") continue; + + if (fi[3] && walk(fi[3])) continue; + + var t = walk(fi[2]); + if (!aborts(t)) continue; + + var conditional = walk(fi[1]); + + var e_body = statements.slice(i + 1); + var e; + if (e_body.length == 1) e = e_body[0]; + else e = [ "block", e_body ]; + + var ret = statements.slice(0, i).concat([ [ + fi[0], // "if" + conditional, // conditional + t, // then + e // else + ] ]); + + return redo_if(ret); + } + + return statements; + }; + + function redo_if_lambda(name, args, body) { + body = redo_if(body); + return [ this[0], name, args.slice(), body ]; + }; + + function redo_if_block(statements) { + var out = [ this[0] ]; + if (statements != null) + out.push(redo_if(statements)); + return out; + }; + + return w.with_walkers({ + "defun": redo_if_lambda, + "function": redo_if_lambda, + "block": redo_if_block, + "splice": redo_if_block, + "toplevel": function(statements) { + return [ this[0], redo_if(statements) ]; + }, + "try": function(t, c, f) { + return [ + this[0], + redo_if(t), + c != null ? [ c[0], redo_if(c[1]) ] : null, + f != null ? redo_if(f) : null + ]; + }, + "with": function(expr, block) { + return [ this[0], walk(expr), redo_if(block) ]; + } + }, function() { + return walk(ast); + }); +}; + +function ast_squeeze(ast, options) { + options = defaults(options, { + make_seqs : true, + dead_code : true, + keep_comps : true, + no_warnings : false + }); + + var w = ast_walker(), walk = w.walk, scope; + + function negate(c) { + var not_c = [ "unary-prefix", "!", c ]; + switch (c[0]) { + case "unary-prefix": + return c[1] == "!" && boolean_expr(c[2]) ? c[2] : not_c; + case "seq": + c = slice(c); + c[c.length - 1] = negate(c[c.length - 1]); + return c; + case "conditional": + return best_of(not_c, [ "conditional", c[1], negate(c[2]), negate(c[3]) ]); + case "binary": + var op = c[1], left = c[2], right = c[3]; + if (!options.keep_comps) switch (op) { + case "<=" : return [ "binary", ">", left, right ]; + case "<" : return [ "binary", ">=", left, right ]; + case ">=" : return [ "binary", "<", left, right ]; + case ">" : return [ "binary", "<=", left, right ]; + } + switch (op) { + case "==" : return [ "binary", "!=", left, right ]; + case "!=" : return [ "binary", "==", left, right ]; + case "===" : return [ "binary", "!==", left, right ]; + case "!==" : return [ "binary", "===", left, right ]; + case "&&" : return best_of(not_c, [ "binary", "||", negate(left), negate(right) ]); + case "||" : return best_of(not_c, [ "binary", "&&", negate(left), negate(right) ]); + } + break; + } + return not_c; + }; + + function with_scope(s, cont) { + var _scope = scope; + scope = s; + var ret = cont(); + ret.scope = s; + scope = _scope; + return ret; + }; + + function rmblock(block) { + if (block != null && block[0] == "block" && block[1]) { + if (block[1].length == 1) + block = block[1][0]; + else if (block[1].length == 0) + block = [ "block" ]; + } + return block; + }; + + function _lambda(name, args, body) { + var is_defun = this[0] == "defun"; + body = with_scope(body.scope, function(){ + var ret = tighten(MAP(body, walk), "lambda"); + if (!is_defun && name && !HOP(scope.refs, name)) + name = null; + return ret; + }); + return [ this[0], name, args, body ]; + }; + + // we get here for blocks that have been already transformed. + // this function does a few things: + // 1. discard useless blocks + // 2. join consecutive var declarations + // 3. remove obviously dead code + // 4. transform consecutive statements using the comma operator + // 5. if block_type == "lambda" and it detects constructs like if(foo) return ... - rewrite like if (!foo) { ... } + function tighten(statements, block_type) { + statements = statements.reduce(function(a, stat){ + if (stat[0] == "block") { + if (stat[1]) { + a.push.apply(a, stat[1]); + } + } else { + a.push(stat); + } + return a; + }, []); + + statements = (function(a, prev){ + statements.forEach(function(cur){ + if (prev && ((cur[0] == "var" && prev[0] == "var") || + (cur[0] == "const" && prev[0] == "const"))) { + prev[1] = prev[1].concat(cur[1]); + } else { + a.push(cur); + prev = cur; + } + }); + return a; + })([]); + + if (options.dead_code) statements = (function(a, has_quit){ + statements.forEach(function(st){ + if (has_quit) { + if (member(st[0], [ "function", "defun" , "var", "const" ])) { + a.push(st); + } + else if (!options.no_warnings) + warn_unreachable(st); + } + else { + a.push(st); + if (member(st[0], [ "return", "throw", "break", "continue" ])) + has_quit = true; + } + }); + return a; + })([]); + + if (options.make_seqs) statements = (function(a, prev) { + statements.forEach(function(cur){ + if (prev && prev[0] == "stat" && cur[0] == "stat") { + prev[1] = [ "seq", prev[1], cur[1] ]; + } else { + a.push(cur); + prev = cur; + } + }); + return a; + })([]); + + if (block_type == "lambda") statements = (function(i, a, stat){ + while (i < statements.length) { + stat = statements[i++]; + if (stat[0] == "if" && !stat[3]) { + if (stat[2][0] == "return" && stat[2][1] == null) { + a.push(make_if(negate(stat[1]), [ "block", statements.slice(i) ])); + break; + } + var last = last_stat(stat[2]); + if (last[0] == "return" && last[1] == null) { + a.push(make_if(stat[1], [ "block", stat[2][1].slice(0, -1) ], [ "block", statements.slice(i) ])); + break; + } + } + a.push(stat); + } + return a; + })(0, []); + + return statements; + }; + + function make_if(c, t, e) { + return when_constant(c, function(ast, val){ + if (val) { + warn_unreachable(e); + return t; + } else { + warn_unreachable(t); + return e; + } + }, function() { + return make_real_if(c, t, e); + }); + }; + + function make_real_if(c, t, e) { + c = walk(c); + t = walk(t); + e = walk(e); + + if (empty(t)) { + c = negate(c); + t = e; + e = null; + } else if (empty(e)) { + e = null; + } else { + // if we have both else and then, maybe it makes sense to switch them? + (function(){ + var a = gen_code(c); + var n = negate(c); + var b = gen_code(n); + if (b.length < a.length) { + var tmp = t; + t = e; + e = tmp; + c = n; + } + })(); + } + if (empty(e) && empty(t)) + return [ "stat", c ]; + var ret = [ "if", c, t, e ]; + if (t[0] == "if" && empty(t[3]) && empty(e)) { + ret = best_of(ret, walk([ "if", [ "binary", "&&", c, t[1] ], t[2] ])); + } + else if (t[0] == "stat") { + if (e) { + if (e[0] == "stat") { + ret = best_of(ret, [ "stat", make_conditional(c, t[1], e[1]) ]); + } + } + else { + ret = best_of(ret, [ "stat", make_conditional(c, t[1]) ]); + } + } + else if (e && t[0] == e[0] && (t[0] == "return" || t[0] == "throw") && t[1] && e[1]) { + ret = best_of(ret, [ t[0], make_conditional(c, t[1], e[1] ) ]); + } + else if (e && aborts(t)) { + ret = [ [ "if", c, t ] ]; + if (e[0] == "block") { + if (e[1]) ret = ret.concat(e[1]); + } + else { + ret.push(e); + } + ret = walk([ "block", ret ]); + } + else if (t && aborts(e)) { + ret = [ [ "if", negate(c), e ] ]; + if (t[0] == "block") { + if (t[1]) ret = ret.concat(t[1]); + } else { + ret.push(t); + } + ret = walk([ "block", ret ]); + } + return ret; + }; + + function _do_while(cond, body) { + return when_constant(cond, function(cond, val){ + if (!val) { + warn_unreachable(body); + return [ "block" ]; + } else { + return [ "for", null, null, null, walk(body) ]; + } + }); + }; + + ast = prepare_ifs(ast); + ast = ast_add_scope(ast); + + return w.with_walkers({ + "sub": function(expr, subscript) { + if (subscript[0] == "string") { + var name = subscript[1]; + if (is_identifier(name)) + return [ "dot", walk(expr), name ]; + else if (/^[1-9][0-9]*$/.test(name) || name === "0") + return [ "sub", walk(expr), [ "num", parseInt(name, 10) ] ]; + } + }, + "if": make_if, + "toplevel": function(body) { + return [ "toplevel", with_scope(this.scope, function(){ + return tighten(MAP(body, walk)); + }) ]; + }, + "switch": function(expr, body) { + var last = body.length - 1; + return [ "switch", walk(expr), MAP(body, function(branch, i){ + var block = tighten(MAP(branch[1], walk)); + if (i == last && block.length > 0) { + var node = block[block.length - 1]; + if (node[0] == "break" && !node[1]) + block.pop(); + } + return [ branch[0] ? walk(branch[0]) : null, block ]; + }) ]; + }, + "function": _lambda, + "defun": _lambda, + "block": function(body) { + if (body) return rmblock([ "block", tighten(MAP(body, walk)) ]); + }, + "binary": function(op, left, right) { + return when_constant([ "binary", op, walk(left), walk(right) ], function yes(c){ + return best_of(walk(c), this); + }, function no() { + return this; + }); + }, + "conditional": function(c, t, e) { + return make_conditional(walk(c), walk(t), walk(e)); + }, + "try": function(t, c, f) { + return [ + "try", + tighten(MAP(t, walk)), + c != null ? [ c[0], tighten(MAP(c[1], walk)) ] : null, + f != null ? tighten(MAP(f, walk)) : null + ]; + }, + "unary-prefix": function(op, expr) { + expr = walk(expr); + var ret = [ "unary-prefix", op, expr ]; + if (op == "!") + ret = best_of(ret, negate(expr)); + return when_constant(ret, function(ast, val){ + return walk(ast); // it's either true or false, so minifies to !0 or !1 + }, function() { return ret }); + }, + "name": function(name) { + switch (name) { + case "true": return [ "unary-prefix", "!", [ "num", 0 ]]; + case "false": return [ "unary-prefix", "!", [ "num", 1 ]]; + } + }, + "new": function(ctor, args) { + if (ctor[0] == "name" && ctor[1] == "Array" && !scope.has("Array")) { + if (args.length != 1) { + return [ "array", args ]; + } else { + return [ "call", [ "name", "Array" ], args ]; + } + } + }, + "call": function(expr, args) { + if (expr[0] == "name" && expr[1] == "Array" && args.length != 1 && !scope.has("Array")) { + return [ "array", args ]; + } + }, + "while": _do_while + }, function() { + return walk(ast); + }); +}; + +/* -----[ re-generate code from the AST ]----- */ + +var DOT_CALL_NO_PARENS = jsp.array_to_hash([ + "name", + "array", + "object", + "string", + "dot", + "sub", + "call", + "regexp" +]); + +function make_string(str, ascii_only) { + var dq = 0, sq = 0; + str = str.replace(/[\\\b\f\n\r\t\x22\x27\u2028\u2029]/g, function(s){ + switch (s) { + case "\\": return "\\\\"; + case "\b": return "\\b"; + case "\f": return "\\f"; + case "\n": return "\\n"; + case "\r": return "\\r"; + case "\t": return "\\t"; + case "\u2028": return "\\u2028"; + case "\u2029": return "\\u2029"; + case '"': ++dq; return '"'; + case "'": ++sq; return "'"; + } + return s; + }); + if (ascii_only) str = to_ascii(str); + if (dq > sq) return "'" + str.replace(/\x27/g, "\\'") + "'"; + else return '"' + str.replace(/\x22/g, '\\"') + '"'; +}; + +function to_ascii(str) { + return str.replace(/[\u0080-\uffff]/g, function(ch) { + var code = ch.charCodeAt(0).toString(16); + while (code.length < 4) code = "0" + code; + return "\\u" + code; + }); +}; + +var SPLICE_NEEDS_BRACKETS = jsp.array_to_hash([ "if", "while", "do", "for", "for-in", "with" ]); + +function gen_code(ast, options) { + options = defaults(options, { + indent_start : 0, + indent_level : 4, + quote_keys : false, + space_colon : false, + beautify : false, + ascii_only : false + }); + var beautify = !!options.beautify; + var indentation = 0, + newline = beautify ? "\n" : "", + space = beautify ? " " : ""; + + function encode_string(str) { + return make_string(str, options.ascii_only); + }; + + function make_name(name) { + name = name.toString(); + if (options.ascii_only) + name = to_ascii(name); + return name; + }; + + function indent(line) { + if (line == null) + line = ""; + if (beautify) + line = repeat_string(" ", options.indent_start + indentation * options.indent_level) + line; + return line; + }; + + function with_indent(cont, incr) { + if (incr == null) incr = 1; + indentation += incr; + try { return cont.apply(null, slice(arguments, 1)); } + finally { indentation -= incr; } + }; + + function add_spaces(a) { + if (beautify) + return a.join(" "); + var b = []; + for (var i = 0; i < a.length; ++i) { + var next = a[i + 1]; + b.push(a[i]); + if (next && + ((/[a-z0-9_\x24]$/i.test(a[i].toString()) && /^[a-z0-9_\x24]/i.test(next.toString())) || + (/[\+\-]$/.test(a[i].toString()) && /^[\+\-]/.test(next.toString())))) { + b.push(" "); + } + } + return b.join(""); + }; + + function add_commas(a) { + return a.join("," + space); + }; + + function parenthesize(expr) { + var gen = make(expr); + for (var i = 1; i < arguments.length; ++i) { + var el = arguments[i]; + if ((el instanceof Function && el(expr)) || expr[0] == el) + return "(" + gen + ")"; + } + return gen; + }; + + function best_of(a) { + if (a.length == 1) { + return a[0]; + } + if (a.length == 2) { + var b = a[1]; + a = a[0]; + return a.length <= b.length ? a : b; + } + return best_of([ a[0], best_of(a.slice(1)) ]); + }; + + function needs_parens(expr) { + if (expr[0] == "function" || expr[0] == "object") { + // dot/call on a literal function requires the + // function literal itself to be parenthesized + // only if it's the first "thing" in a + // statement. This means that the parent is + // "stat", but it could also be a "seq" and + // we're the first in this "seq" and the + // parent is "stat", and so on. Messy stuff, + // but it worths the trouble. + var a = slice($stack), self = a.pop(), p = a.pop(); + while (p) { + if (p[0] == "stat") return true; + if (((p[0] == "seq" || p[0] == "call" || p[0] == "dot" || p[0] == "sub" || p[0] == "conditional") && p[1] === self) || + ((p[0] == "binary" || p[0] == "assign" || p[0] == "unary-postfix") && p[2] === self)) { + self = p; + p = a.pop(); + } else { + return false; + } + } + } + return !HOP(DOT_CALL_NO_PARENS, expr[0]); + }; + + function make_num(num) { + var str = num.toString(10), a = [ str.replace(/^0\./, ".") ], m; + if (Math.floor(num) === num) { + a.push("0x" + num.toString(16).toLowerCase(), // probably pointless + "0" + num.toString(8)); // same. + if ((m = /^(.*?)(0+)$/.exec(num))) { + a.push(m[1] + "e" + m[2].length); + } + } else if ((m = /^0?\.(0+)(.*)$/.exec(num))) { + a.push(m[2] + "e-" + (m[1].length + m[2].length), + str.substr(str.indexOf("."))); + } + return best_of(a); + }; + + var generators = { + "string": encode_string, + "num": make_num, + "name": make_name, + "toplevel": function(statements) { + return make_block_statements(statements) + .join(newline + newline); + }, + "splice": function(statements) { + var parent = $stack[$stack.length - 2][0]; + if (HOP(SPLICE_NEEDS_BRACKETS, parent)) { + // we need block brackets in this case + return make_block.apply(this, arguments); + } else { + return MAP(make_block_statements(statements, true), + function(line, i) { + // the first line is already indented + return i > 0 ? indent(line) : line; + }).join(newline); + } + }, + "block": make_block, + "var": function(defs) { + return "var " + add_commas(MAP(defs, make_1vardef)) + ";"; + }, + "const": function(defs) { + return "const " + add_commas(MAP(defs, make_1vardef)) + ";"; + }, + "try": function(tr, ca, fi) { + var out = [ "try", make_block(tr) ]; + if (ca) out.push("catch", "(" + ca[0] + ")", make_block(ca[1])); + if (fi) out.push("finally", make_block(fi)); + return add_spaces(out); + }, + "throw": function(expr) { + return add_spaces([ "throw", make(expr) ]) + ";"; + }, + "new": function(ctor, args) { + args = args.length > 0 ? "(" + add_commas(MAP(args, make)) + ")" : ""; + return add_spaces([ "new", parenthesize(ctor, "seq", "binary", "conditional", "assign", function(expr){ + var w = ast_walker(), has_call = {}; + try { + w.with_walkers({ + "call": function() { throw has_call }, + "function": function() { return this } + }, function(){ + w.walk(expr); + }); + } catch(ex) { + if (ex === has_call) + return true; + throw ex; + } + }) + args ]); + }, + "switch": function(expr, body) { + return add_spaces([ "switch", "(" + make(expr) + ")", make_switch_block(body) ]); + }, + "break": function(label) { + var out = "break"; + if (label != null) + out += " " + make_name(label); + return out + ";"; + }, + "continue": function(label) { + var out = "continue"; + if (label != null) + out += " " + make_name(label); + return out + ";"; + }, + "conditional": function(co, th, el) { + return add_spaces([ parenthesize(co, "assign", "seq", "conditional"), "?", + parenthesize(th, "seq"), ":", + parenthesize(el, "seq") ]); + }, + "assign": function(op, lvalue, rvalue) { + if (op && op !== true) op += "="; + else op = "="; + return add_spaces([ make(lvalue), op, parenthesize(rvalue, "seq") ]); + }, + "dot": function(expr) { + var out = make(expr), i = 1; + if (expr[0] == "num") { + if (!/\./.test(expr[1])) + out += "."; + } else if (needs_parens(expr)) + out = "(" + out + ")"; + while (i < arguments.length) + out += "." + make_name(arguments[i++]); + return out; + }, + "call": function(func, args) { + var f = make(func); + if (needs_parens(func)) + f = "(" + f + ")"; + return f + "(" + add_commas(MAP(args, function(expr){ + return parenthesize(expr, "seq"); + })) + ")"; + }, + "function": make_function, + "defun": make_function, + "if": function(co, th, el) { + var out = [ "if", "(" + make(co) + ")", el ? make_then(th) : make(th) ]; + if (el) { + out.push("else", make(el)); + } + return add_spaces(out); + }, + "for": function(init, cond, step, block) { + var out = [ "for" ]; + init = (init != null ? make(init) : "").replace(/;*\s*$/, ";" + space); + cond = (cond != null ? make(cond) : "").replace(/;*\s*$/, ";" + space); + step = (step != null ? make(step) : "").replace(/;*\s*$/, ""); + var args = init + cond + step; + if (args == "; ; ") args = ";;"; + out.push("(" + args + ")", make(block)); + return add_spaces(out); + }, + "for-in": function(vvar, key, hash, block) { + return add_spaces([ "for", "(" + + (vvar ? make(vvar).replace(/;+$/, "") : make(key)), + "in", + make(hash) + ")", make(block) ]); + }, + "while": function(condition, block) { + return add_spaces([ "while", "(" + make(condition) + ")", make(block) ]); + }, + "do": function(condition, block) { + return add_spaces([ "do", make(block), "while", "(" + make(condition) + ")" ]) + ";"; + }, + "return": function(expr) { + var out = [ "return" ]; + if (expr != null) out.push(make(expr)); + return add_spaces(out) + ";"; + }, + "binary": function(operator, lvalue, rvalue) { + var left = make(lvalue), right = make(rvalue); + // XXX: I'm pretty sure other cases will bite here. + // we need to be smarter. + // adding parens all the time is the safest bet. + if (member(lvalue[0], [ "assign", "conditional", "seq" ]) || + lvalue[0] == "binary" && PRECEDENCE[operator] > PRECEDENCE[lvalue[1]]) { + left = "(" + left + ")"; + } + if (member(rvalue[0], [ "assign", "conditional", "seq" ]) || + rvalue[0] == "binary" && PRECEDENCE[operator] >= PRECEDENCE[rvalue[1]] && + !(rvalue[1] == operator && member(operator, [ "&&", "||", "*" ]))) { + right = "(" + right + ")"; + } + return add_spaces([ left, operator, right ]); + }, + "unary-prefix": function(operator, expr) { + var val = make(expr); + if (!(expr[0] == "num" || (expr[0] == "unary-prefix" && !HOP(OPERATORS, operator + expr[1])) || !needs_parens(expr))) + val = "(" + val + ")"; + return operator + (jsp.is_alphanumeric_char(operator.charAt(0)) ? " " : "") + val; + }, + "unary-postfix": function(operator, expr) { + var val = make(expr); + if (!(expr[0] == "num" || (expr[0] == "unary-postfix" && !HOP(OPERATORS, operator + expr[1])) || !needs_parens(expr))) + val = "(" + val + ")"; + return val + operator; + }, + "sub": function(expr, subscript) { + var hash = make(expr); + if (needs_parens(expr)) + hash = "(" + hash + ")"; + return hash + "[" + make(subscript) + "]"; + }, + "object": function(props) { + if (props.length == 0) + return "{}"; + return "{" + newline + with_indent(function(){ + return MAP(props, function(p){ + if (p.length == 3) { + // getter/setter. The name is in p[0], the arg.list in p[1][2], the + // body in p[1][3] and type ("get" / "set") in p[2]. + return indent(make_function(p[0], p[1][2], p[1][3], p[2])); + } + var key = p[0], val = make(p[1]); + if (options.quote_keys) { + key = encode_string(key); + } else if ((typeof key == "number" || !beautify && +key + "" == key) + && parseFloat(key) >= 0) { + key = make_num(+key); + } else if (!is_identifier(key)) { + key = encode_string(key); + } + return indent(add_spaces(beautify && options.space_colon + ? [ key, ":", val ] + : [ key + ":", val ])); + }).join("," + newline); + }) + newline + indent("}"); + }, + "regexp": function(rx, mods) { + return "/" + rx + "/" + mods; + }, + "array": function(elements) { + if (elements.length == 0) return "[]"; + return add_spaces([ "[", add_commas(MAP(elements, function(el){ + if (!beautify && el[0] == "atom" && el[1] == "undefined") return ""; + return parenthesize(el, "seq"); + })), "]" ]); + }, + "stat": function(stmt) { + return make(stmt).replace(/;*\s*$/, ";"); + }, + "seq": function() { + return add_commas(MAP(slice(arguments), make)); + }, + "label": function(name, block) { + return add_spaces([ make_name(name), ":", make(block) ]); + }, + "with": function(expr, block) { + return add_spaces([ "with", "(" + make(expr) + ")", make(block) ]); + }, + "atom": function(name) { + return make_name(name); + } + }; + + // The squeezer replaces "block"-s that contain only a single + // statement with the statement itself; technically, the AST + // is correct, but this can create problems when we output an + // IF having an ELSE clause where the THEN clause ends in an + // IF *without* an ELSE block (then the outer ELSE would refer + // to the inner IF). This function checks for this case and + // adds the block brackets if needed. + function make_then(th) { + if (th[0] == "do") { + // https://github.com/mishoo/UglifyJS/issues/#issue/57 + // IE croaks with "syntax error" on code like this: + // if (foo) do ... while(cond); else ... + // we need block brackets around do/while + return make([ "block", [ th ]]); + } + var b = th; + while (true) { + var type = b[0]; + if (type == "if") { + if (!b[3]) + // no else, we must add the block + return make([ "block", [ th ]]); + b = b[3]; + } + else if (type == "while" || type == "do") b = b[2]; + else if (type == "for" || type == "for-in") b = b[4]; + else break; + } + return make(th); + }; + + function make_function(name, args, body, keyword) { + var out = keyword || "function"; + if (name) { + out += " " + make_name(name); + } + out += "(" + add_commas(MAP(args, make_name)) + ")"; + return add_spaces([ out, make_block(body) ]); + }; + + function make_block_statements(statements, noindent) { + for (var a = [], last = statements.length - 1, i = 0; i <= last; ++i) { + var stat = statements[i]; + var code = make(stat); + if (code != ";") { + if (!beautify && i == last) { + if ((stat[0] == "while" && empty(stat[2])) || + (member(stat[0], [ "for", "for-in"] ) && empty(stat[4])) || + (stat[0] == "if" && empty(stat[2]) && !stat[3]) || + (stat[0] == "if" && stat[3] && empty(stat[3]))) { + code = code.replace(/;*\s*$/, ";"); + } else { + code = code.replace(/;+\s*$/, ""); + } + } + a.push(code); + } + } + return noindent ? a : MAP(a, indent); + }; + + function make_switch_block(body) { + var n = body.length; + if (n == 0) return "{}"; + return "{" + newline + MAP(body, function(branch, i){ + var has_body = branch[1].length > 0, code = with_indent(function(){ + return indent(branch[0] + ? add_spaces([ "case", make(branch[0]) + ":" ]) + : "default:"); + }, 0.5) + (has_body ? newline + with_indent(function(){ + return make_block_statements(branch[1]).join(newline); + }) : ""); + if (!beautify && has_body && i < n - 1) + code += ";"; + return code; + }).join(newline) + newline + indent("}"); + }; + + function make_block(statements) { + if (!statements) return ";"; + if (statements.length == 0) return "{}"; + return "{" + newline + with_indent(function(){ + return make_block_statements(statements).join(newline); + }) + newline + indent("}"); + }; + + function make_1vardef(def) { + var name = def[0], val = def[1]; + if (val != null) + name = add_spaces([ make_name(name), "=", parenthesize(val, "seq") ]); + return name; + }; + + var $stack = []; + + function make(node) { + var type = node[0]; + var gen = generators[type]; + if (!gen) + throw new Error("Can't find generator for \"" + type + "\""); + $stack.push(node); + var ret = gen.apply(type, node.slice(1)); + $stack.pop(); + return ret; + }; + + return make(ast); +}; + +function split_lines(code, max_line_length) { + var splits = [ 0 ]; + jsp.parse(function(){ + var next_token = jsp.tokenizer(code); + var last_split = 0; + var prev_token; + function current_length(tok) { + return tok.pos - last_split; + }; + function split_here(tok) { + last_split = tok.pos; + splits.push(last_split); + }; + function custom(){ + var tok = next_token.apply(this, arguments); + out: { + if (prev_token) { + if (prev_token.type == "keyword") break out; + } + if (current_length(tok) > max_line_length) { + switch (tok.type) { + case "keyword": + case "atom": + case "name": + case "punc": + split_here(tok); + break out; + } + } + } + prev_token = tok; + return tok; + }; + custom.context = function() { + return next_token.context.apply(this, arguments); + }; + return custom; + }()); + return splits.map(function(pos, i){ + return code.substring(pos, splits[i + 1] || code.length); + }).join("\n"); +}; + +/* -----[ Utilities ]----- */ + +function repeat_string(str, i) { + if (i <= 0) return ""; + if (i == 1) return str; + var d = repeat_string(str, i >> 1); + d += d; + if (i & 1) d += str; + return d; +}; + +function defaults(args, defs) { + var ret = {}; + if (args === true) + args = {}; + for (var i in defs) if (HOP(defs, i)) { + ret[i] = (args && HOP(args, i)) ? args[i] : defs[i]; + } + return ret; +}; + +function is_identifier(name) { + return /^[a-z_$][a-z0-9_$]*$/i.test(name) + && name != "this" + && !HOP(jsp.KEYWORDS_ATOM, name) + && !HOP(jsp.RESERVED_WORDS, name) + && !HOP(jsp.KEYWORDS, name); +}; + +function HOP(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +}; + +// some utilities + +var MAP; + +(function(){ + MAP = function(a, f, o) { + var ret = []; + for (var i = 0; i < a.length; ++i) { + var val = f.call(o, a[i], i); + if (val instanceof AtTop) ret.unshift(val.v); + else ret.push(val); + } + return ret; + }; + MAP.at_top = function(val) { return new AtTop(val) }; + function AtTop(val) { this.v = val }; +})(); + +/* -----[ Exports ]----- */ + +exports.ast_walker = ast_walker; +exports.ast_mangle = ast_mangle; +exports.ast_squeeze = ast_squeeze; +exports.gen_code = gen_code; +exports.ast_add_scope = ast_add_scope; +exports.set_logger = function(logger) { warn = logger }; +exports.make_string = make_string; +exports.split_lines = split_lines; +exports.MAP = MAP; + +// keep this last! +exports.ast_squeeze_more = require("./squeeze-more").ast_squeeze_more; +; + }).call(module.exports); + + __require.modules["/node_modules/burrito/node_modules/uglify-js/lib/process.js"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/burrito/node_modules/uglify-js/lib/squeeze-more.js"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/burrito/node_modules/uglify-js/lib"; + var __filename = "/node_modules/burrito/node_modules/uglify-js/lib/squeeze-more.js"; + + var require = function (file) { + return __require(file, "/node_modules/burrito/node_modules/uglify-js/lib"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/burrito/node_modules/uglify-js/lib"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/burrito/node_modules/uglify-js/lib/squeeze-more.js"]._cached = module.exports; + + (function () { + var jsp = require("./parse-js"), + pro = require("./process"), + slice = jsp.slice, + member = jsp.member, + PRECEDENCE = jsp.PRECEDENCE, + OPERATORS = jsp.OPERATORS; + +function ast_squeeze_more(ast) { + var w = pro.ast_walker(), walk = w.walk; + return w.with_walkers({ + "call": function(expr, args) { + if (expr[0] == "dot" && expr[2] == "toString" && args.length == 0) { + // foo.toString() ==> foo+"" + return [ "binary", "+", expr[1], [ "string", "" ]]; + } + } + }, function() { + return walk(ast); + }); +}; + +exports.ast_squeeze_more = ast_squeeze_more; +; + }).call(module.exports); + + __require.modules["/node_modules/burrito/node_modules/uglify-js/lib/squeeze-more.js"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/burrito/node_modules/traverse/package.json"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/burrito/node_modules/traverse"; + var __filename = "/node_modules/burrito/node_modules/traverse/package.json"; + + var require = function (file) { + return __require(file, "/node_modules/burrito/node_modules/traverse"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/burrito/node_modules/traverse"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/burrito/node_modules/traverse/package.json"]._cached = module.exports; + + (function () { + module.exports = {"name":"traverse","version":"0.5.0","description":"Traverse and transform objects by visiting every node on a recursive walk","author":"James Halliday","license":"MIT/X11","main":"./index","repository":{"type":"git","url":"http://github.com/substack/js-traverse.git"},"devDependencies":{"expresso":"0.7.x"},"scripts":{"test":"expresso"}}; + }).call(module.exports); + + __require.modules["/node_modules/burrito/node_modules/traverse/package.json"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/burrito/node_modules/traverse/index.js"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/burrito/node_modules/traverse"; + var __filename = "/node_modules/burrito/node_modules/traverse/index.js"; + + var require = function (file) { + return __require(file, "/node_modules/burrito/node_modules/traverse"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/burrito/node_modules/traverse"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/burrito/node_modules/traverse/index.js"]._cached = module.exports; + + (function () { + module.exports = Traverse; +function Traverse (obj) { + if (!(this instanceof Traverse)) return new Traverse(obj); + this.value = obj; +} + +Traverse.prototype.get = function (ps) { + var node = this.value; + for (var i = 0; i < ps.length; i ++) { + var key = ps[i]; + if (!Object.hasOwnProperty.call(node, key)) { + node = undefined; + break; + } + node = node[key]; + } + return node; +}; + +Traverse.prototype.set = function (ps, value) { + var node = this.value; + for (var i = 0; i < ps.length - 1; i ++) { + var key = ps[i]; + if (!Object.hasOwnProperty.call(node, key)) node[key] = {}; + node = node[key]; + } + node[ps[i]] = value; + return value; +}; + +Traverse.prototype.map = function (cb) { + return walk(this.value, cb, true); +}; + +Traverse.prototype.forEach = function (cb) { + this.value = walk(this.value, cb, false); + return this.value; +}; + +Traverse.prototype.reduce = function (cb, init) { + var skip = arguments.length === 1; + var acc = skip ? this.value : init; + this.forEach(function (x) { + if (!this.isRoot || !skip) { + acc = cb.call(this, acc, x); + } + }); + return acc; +}; + +Traverse.prototype.paths = function () { + var acc = []; + this.forEach(function (x) { + acc.push(this.path); + }); + return acc; +}; + +Traverse.prototype.nodes = function () { + var acc = []; + this.forEach(function (x) { + acc.push(this.node); + }); + return acc; +}; + +Traverse.prototype.clone = function () { + var parents = [], nodes = []; + + return (function clone (src) { + for (var i = 0; i < parents.length; i++) { + if (parents[i] === src) { + return nodes[i]; + } + } + + if (typeof src === 'object' && src !== null) { + var dst = copy(src); + + parents.push(src); + nodes.push(dst); + + forEach(Object_keys(src), function (key) { + dst[key] = clone(src[key]); + }); + + parents.pop(); + nodes.pop(); + return dst; + } + else { + return src; + } + })(this.value); +}; + +function walk (root, cb, immutable) { + var path = []; + var parents = []; + var alive = true; + + return (function walker (node_) { + var node = immutable ? copy(node_) : node_; + var modifiers = {}; + + var keepGoing = true; + + var state = { + node : node, + node_ : node_, + path : [].concat(path), + parent : parents[parents.length - 1], + parents : parents, + key : path.slice(-1)[0], + isRoot : path.length === 0, + level : path.length, + circular : null, + update : function (x, stopHere) { + if (!state.isRoot) { + state.parent.node[state.key] = x; + } + state.node = x; + if (stopHere) keepGoing = false; + }, + 'delete' : function () { + delete state.parent.node[state.key]; + }, + remove : function () { + if (Array_isArray(state.parent.node)) { + state.parent.node.splice(state.key, 1); + } + else { + delete state.parent.node[state.key]; + } + }, + keys : null, + before : function (f) { modifiers.before = f }, + after : function (f) { modifiers.after = f }, + pre : function (f) { modifiers.pre = f }, + post : function (f) { modifiers.post = f }, + stop : function () { alive = false }, + block : function () { keepGoing = false } + }; + + if (!alive) return state; + + if (typeof node === 'object' && node !== null) { + state.keys = Object_keys(node); + + state.isLeaf = state.keys.length == 0; + + for (var i = 0; i < parents.length; i++) { + if (parents[i].node_ === node_) { + state.circular = parents[i]; + break; + } + } + } + else { + state.isLeaf = true; + } + + state.notLeaf = !state.isLeaf; + state.notRoot = !state.isRoot; + + // use return values to update if defined + var ret = cb.call(state, state.node); + if (ret !== undefined && state.update) state.update(ret); + + if (modifiers.before) modifiers.before.call(state, state.node); + + if (!keepGoing) return state; + + if (typeof state.node == 'object' + && state.node !== null && !state.circular) { + parents.push(state); + + forEach(state.keys, function (key, i) { + path.push(key); + + if (modifiers.pre) modifiers.pre.call(state, state.node[key], key); + + var child = walker(state.node[key]); + if (immutable && Object.hasOwnProperty.call(state.node, key)) { + state.node[key] = child.node; + } + + child.isLast = i == state.keys.length - 1; + child.isFirst = i == 0; + + if (modifiers.post) modifiers.post.call(state, child); + + path.pop(); + }); + parents.pop(); + } + + if (modifiers.after) modifiers.after.call(state, state.node); + + return state; + })(root).node; +} + +function copy (src) { + if (typeof src === 'object' && src !== null) { + var dst; + + if (Array_isArray(src)) { + dst = []; + } + else if (src instanceof Date) { + dst = new Date(src); + } + else if (src instanceof Boolean) { + dst = new Boolean(src); + } + else if (src instanceof Number) { + dst = new Number(src); + } + else if (src instanceof String) { + dst = new String(src); + } + else if (Object.create && Object.getPrototypeOf) { + dst = Object.create(Object.getPrototypeOf(src)); + } + else if (src.__proto__ || src.constructor.prototype) { + var proto = src.__proto__ || src.constructor.prototype || {}; + var T = function () {}; + T.prototype = proto; + dst = new T; + if (!dst.__proto__) dst.__proto__ = proto; + } + + forEach(Object_keys(src), function (key) { + dst[key] = src[key]; + }); + return dst; + } + else return src; +} + +var Object_keys = Object.keys || function keys (obj) { + var res = []; + for (var key in obj) res.push(key) + return res; +}; + +var Array_isArray = Array.isArray || function isArray (xs) { + return Object.prototype.toString.call(xs) === '[object Array]'; +}; + +var forEach = function (xs, fn) { + if (xs.forEach) return xs.forEach(fn) + else for (var i = 0; i < xs.length; i++) { + fn(xs[i], i, xs); + } +}; + +forEach(Object_keys(Traverse.prototype), function (key) { + Traverse[key] = function (obj) { + var args = [].slice.call(arguments, 1); + var t = Traverse(obj); + return t[key].apply(t, args); + }; +}); +; + }).call(module.exports); + + __require.modules["/node_modules/burrito/node_modules/traverse/index.js"]._cached = module.exports; + return module.exports; +}; + +require.modules["vm"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "."; + var __filename = "vm"; + + var require = function (file) { + return __require(file, "."); + }; + + require.resolve = function (file) { + return __require.resolve(name, "."); + }; + + require.modules = __require.modules; + __require.modules["vm"]._cached = module.exports; + + (function () { + var Object_keys = function (obj) { + if (Object.keys) return Object.keys(obj) + else { + var res = []; + for (var key in obj) res.push(key) + return res; + } +}; + +var forEach = function (xs, fn) { + if (xs.forEach) return xs.forEach(fn) + else for (var i = 0; i < xs.length; i++) { + fn(xs[i], i, xs); + } +}; + +var Script = exports.Script = function NodeScript (code) { + if (!(this instanceof Script)) return new Script(code); + this.code = code; +}; + +var iframe = document.createElement('iframe'); +if (!iframe.style) iframe.style = {}; +iframe.style.display = 'none'; + +var iframeCapable = true; // until proven otherwise +if (navigator.appName === 'Microsoft Internet Explorer') { + var m = navigator.appVersion.match(/\bMSIE (\d+\.\d+);/); + if (m && parseFloat(m[1]) <= 9.0) { + iframeCapable = false; + } +} + +Script.prototype.runInNewContext = function (context) { + if (!context) context = {}; + + if (!iframeCapable) { + var keys = Object_keys(context); + var args = []; + for (var i = 0; i < keys.length; i++) { + args.push(context[keys[i]]); + } + + var fn = Function(keys, this.code); + return fn.apply(null, args); + } + + document.body.appendChild(iframe); + + var win = iframe.contentWindow + || (window.frames && window.frames[window.frames.length - 1]) + || window[window.length - 1] + ; + + forEach(Object_keys(context), function (key) { + win[key] = context[key]; + iframe[key] = context[key]; + }); + + if (win.eval) { + // chrome and ff can just .eval() + var res = win.eval(this.code); + } + else { + // this works in IE9 but not anything newer + iframe.setAttribute('src', + 'javascript:__browserifyVmResult=(' + this.code + ')' + ); + if ('__browserifyVmResult' in win) { + var res = win.__browserifyVmResult; + } + else { + iframeCapable = false; + res = this.runInThisContext(context); + } + } + + forEach(Object_keys(win), function (key) { + context[key] = win[key]; + }); + + document.body.removeChild(iframe); + + return res; +}; + +Script.prototype.runInThisContext = function () { + return eval(this.code); // maybe... +}; + +Script.prototype.runInContext = function (context) { + // seems to be just runInNewContext on magical context objects which are + // otherwise indistinguishable from objects except plain old objects + // for the parameter segfaults node + return this.runInNewContext(context); +}; + +forEach(Object_keys(Script.prototype), function (name) { + exports[name] = Script[name] = function (code) { + var s = Script(code); + return s[name].apply(s, [].slice.call(arguments, 1)); + }; +}); + +exports.createScript = function (code) { + return exports.Script(code); +}; + +exports.createContext = Script.createContext = function (context) { + // not really sure what this one does + // seems to just make a shallow copy + var copy = {}; + forEach(Object_keys(context), function (key) { + copy[key] = context[key]; + }); + return copy; +}; +; + }).call(module.exports); + + __require.modules["vm"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/jsonify/package.json"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/jsonify"; + var __filename = "/node_modules/jsonify/package.json"; + + var require = function (file) { + return __require(file, "/node_modules/jsonify"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/jsonify"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/jsonify/package.json"]._cached = module.exports; + + (function () { + module.exports = {"name":"jsonify","version":"0.0.0","description":"JSON without touching any globals","main":"index.js","directories":{"lib":".","test":"test"},"devDependencies":{"tap":"0.0.x","garbage":"0.0.x"},"scripts":{"test":"tap test"},"repository":{"type":"git","url":"http://github.com/substack/jsonify.git"},"keywords":["json","browser"],"author":{"name":"Douglas Crockford","url":"http://crockford.com/"},"license":"Public Domain"}; + }).call(module.exports); + + __require.modules["/node_modules/jsonify/package.json"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/jsonify/index.js"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/jsonify"; + var __filename = "/node_modules/jsonify/index.js"; + + var require = function (file) { + return __require(file, "/node_modules/jsonify"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/jsonify"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/jsonify/index.js"]._cached = module.exports; + + (function () { + exports.parse = require('./lib/parse'); +exports.stringify = require('./lib/stringify'); +; + }).call(module.exports); + + __require.modules["/node_modules/jsonify/index.js"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/jsonify/lib/parse.js"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/jsonify/lib"; + var __filename = "/node_modules/jsonify/lib/parse.js"; + + var require = function (file) { + return __require(file, "/node_modules/jsonify/lib"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/jsonify/lib"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/jsonify/lib/parse.js"]._cached = module.exports; + + (function () { + var at, // The index of the current character + ch, // The current character + escapee = { + '"': '"', + '\\': '\\', + '/': '/', + b: '\b', + f: '\f', + n: '\n', + r: '\r', + t: '\t' + }, + text, + + error = function (m) { + // Call error when something is wrong. + throw { + name: 'SyntaxError', + message: m, + at: at, + text: text + }; + }, + + next = function (c) { + // If a c parameter is provided, verify that it matches the current character. + if (c && c !== ch) { + error("Expected '" + c + "' instead of '" + ch + "'"); + } + + // Get the next character. When there are no more characters, + // return the empty string. + + ch = text.charAt(at); + at += 1; + return ch; + }, + + number = function () { + // Parse a number value. + var number, + string = ''; + + if (ch === '-') { + string = '-'; + next('-'); + } + while (ch >= '0' && ch <= '9') { + string += ch; + next(); + } + if (ch === '.') { + string += '.'; + while (next() && ch >= '0' && ch <= '9') { + string += ch; + } + } + if (ch === 'e' || ch === 'E') { + string += ch; + next(); + if (ch === '-' || ch === '+') { + string += ch; + next(); + } + while (ch >= '0' && ch <= '9') { + string += ch; + next(); + } + } + number = +string; + if (!isFinite(number)) { + error("Bad number"); + } else { + return number; + } + }, + + string = function () { + // Parse a string value. + var hex, + i, + string = '', + uffff; + + // When parsing for string values, we must look for " and \ characters. + if (ch === '"') { + while (next()) { + if (ch === '"') { + next(); + return string; + } else if (ch === '\\') { + next(); + if (ch === 'u') { + uffff = 0; + for (i = 0; i < 4; i += 1) { + hex = parseInt(next(), 16); + if (!isFinite(hex)) { + break; + } + uffff = uffff * 16 + hex; + } + string += String.fromCharCode(uffff); + } else if (typeof escapee[ch] === 'string') { + string += escapee[ch]; + } else { + break; + } + } else { + string += ch; + } + } + } + error("Bad string"); + }, + + white = function () { + +// Skip whitespace. + + while (ch && ch <= ' ') { + next(); + } + }, + + word = function () { + +// true, false, or null. + + switch (ch) { + case 't': + next('t'); + next('r'); + next('u'); + next('e'); + return true; + case 'f': + next('f'); + next('a'); + next('l'); + next('s'); + next('e'); + return false; + case 'n': + next('n'); + next('u'); + next('l'); + next('l'); + return null; + } + error("Unexpected '" + ch + "'"); + }, + + value, // Place holder for the value function. + + array = function () { + +// Parse an array value. + + var array = []; + + if (ch === '[') { + next('['); + white(); + if (ch === ']') { + next(']'); + return array; // empty array + } + while (ch) { + array.push(value()); + white(); + if (ch === ']') { + next(']'); + return array; + } + next(','); + white(); + } + } + error("Bad array"); + }, + + object = function () { + +// Parse an object value. + + var key, + object = {}; + + if (ch === '{') { + next('{'); + white(); + if (ch === '}') { + next('}'); + return object; // empty object + } + while (ch) { + key = string(); + white(); + next(':'); + if (Object.hasOwnProperty.call(object, key)) { + error('Duplicate key "' + key + '"'); + } + object[key] = value(); + white(); + if (ch === '}') { + next('}'); + return object; + } + next(','); + white(); + } + } + error("Bad object"); + }; + +value = function () { + +// Parse a JSON value. It could be an object, an array, a string, a number, +// or a word. + + white(); + switch (ch) { + case '{': + return object(); + case '[': + return array(); + case '"': + return string(); + case '-': + return number(); + default: + return ch >= '0' && ch <= '9' ? number() : word(); + } +}; + +// Return the json_parse function. It will have access to all of the above +// functions and variables. + +module.exports = function (source, reviver) { + var result; + + text = source; + at = 0; + ch = ' '; + result = value(); + white(); + if (ch) { + error("Syntax error"); + } + + // If there is a reviver function, we recursively walk the new structure, + // passing each name/value pair to the reviver function for possible + // transformation, starting with a temporary root object that holds the result + // in an empty key. If there is not a reviver function, we simply return the + // result. + + return typeof reviver === 'function' ? (function walk(holder, key) { + var k, v, value = holder[key]; + if (value && typeof value === 'object') { + for (k in value) { + if (Object.prototype.hasOwnProperty.call(value, k)) { + v = walk(value, k); + if (v !== undefined) { + value[k] = v; + } else { + delete value[k]; + } + } + } + } + return reviver.call(holder, key, value); + }({'': result}, '')) : result; +}; +; + }).call(module.exports); + + __require.modules["/node_modules/jsonify/lib/parse.js"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/jsonify/lib/stringify.js"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/jsonify/lib"; + var __filename = "/node_modules/jsonify/lib/stringify.js"; + + var require = function (file) { + return __require(file, "/node_modules/jsonify/lib"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/jsonify/lib"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/jsonify/lib/stringify.js"]._cached = module.exports; + + (function () { + var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + gap, + indent, + meta = { // table of character substitutions + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"' : '\\"', + '\\': '\\\\' + }, + rep; + +function quote(string) { + // If the string contains no control characters, no quote characters, and no + // backslash characters, then we can safely slap some quotes around it. + // Otherwise we must also replace the offending characters with safe escape + // sequences. + + escapable.lastIndex = 0; + return escapable.test(string) ? '"' + string.replace(escapable, function (a) { + var c = meta[a]; + return typeof c === 'string' ? c : + '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }) + '"' : '"' + string + '"'; +} + +function str(key, holder) { + // Produce a string from holder[key]. + var i, // The loop counter. + k, // The member key. + v, // The member value. + length, + mind = gap, + partial, + value = holder[key]; + + // If the value has a toJSON method, call it to obtain a replacement value. + if (value && typeof value === 'object' && + typeof value.toJSON === 'function') { + value = value.toJSON(key); + } + + // If we were called with a replacer function, then call the replacer to + // obtain a replacement value. + if (typeof rep === 'function') { + value = rep.call(holder, key, value); + } + + // What happens next depends on the value's type. + switch (typeof value) { + case 'string': + return quote(value); + + case 'number': + // JSON numbers must be finite. Encode non-finite numbers as null. + return isFinite(value) ? String(value) : 'null'; + + case 'boolean': + case 'null': + // If the value is a boolean or null, convert it to a string. Note: + // typeof null does not produce 'null'. The case is included here in + // the remote chance that this gets fixed someday. + return String(value); + + case 'object': + if (!value) return 'null'; + gap += indent; + partial = []; + + // Array.isArray + if (Object.prototype.toString.apply(value) === '[object Array]') { + length = value.length; + for (i = 0; i < length; i += 1) { + partial[i] = str(i, value) || 'null'; + } + + // Join all of the elements together, separated with commas, and + // wrap them in brackets. + v = partial.length === 0 ? '[]' : gap ? + '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : + '[' + partial.join(',') + ']'; + gap = mind; + return v; + } + + // If the replacer is an array, use it to select the members to be + // stringified. + if (rep && typeof rep === 'object') { + length = rep.length; + for (i = 0; i < length; i += 1) { + k = rep[i]; + if (typeof k === 'string') { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } + else { + // Otherwise, iterate through all of the keys in the object. + for (k in value) { + if (Object.prototype.hasOwnProperty.call(value, k)) { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } + + // Join all of the member texts together, separated with commas, + // and wrap them in braces. + + v = partial.length === 0 ? '{}' : gap ? + '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : + '{' + partial.join(',') + '}'; + gap = mind; + return v; + } +} + +module.exports = function (value, replacer, space) { + var i; + gap = ''; + indent = ''; + + // If the space parameter is a number, make an indent string containing that + // many spaces. + if (typeof space === 'number') { + for (i = 0; i < space; i += 1) { + indent += ' '; + } + } + // If the space parameter is a string, it will be used as the indent string. + else if (typeof space === 'string') { + indent = space; + } + + // If there is a replacer, it must be a function or an array. + // Otherwise, throw an error. + rep = replacer; + if (replacer && typeof replacer !== 'function' + && (typeof replacer !== 'object' || typeof replacer.length !== 'number')) { + throw new Error('JSON.stringify'); + } + + // Make a fake root object containing our value under the key of ''. + // Return the result of stringifying the value. + return str('', {'': value}); +}; +; + }).call(module.exports); + + __require.modules["/node_modules/jsonify/lib/stringify.js"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/burrito/index.js"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/burrito"; + var __filename = "/node_modules/burrito/index.js"; + + var require = function (file) { + return __require(file, "/node_modules/burrito"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/burrito"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/burrito/index.js"]._cached = module.exports; + + (function () { + var uglify = require('uglify-js'); +var parser = uglify.parser; +var parse = function (expr) { + if (typeof expr !== 'string') throw 'expression should be a string'; + + //try { + var args = [].slice.call(arguments); + var ast = parser.parse.apply(null, args); + /* } + catch (err) { + if (err.message === undefined + || err.line === undefined + || err.col === undefined + || err.pos === undefined + ) { throw err } + + var e = new SyntaxError( + err.message + + '\n at line ' + err.line + ':' + err.col + ' in expression:\n\n' + + ' ' + expr.split(/\r?\n/)[err.line] + ); + + e.original = err; + e.line = err.line; + e.col = err.col; + e.pos = err.pos; + throw e; + } + */ + return ast; +}; + +var deparse = function (ast, b) { + return uglify.uglify.gen_code(ast, { beautify : b }); +}; + +var traverse = require('traverse'); +var vm = require('vm'); + +var burrito = module.exports = function (code, cb) { + var ast = Array_isArray(code) + ? code // already an ast + : parse(code.toString(), false, true) + ; + + var ast_ = traverse(ast).map(function mapper () { + wrapNode(this, cb); + }); + + return deparse(parse(deparse(ast_)), true); +}; + +var wrapNode = burrito.wrapNode = function (state, cb) { + var node = state.node; + + var ann = Array_isArray(node) && node[0] + && typeof node[0] === 'object' && node[0].name + ? node[0] + : null + ; + + if (!ann) return undefined; + + var self = { + name : ann.name, + node : node, + start : node[0].start, + end : node[0].end, + value : node.slice(1), + state : state + }; + + self.wrap = function (s) { + var subsrc = deparse( + traverse(node).map(function (x) { + if (!this.isRoot) wrapNode(this, cb) + }) + ); + + if (self.name === 'binary') { + var a = deparse(traverse(node[2]).map(function (x) { + if (!this.isRoot) wrapNode(this, cb) + })); + var b = deparse(traverse(node[3]).map(function (x) { + if (!this.isRoot) wrapNode(this, cb) + })); + } + + var src = ''; + + if (typeof s === 'function') { + if (self.name === 'binary') { + src = s(subsrc, a, b); + } + else { + src = s(subsrc); + } + } + else { + src = s.toString() + .replace(/%s/g, function () { + return subsrc + }) + ; + + if (self.name === 'binary') { + src = src + .replace(/%a/g, function () { return a }) + .replace(/%b/g, function () { return b }) + ; + } + } + + var expr = parse(src); + state.update(expr, true); + }; + + var cache = {}; + + self.parent = state.isRoot ? null : function () { + if (!cache.parent) { + var s = state; + var x; + do { + s = s.parent; + if (s) x = wrapNode(s); + } while (s && !x); + + cache.parent = x; + } + + return cache.parent; + }; + + self.source = function () { + if (!cache.source) cache.source = deparse(node); + return cache.source; + }; + + self.label = function () { + return burrito.label(self); + }; + + if (cb) cb.call(state, self); + + if (self.node[0].name === 'conditional') { + self.wrap('[%s][0]'); + } + + return self; +} + +burrito.microwave = function (code, context, cb) { + if (!cb) { cb = context; context = {} }; + if (!context) context = {}; + + var src = burrito(code, cb); + return vm.runInNewContext(src, context); +}; + +burrito.generateName = function (len) { + var name = ''; + var lower = '$'.charCodeAt(0); + var upper = 'z'.charCodeAt(0); + + while (name.length < len) { + var c = String.fromCharCode(Math.floor( + Math.random() * (upper - lower + 1) + lower + )); + if ((name + c).match(/^[A-Za-z_$][A-Za-z0-9_$]*$/)) name += c; + } + + return name; +}; + +burrito.parse = parse; +burrito.deparse = deparse; + +burrito.label = function (node) { + if (node.name === 'call') { + if (typeof node.value[0] === 'string') { + return node.value[0]; + } + else if (node.value[0] && typeof node.value[0][1] === 'string') { + return node.value[0][1]; + } + else { + return null; + } + } + else if (node.name === 'var') { + return node.value[0].map(function (x) { return x[0] }); + } + else if (node.name === 'defun') { + return node.value[0]; + } + else if (node.name === 'function') { + return node.value[0]; + } + else { + return null; + } +}; + +var Array_isArray = Array.isArray || function isArray (xs) { + return Object.prototype.toString.call(xs) === '[object Array]'; +}; +; + }).call(module.exports); + + __require.modules["/node_modules/burrito/index.js"]._cached = module.exports; + return module.exports; +}; + +process.nextTick(function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/"; + var __filename = "//home/substack/projects/node-burrito/example/web"; + + var require = function (file) { + return __require(file, "/"); + }; + require.modules = __require.modules; + + var burrito = require('burrito'); +var json = require('jsonify'); + +var src = [ + 'function f () { g() }', + 'function g () { h() }', + 'function h () { throw "moo" + Array(x).join("!") }', + 'var x = 4', + 'f()' +].join('\r\n'); + +window.onload = function () { + burrito(src, function (node) { + document.body.innerHTML += node.name + '
\n'; + }); +}; +if (document.readyState === 'complete') window.onload(); +; +}); diff --git a/node_modules/burrito/example/web/index.html b/node_modules/burrito/example/web/index.html new file mode 100644 index 0000000..66804fb --- /dev/null +++ b/node_modules/burrito/example/web/index.html @@ -0,0 +1,14 @@ + + + + + + +


+
+
diff --git a/node_modules/burrito/example/web/main.js b/node_modules/burrito/example/web/main.js
new file mode 100644
index 0000000..cc81a8b
--- /dev/null
+++ b/node_modules/burrito/example/web/main.js
@@ -0,0 +1,17 @@
+var burrito = require('burrito');
+var json = require('jsonify');
+
+var src = [
+    'function f () { g() }',
+    'function g () { h() }',
+    'function h () { throw "moo" + Array(x).join("!") }',
+    'var x = 4',
+    'f()'
+].join('\r\n');
+
+window.onload = function () {
+    burrito(src, function (node) {
+        document.body.innerHTML += node.name + '
\n'; + }); +}; +if (document.readyState === 'complete') window.onload(); diff --git a/node_modules/burrito/example/web/server.js b/node_modules/burrito/example/web/server.js new file mode 100644 index 0000000..6bce020 --- /dev/null +++ b/node_modules/burrito/example/web/server.js @@ -0,0 +1,12 @@ +var express = require('express'); +var browserify = require('browserify'); + +var app = express.createServer(); +app.use(express.static(__dirname)); +app.use(browserify({ + entry : __dirname + '/main.js', + watch : true, +})); + +app.listen(8081); +console.log('Listening on :8081'); diff --git a/node_modules/burrito/example/wrap.js b/node_modules/burrito/example/wrap.js new file mode 100644 index 0000000..1642401 --- /dev/null +++ b/node_modules/burrito/example/wrap.js @@ -0,0 +1,7 @@ +var burrito = require('burrito'); + +var src = burrito('f() && g(h())\nfoo()', function (node) { + if (node.name === 'call') node.wrap('qqq(%s)'); +}); + +console.log(src); diff --git a/node_modules/burrito/index.js b/node_modules/burrito/index.js new file mode 100644 index 0000000..60ef569 --- /dev/null +++ b/node_modules/burrito/index.js @@ -0,0 +1,208 @@ +var uglify = require('uglify-js'); +var parser = uglify.parser; +var parse = function (expr) { + if (typeof expr !== 'string') throw 'expression should be a string'; + + try { + var ast = parser.parse.apply(null, arguments); + } + catch (err) { + if (err.message === undefined + || err.line === undefined + || err.col === undefined + || err.pos === undefined + ) { throw err } + + var e = new SyntaxError( + err.message + + '\n at line ' + err.line + ':' + err.col + ' in expression:\n\n' + + ' ' + expr.split(/\r?\n/)[err.line] + ); + + e.original = err; + e.line = err.line; + e.col = err.col; + e.pos = err.pos; + throw e; + } + return ast; +}; + +var deparse = function (ast, b) { + return uglify.uglify.gen_code(ast, { beautify : b }); +}; + +var traverse = require('traverse'); +var vm = require('vm'); + +var burrito = module.exports = function (code, cb) { + var ast = Array_isArray(code) + ? code // already an ast + : parse(code.toString(), false, true) + ; + + var ast_ = traverse(ast).map(function mapper () { + wrapNode(this, cb); + }); + + return deparse(parse(deparse(ast_)), true); +}; + +var wrapNode = burrito.wrapNode = function (state, cb) { + var node = state.node; + + var ann = Array_isArray(node) && node[0] + && typeof node[0] === 'object' && node[0].name + ? node[0] + : null + ; + + if (!ann) return undefined; + + var self = { + name : ann.name, + node : node, + start : node[0].start, + end : node[0].end, + value : node.slice(1), + state : state + }; + + self.wrap = function (s) { + var subsrc = deparse( + traverse(node).map(function (x) { + if (!this.isRoot) wrapNode(this, cb) + }) + ); + + if (self.name === 'binary') { + var a = deparse(traverse(node[2]).map(function (x) { + if (!this.isRoot) wrapNode(this, cb) + })); + var b = deparse(traverse(node[3]).map(function (x) { + if (!this.isRoot) wrapNode(this, cb) + })); + } + + var src = ''; + + if (typeof s === 'function') { + if (self.name === 'binary') { + src = s(subsrc, a, b); + } + else { + src = s(subsrc); + } + } + else { + src = s.toString() + .replace(/%s/g, function () { + return subsrc + }) + ; + + if (self.name === 'binary') { + src = src + .replace(/%a/g, function () { return a }) + .replace(/%b/g, function () { return b }) + ; + } + } + + var expr = parse(src); + state.update(expr, true); + }; + + var cache = {}; + + self.parent = state.isRoot ? null : function () { + if (!cache.parent) { + var s = state; + var x; + do { + s = s.parent; + if (s) x = wrapNode(s); + } while (s && !x); + + cache.parent = x; + } + + return cache.parent; + }; + + self.source = function () { + if (!cache.source) cache.source = deparse(node); + return cache.source; + }; + + self.label = function () { + return burrito.label(self); + }; + + if (cb) cb.call(state, self); + + if (self.node[0].name === 'conditional') { + self.wrap('[%s][0]'); + } + + return self; +} + +burrito.microwave = function (code, context, cb) { + if (!cb) { cb = context; context = {} }; + if (!context) context = {}; + + var src = burrito(code, cb); + return vm.runInNewContext(src, context); +}; + +burrito.generateName = function (len) { + var name = ''; + var lower = '$'.charCodeAt(0); + var upper = 'z'.charCodeAt(0); + + while (name.length < len) { + var c = String.fromCharCode(Math.floor( + Math.random() * (upper - lower + 1) + lower + )); + if ((name + c).match(/^[A-Za-z_$][A-Za-z0-9_$]*$/)) name += c; + } + + return name; +}; + +burrito.parse = parse; +burrito.deparse = deparse; + +burrito.label = function (node) { + if (node.name === 'call') { + if (typeof node.value[0] === 'string') { + return node.value[0]; + } + else if (node.value[0] && typeof node.value[0][1] === 'string') { + return node.value[0][1]; + } + else if (node.value[0][0] === 'dot') { + return node.value[0][node.value[0].length - 1]; + } + else { + return null; + } + } + else if (node.name === 'var') { + return node.value[0].map(function (x) { return x[0] }); + } + else if (node.name === 'defun') { + return node.value[0]; + } + else if (node.name === 'function') { + return node.value[0]; + } + else { + return null; + } +}; + +var Array_isArray = Array.isArray || function isArray (xs) { + return Object.prototype.toString.call(xs) === '[object Array]'; +}; diff --git a/node_modules/burrito/node_modules/traverse/.npmignore b/node_modules/burrito/node_modules/traverse/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/burrito/node_modules/traverse/LICENSE b/node_modules/burrito/node_modules/traverse/LICENSE new file mode 100644 index 0000000..7b75500 --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/LICENSE @@ -0,0 +1,24 @@ +Copyright 2010 James Halliday (mail@substack.net) + +This project is free software released under the MIT/X11 license: +http://www.opensource.org/licenses/mit-license.php + +Copyright 2010 James Halliday (mail@substack.net) + +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/burrito/node_modules/traverse/README.markdown b/node_modules/burrito/node_modules/traverse/README.markdown new file mode 100644 index 0000000..f86ef76 --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/README.markdown @@ -0,0 +1,237 @@ +traverse +======== + +Traverse and transform objects by visiting every node on a recursive walk. + +examples +======== + +transform negative numbers in-place +----------------------------------- + +negative.js + +````javascript +var traverse = require('traverse'); +var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + +traverse(obj).forEach(function (x) { + if (x < 0) this.update(x + 128); +}); + +console.dir(obj); +```` + +Output: + + [ 5, 6, 125, [ 7, 8, 126, 1 ], { f: 10, g: 115 } ] + +collect leaf nodes +------------------ + +leaves.js + +````javascript +var traverse = require('traverse'); + +var obj = { + a : [1,2,3], + b : 4, + c : [5,6], + d : { e : [7,8], f : 9 }, +}; + +var leaves = traverse(obj).reduce(function (acc, x) { + if (this.isLeaf) acc.push(x); + return acc; +}, []); + +console.dir(leaves); +```` + +Output: + + [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ] + +scrub circular references +------------------------- + +scrub.js: + +````javascript +var traverse = require('traverse'); + +var obj = { a : 1, b : 2, c : [ 3, 4 ] }; +obj.c.push(obj); + +var scrubbed = traverse(obj).map(function (x) { + if (this.circular) this.remove() +}); +console.dir(scrubbed); +```` + +output: + + { a: 1, b: 2, c: [ 3, 4 ] } + +context +======= + +Each method that takes a callback has a context (its `this` object) with these +attributes: + +this.node +--------- + +The present node on the recursive walk + +this.path +--------- + +An array of string keys from the root to the present node + +this.parent +----------- + +The context of the node's parent. +This is `undefined` for the root node. + +this.key +-------- + +The name of the key of the present node in its parent. +This is `undefined` for the root node. + +this.isRoot, this.notRoot +------------------------- + +Whether the present node is the root node + +this.isLeaf, this.notLeaf +------------------------- + +Whether or not the present node is a leaf node (has no children) + +this.level +---------- + +Depth of the node within the traversal + +this.circular +------------- + +If the node equals one of its parents, the `circular` attribute is set to the +context of that parent and the traversal progresses no deeper. + +this.update(value, stopHere=false) +---------------------------------- + +Set a new value for the present node. + +All the elements in `value` will be recursively traversed unless `stopHere` is +true. + +this.remove(stopHere=false) +------------- + +Remove the current element from the output. If the node is in an Array it will +be spliced off. Otherwise it will be deleted from its parent. + +this.delete(stopHere=false) +------------- + +Delete the current element from its parent in the output. Calls `delete` even on +Arrays. + +this.before(fn) +--------------- + +Call this function before any of the children are traversed. + +You can assign into `this.keys` here to traverse in a custom order. + +this.after(fn) +-------------- + +Call this function after any of the children are traversed. + +this.pre(fn) +------------ + +Call this function before each of the children are traversed. + +this.post(fn) +------------- + +Call this function after each of the children are traversed. + +methods +======= + +.map(fn) +-------- + +Execute `fn` for each node in the object and return a new object with the +results of the walk. To update nodes in the result use `this.update(value)`. + +.forEach(fn) +------------ + +Execute `fn` for each node in the object but unlike `.map()`, when +`this.update()` is called it updates the object in-place. + +.reduce(fn, acc) +---------------- + +For each node in the object, perform a +[left-fold](http://en.wikipedia.org/wiki/Fold_(higher-order_function)) +with the return value of `fn(acc, node)`. + +If `acc` isn't specified, `acc` is set to the root object for the first step +and the root element is skipped. + +.paths() +-------- + +Return an `Array` of every possible non-cyclic path in the object. +Paths are `Array`s of string keys. + +.nodes() +-------- + +Return an `Array` of every node in the object. + +.clone() +-------- + +Create a deep clone of the object. + +install +======= + +Using [npm](http://npmjs.org) do: + + $ npm install traverse + +test +==== + +Using [expresso](http://github.com/visionmedia/expresso) do: + + $ expresso + + 100% wahoo, your stuff is not broken! + +in the browser +============== + +Use [browserify](https://github.com/substack/node-browserify) to run traverse in +the browser. + +traverse has been tested and works with: + +* Internet Explorer 5.5, 6.0, 7.0, 8.0, 9.0 +* Firefox 3.5 +* Chrome 6.0 +* Opera 10.6 +* Safari 5.0 diff --git a/node_modules/burrito/node_modules/traverse/examples/json.js b/node_modules/burrito/node_modules/traverse/examples/json.js new file mode 100755 index 0000000..50d612e --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/examples/json.js @@ -0,0 +1,16 @@ +var traverse = require('traverse'); + +var id = 54; +var callbacks = {}; +var obj = { moo : function () {}, foo : [2,3,4, function () {}] }; + +var scrubbed = traverse(obj).map(function (x) { + if (typeof x === 'function') { + callbacks[id] = { id : id, f : x, path : this.path }; + this.update('[Function]'); + id++; + } +}); + +console.dir(scrubbed); +console.dir(callbacks); diff --git a/node_modules/burrito/node_modules/traverse/examples/leaves.js b/node_modules/burrito/node_modules/traverse/examples/leaves.js new file mode 100755 index 0000000..c1b310b --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/examples/leaves.js @@ -0,0 +1,15 @@ +var traverse = require('traverse'); + +var obj = { + a : [1,2,3], + b : 4, + c : [5,6], + d : { e : [7,8], f : 9 }, +}; + +var leaves = traverse(obj).reduce(function (acc, x) { + if (this.isLeaf) acc.push(x); + return acc; +}, []); + +console.dir(leaves); diff --git a/node_modules/burrito/node_modules/traverse/examples/negative.js b/node_modules/burrito/node_modules/traverse/examples/negative.js new file mode 100755 index 0000000..78608a0 --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/examples/negative.js @@ -0,0 +1,8 @@ +var traverse = require('traverse'); +var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + +traverse(obj).forEach(function (x) { + if (x < 0) this.update(x + 128); +}); + +console.dir(obj); diff --git a/node_modules/burrito/node_modules/traverse/examples/scrub.js b/node_modules/burrito/node_modules/traverse/examples/scrub.js new file mode 100755 index 0000000..5d15b91 --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/examples/scrub.js @@ -0,0 +1,10 @@ +// scrub out circular references +var traverse = require('traverse'); + +var obj = { a : 1, b : 2, c : [ 3, 4 ] }; +obj.c.push(obj); + +var scrubbed = traverse(obj).map(function (x) { + if (this.circular) this.remove() +}); +console.dir(scrubbed); diff --git a/node_modules/burrito/node_modules/traverse/examples/stringify.js b/node_modules/burrito/node_modules/traverse/examples/stringify.js new file mode 100755 index 0000000..167b68b --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/examples/stringify.js @@ -0,0 +1,38 @@ +#!/usr/bin/env node +var traverse = require('traverse'); + +var obj = [ 'five', 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + +var s = ''; +traverse(obj).forEach(function to_s (node) { + if (Array.isArray(node)) { + this.before(function () { s += '[' }); + this.post(function (child) { + if (!child.isLast) s += ','; + }); + this.after(function () { s += ']' }); + } + else if (typeof node == 'object') { + this.before(function () { s += '{' }); + this.pre(function (x, key) { + to_s(key); + s += ':'; + }); + this.post(function (child) { + if (!child.isLast) s += ','; + }); + this.after(function () { s += '}' }); + } + else if (typeof node == 'string') { + s += '"' + node.toString().replace(/"/g, '\\"') + '"'; + } + else if (typeof node == 'function') { + s += 'null'; + } + else { + s += node.toString(); + } +}); + +console.log('JSON.stringify: ' + JSON.stringify(obj)); +console.log('this stringify: ' + s); diff --git a/node_modules/burrito/node_modules/traverse/index.js b/node_modules/burrito/node_modules/traverse/index.js new file mode 100644 index 0000000..038a1ad --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/index.js @@ -0,0 +1,267 @@ +module.exports = Traverse; +function Traverse (obj) { + if (!(this instanceof Traverse)) return new Traverse(obj); + this.value = obj; +} + +Traverse.prototype.get = function (ps) { + var node = this.value; + for (var i = 0; i < ps.length; i ++) { + var key = ps[i]; + if (!Object.hasOwnProperty.call(node, key)) { + node = undefined; + break; + } + node = node[key]; + } + return node; +}; + +Traverse.prototype.set = function (ps, value) { + var node = this.value; + for (var i = 0; i < ps.length - 1; i ++) { + var key = ps[i]; + if (!Object.hasOwnProperty.call(node, key)) node[key] = {}; + node = node[key]; + } + node[ps[i]] = value; + return value; +}; + +Traverse.prototype.map = function (cb) { + return walk(this.value, cb, true); +}; + +Traverse.prototype.forEach = function (cb) { + this.value = walk(this.value, cb, false); + return this.value; +}; + +Traverse.prototype.reduce = function (cb, init) { + var skip = arguments.length === 1; + var acc = skip ? this.value : init; + this.forEach(function (x) { + if (!this.isRoot || !skip) { + acc = cb.call(this, acc, x); + } + }); + return acc; +}; + +Traverse.prototype.paths = function () { + var acc = []; + this.forEach(function (x) { + acc.push(this.path); + }); + return acc; +}; + +Traverse.prototype.nodes = function () { + var acc = []; + this.forEach(function (x) { + acc.push(this.node); + }); + return acc; +}; + +Traverse.prototype.clone = function () { + var parents = [], nodes = []; + + return (function clone (src) { + for (var i = 0; i < parents.length; i++) { + if (parents[i] === src) { + return nodes[i]; + } + } + + if (typeof src === 'object' && src !== null) { + var dst = copy(src); + + parents.push(src); + nodes.push(dst); + + forEach(Object_keys(src), function (key) { + dst[key] = clone(src[key]); + }); + + parents.pop(); + nodes.pop(); + return dst; + } + else { + return src; + } + })(this.value); +}; + +function walk (root, cb, immutable) { + var path = []; + var parents = []; + var alive = true; + + return (function walker (node_) { + var node = immutable ? copy(node_) : node_; + var modifiers = {}; + + var keepGoing = true; + + var state = { + node : node, + node_ : node_, + path : [].concat(path), + parent : parents[parents.length - 1], + parents : parents, + key : path.slice(-1)[0], + isRoot : path.length === 0, + level : path.length, + circular : null, + update : function (x, stopHere) { + if (!state.isRoot) { + state.parent.node[state.key] = x; + } + state.node = x; + if (stopHere) keepGoing = false; + }, + 'delete' : function (stopHere) { + delete state.parent.node[state.key]; + if (stopHere) keepGoing = false; + }, + remove : function (stopHere) { + if (Array_isArray(state.parent.node)) { + state.parent.node.splice(state.key, 1); + } + else { + delete state.parent.node[state.key]; + } + if (stopHere) keepGoing = false; + }, + keys : null, + before : function (f) { modifiers.before = f }, + after : function (f) { modifiers.after = f }, + pre : function (f) { modifiers.pre = f }, + post : function (f) { modifiers.post = f }, + stop : function () { alive = false }, + block : function () { keepGoing = false } + }; + + if (!alive) return state; + + if (typeof node === 'object' && node !== null) { + state.keys = Object_keys(node); + + state.isLeaf = state.keys.length == 0; + + for (var i = 0; i < parents.length; i++) { + if (parents[i].node_ === node_) { + state.circular = parents[i]; + break; + } + } + } + else { + state.isLeaf = true; + } + + state.notLeaf = !state.isLeaf; + state.notRoot = !state.isRoot; + + // use return values to update if defined + var ret = cb.call(state, state.node); + if (ret !== undefined && state.update) state.update(ret); + + if (modifiers.before) modifiers.before.call(state, state.node); + + if (!keepGoing) return state; + + if (typeof state.node == 'object' + && state.node !== null && !state.circular) { + parents.push(state); + + forEach(state.keys, function (key, i) { + path.push(key); + + if (modifiers.pre) modifiers.pre.call(state, state.node[key], key); + + var child = walker(state.node[key]); + if (immutable && Object.hasOwnProperty.call(state.node, key)) { + state.node[key] = child.node; + } + + child.isLast = i == state.keys.length - 1; + child.isFirst = i == 0; + + if (modifiers.post) modifiers.post.call(state, child); + + path.pop(); + }); + parents.pop(); + } + + if (modifiers.after) modifiers.after.call(state, state.node); + + return state; + })(root).node; +} + +function copy (src) { + if (typeof src === 'object' && src !== null) { + var dst; + + if (Array_isArray(src)) { + dst = []; + } + else if (src instanceof Date) { + dst = new Date(src); + } + else if (src instanceof Boolean) { + dst = new Boolean(src); + } + else if (src instanceof Number) { + dst = new Number(src); + } + else if (src instanceof String) { + dst = new String(src); + } + else if (Object.create && Object.getPrototypeOf) { + dst = Object.create(Object.getPrototypeOf(src)); + } + else if (src.__proto__ || src.constructor.prototype) { + var proto = src.__proto__ || src.constructor.prototype || {}; + var T = function () {}; + T.prototype = proto; + dst = new T; + if (!dst.__proto__) dst.__proto__ = proto; + } + + forEach(Object_keys(src), function (key) { + dst[key] = src[key]; + }); + return dst; + } + else return src; +} + +var Object_keys = Object.keys || function keys (obj) { + var res = []; + for (var key in obj) res.push(key) + return res; +}; + +var Array_isArray = Array.isArray || function isArray (xs) { + return Object.prototype.toString.call(xs) === '[object Array]'; +}; + +var forEach = function (xs, fn) { + if (xs.forEach) return xs.forEach(fn) + else for (var i = 0; i < xs.length; i++) { + fn(xs[i], i, xs); + } +}; + +forEach(Object_keys(Traverse.prototype), function (key) { + Traverse[key] = function (obj) { + var args = [].slice.call(arguments, 1); + var t = Traverse(obj); + return t[key].apply(t, args); + }; +}); diff --git a/node_modules/burrito/node_modules/traverse/main.js b/node_modules/burrito/node_modules/traverse/main.js new file mode 100755 index 0000000..d562d37 --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/main.js @@ -0,0 +1,10 @@ +// scrub out circular references +var traverse = require('./index.js'); + +var obj = { a : 1, b : 2, c : [ 3, 4 ] }; +obj.c.push(obj); + +var scrubbed = traverse(obj).map(function (x) { + if (this.circular) this.remove() +}); +console.dir(scrubbed); diff --git a/node_modules/burrito/node_modules/traverse/package.json b/node_modules/burrito/node_modules/traverse/package.json new file mode 100644 index 0000000..f86322a --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/package.json @@ -0,0 +1,18 @@ +{ + "name" : "traverse", + "version" : "0.5.2", + "description" : "Traverse and transform objects by visiting every node on a recursive walk", + "author" : "James Halliday", + "license" : "MIT/X11", + "main" : "./index", + "repository" : { + "type" : "git", + "url" : "http://github.com/substack/js-traverse.git" + }, + "devDependencies" : { + "expresso" : "0.7.x" + }, + "scripts" : { + "test" : "expresso" + } +} diff --git a/node_modules/burrito/node_modules/traverse/test/circular.js b/node_modules/burrito/node_modules/traverse/test/circular.js new file mode 100644 index 0000000..9162601 --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/test/circular.js @@ -0,0 +1,115 @@ +var assert = require('assert'); +var Traverse = require('../'); +var deepEqual = require('./lib/deep_equal'); +var util = require('util'); + +exports.circular = function () { + var obj = { x : 3 }; + obj.y = obj; + var foundY = false; + Traverse(obj).forEach(function (x) { + if (this.path.join('') == 'y') { + assert.equal( + util.inspect(this.circular.node), + util.inspect(obj) + ); + foundY = true; + } + }); + assert.ok(foundY); +}; + +exports.deepCirc = function () { + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; + obj.y[2] = obj; + + var times = 0; + Traverse(obj).forEach(function (x) { + if (this.circular) { + assert.deepEqual(this.circular.path, []); + assert.deepEqual(this.path, [ 'y', 2 ]); + times ++; + } + }); + + assert.deepEqual(times, 1); +}; + +exports.doubleCirc = function () { + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + var circs = []; + Traverse(obj).forEach(function (x) { + if (this.circular) { + circs.push({ circ : this.circular, self : this, node : x }); + } + }); + + assert.deepEqual(circs[0].self.path, [ 'x', 3, 2 ]); + assert.deepEqual(circs[0].circ.path, []); + + assert.deepEqual(circs[1].self.path, [ 'y', 2 ]); + assert.deepEqual(circs[1].circ.path, []); + + assert.deepEqual(circs.length, 2); +}; + +exports.circDubForEach = function () { + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + Traverse(obj).forEach(function (x) { + if (this.circular) this.update('...'); + }); + + assert.deepEqual(obj, { x : [ 1, 2, 3, [ 4, 5, '...' ] ], y : [ 4, 5, '...' ] }); +}; + +exports.circDubMap = function () { + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + var c = Traverse(obj).map(function (x) { + if (this.circular) { + this.update('...'); + } + }); + + assert.deepEqual(c, { x : [ 1, 2, 3, [ 4, 5, '...' ] ], y : [ 4, 5, '...' ] }); +}; + +exports.circClone = function () { + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + var clone = Traverse.clone(obj); + assert.ok(obj !== clone); + + assert.ok(clone.y[2] === clone); + assert.ok(clone.y[2] !== obj); + assert.ok(clone.x[3][2] === clone); + assert.ok(clone.x[3][2] !== obj); + assert.deepEqual(clone.x.slice(0,3), [1,2,3]); + assert.deepEqual(clone.y.slice(0,2), [4,5]); +}; + +exports.circMapScrub = function () { + var obj = { a : 1, b : 2 }; + obj.c = obj; + + var scrubbed = Traverse(obj).map(function (node) { + if (this.circular) this.remove(); + }); + assert.deepEqual( + Object.keys(scrubbed).sort(), + [ 'a', 'b' ] + ); + assert.ok(deepEqual(scrubbed, { a : 1, b : 2 })); + + assert.equal(obj.c, obj); +}; diff --git a/node_modules/burrito/node_modules/traverse/test/date.js b/node_modules/burrito/node_modules/traverse/test/date.js new file mode 100644 index 0000000..4ca06dc --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/test/date.js @@ -0,0 +1,35 @@ +var assert = require('assert'); +var Traverse = require('../'); + +exports.dateEach = function () { + var obj = { x : new Date, y : 10, z : 5 }; + + var counts = {}; + + Traverse(obj).forEach(function (node) { + var t = (node instanceof Date && 'Date') || typeof node; + counts[t] = (counts[t] || 0) + 1; + }); + + assert.deepEqual(counts, { + object : 1, + Date : 1, + number : 2, + }); +}; + +exports.dateMap = function () { + var obj = { x : new Date, y : 10, z : 5 }; + + var res = Traverse(obj).map(function (node) { + if (typeof node === 'number') this.update(node + 100); + }); + + assert.ok(obj.x !== res.x); + assert.deepEqual(res, { + x : obj.x, + y : 110, + z : 105, + }); +}; + diff --git a/node_modules/burrito/node_modules/traverse/test/equal.js b/node_modules/burrito/node_modules/traverse/test/equal.js new file mode 100644 index 0000000..decc755 --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/test/equal.js @@ -0,0 +1,220 @@ +var assert = require('assert'); +var traverse = require('../'); +var deepEqual = require('./lib/deep_equal'); + +exports.deepDates = function () { + assert.ok( + deepEqual( + { d : new Date, x : [ 1, 2, 3 ] }, + { d : new Date, x : [ 1, 2, 3 ] } + ), + 'dates should be equal' + ); + + var d0 = new Date; + setTimeout(function () { + assert.ok( + !deepEqual( + { d : d0, x : [ 1, 2, 3 ], }, + { d : new Date, x : [ 1, 2, 3 ] } + ), + 'microseconds should count in date equality' + ); + }, 5); +}; + +exports.deepCircular = function () { + var a = [1]; + a.push(a); // a = [ 1, *a ] + + var b = [1]; + b.push(a); // b = [ 1, [ 1, *a ] ] + + assert.ok( + !deepEqual(a, b), + 'circular ref mount points count towards equality' + ); + + var c = [1]; + c.push(c); // c = [ 1, *c ] + assert.ok( + deepEqual(a, c), + 'circular refs are structurally the same here' + ); + + var d = [1]; + d.push(a); // c = [ 1, [ 1, *d ] ] + assert.ok( + deepEqual(b, d), + 'non-root circular ref structural comparison' + ); +}; + +exports.deepInstances = function () { + assert.ok( + !deepEqual([ new Boolean(false) ], [ false ]), + 'boolean instances are not real booleans' + ); + + assert.ok( + !deepEqual([ new String('x') ], [ 'x' ]), + 'string instances are not real strings' + ); + + assert.ok( + !deepEqual([ new Number(4) ], [ 4 ]), + 'number instances are not real numbers' + ); + + assert.ok( + deepEqual([ new RegExp('x') ], [ /x/ ]), + 'regexp instances are real regexps' + ); + + assert.ok( + !deepEqual([ new RegExp(/./) ], [ /../ ]), + 'these regexps aren\'t the same' + ); + + assert.ok( + !deepEqual( + [ function (x) { return x * 2 } ], + [ function (x) { return x * 2 } ] + ), + 'functions with the same .toString() aren\'t necessarily the same' + ); + + var f = function (x) { return x * 2 }; + assert.ok( + deepEqual([ f ], [ f ]), + 'these functions are actually equal' + ); +}; + +exports.deepEqual = function () { + assert.ok( + !deepEqual([ 1, 2, 3 ], { 0 : 1, 1 : 2, 2 : 3 }), + 'arrays are not objects' + ); +}; + +exports.falsy = function () { + assert.ok( + !deepEqual([ undefined ], [ null ]), + 'null is not undefined!' + ); + + assert.ok( + !deepEqual([ null ], [ undefined ]), + 'undefined is not null!' + ); + + assert.ok( + !deepEqual( + { a : 1, b : 2, c : [ 3, undefined, 5 ] }, + { a : 1, b : 2, c : [ 3, null, 5 ] } + ), + 'undefined is not null, however deeply!' + ); + + assert.ok( + !deepEqual( + { a : 1, b : 2, c : [ 3, undefined, 5 ] }, + { a : 1, b : 2, c : [ 3, null, 5 ] } + ), + 'null is not undefined, however deeply!' + ); + + assert.ok( + !deepEqual( + { a : 1, b : 2, c : [ 3, undefined, 5 ] }, + { a : 1, b : 2, c : [ 3, null, 5 ] } + ), + 'null is not undefined, however deeply!' + ); +}; + +exports.deletedArrayEqual = function () { + var xs = [ 1, 2, 3, 4 ]; + delete xs[2]; + + var ys = Object.create(Array.prototype); + ys[0] = 1; + ys[1] = 2; + ys[3] = 4; + + assert.ok( + deepEqual(xs, ys), + 'arrays with deleted elements are only equal to' + + ' arrays with similarly deleted elements' + ); + + assert.ok( + !deepEqual(xs, [ 1, 2, undefined, 4 ]), + 'deleted array elements cannot be undefined' + ); + + assert.ok( + !deepEqual(xs, [ 1, 2, null, 4 ]), + 'deleted array elements cannot be null' + ); +}; + +exports.deletedObjectEqual = function () { + var obj = { a : 1, b : 2, c : 3 }; + delete obj.c; + + assert.ok( + deepEqual(obj, { a : 1, b : 2 }), + 'deleted object elements should not show up' + ); + + assert.ok( + !deepEqual(obj, { a : 1, b : 2, c : undefined }), + 'deleted object elements are not undefined' + ); + + assert.ok( + !deepEqual(obj, { a : 1, b : 2, c : null }), + 'deleted object elements are not null' + ); +}; + +exports.emptyKeyEqual = function () { + assert.ok(!deepEqual( + { a : 1 }, { a : 1, '' : 55 } + )); +}; + +exports.deepArguments = function () { + assert.ok( + !deepEqual( + [ 4, 5, 6 ], + (function () { return arguments })(4, 5, 6) + ), + 'arguments are not arrays' + ); + + assert.ok( + deepEqual( + (function () { return arguments })(4, 5, 6), + (function () { return arguments })(4, 5, 6) + ), + 'arguments should equal' + ); +}; + +exports.deepUn = function () { + assert.ok(!deepEqual({ a : 1, b : 2 }, undefined)); + assert.ok(!deepEqual({ a : 1, b : 2 }, {})); + assert.ok(!deepEqual(undefined, { a : 1, b : 2 })); + assert.ok(!deepEqual({}, { a : 1, b : 2 })); + assert.ok(deepEqual(undefined, undefined)); + assert.ok(deepEqual(null, null)); + assert.ok(!deepEqual(undefined, null)); +}; + +exports.deepLevels = function () { + var xs = [ 1, 2, [ 3, 4, [ 5, 6 ] ] ]; + assert.ok(!deepEqual(xs, [])); +}; diff --git a/node_modules/burrito/node_modules/traverse/test/instance.js b/node_modules/burrito/node_modules/traverse/test/instance.js new file mode 100644 index 0000000..8d73525 --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/test/instance.js @@ -0,0 +1,17 @@ +var assert = require('assert'); +var Traverse = require('../'); +var EventEmitter = require('events').EventEmitter; + +exports['check instanceof on node elems'] = function () { + + var counts = { emitter : 0 }; + + Traverse([ new EventEmitter, 3, 4, { ev : new EventEmitter }]) + .forEach(function (node) { + if (node instanceof EventEmitter) counts.emitter ++; + }) + ; + + assert.equal(counts.emitter, 2); +}; + diff --git a/node_modules/burrito/node_modules/traverse/test/interface.js b/node_modules/burrito/node_modules/traverse/test/interface.js new file mode 100644 index 0000000..fce5bf9 --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/test/interface.js @@ -0,0 +1,42 @@ +var assert = require('assert'); +var Traverse = require('../'); + +exports['interface map'] = function () { + var obj = { a : [ 5,6,7 ], b : { c : [8] } }; + + assert.deepEqual( + Traverse.paths(obj) + .sort() + .map(function (path) { return path.join('/') }) + .slice(1) + .join(' ') + , + 'a a/0 a/1 a/2 b b/c b/c/0' + ); + + assert.deepEqual( + Traverse.nodes(obj), + [ + { a: [ 5, 6, 7 ], b: { c: [ 8 ] } }, + [ 5, 6, 7 ], 5, 6, 7, + { c: [ 8 ] }, [ 8 ], 8 + ] + ); + + assert.deepEqual( + Traverse.map(obj, function (node) { + if (typeof node == 'number') { + return node + 1000; + } + else if (Array.isArray(node)) { + return node.join(' '); + } + }), + { a: '5 6 7', b: { c: '8' } } + ); + + var nodes = 0; + Traverse.forEach(obj, function (node) { nodes ++ }); + assert.deepEqual(nodes, 8); +}; + diff --git a/node_modules/burrito/node_modules/traverse/test/json.js b/node_modules/burrito/node_modules/traverse/test/json.js new file mode 100644 index 0000000..0a04529 --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/test/json.js @@ -0,0 +1,47 @@ +var assert = require('assert'); +var Traverse = require('../'); + +exports['json test'] = function () { + var id = 54; + var callbacks = {}; + var obj = { moo : function () {}, foo : [2,3,4, function () {}] }; + + var scrubbed = Traverse(obj).map(function (x) { + if (typeof x === 'function') { + callbacks[id] = { id : id, f : x, path : this.path }; + this.update('[Function]'); + id++; + } + }); + + assert.equal( + scrubbed.moo, '[Function]', + 'obj.moo replaced with "[Function]"' + ); + + assert.equal( + scrubbed.foo[3], '[Function]', + 'obj.foo[3] replaced with "[Function]"' + ); + + assert.deepEqual(scrubbed, { + moo : '[Function]', + foo : [ 2, 3, 4, "[Function]" ] + }, 'Full JSON string matches'); + + assert.deepEqual( + typeof obj.moo, 'function', + 'Original obj.moo still a function' + ); + + assert.deepEqual( + typeof obj.foo[3], 'function', + 'Original obj.foo[3] still a function' + ); + + assert.deepEqual(callbacks, { + 54: { id: 54, f : obj.moo, path: [ 'moo' ] }, + 55: { id: 55, f : obj.foo[3], path: [ 'foo', '3' ] }, + }, 'Check the generated callbacks list'); +}; + diff --git a/node_modules/burrito/node_modules/traverse/test/keys.js b/node_modules/burrito/node_modules/traverse/test/keys.js new file mode 100644 index 0000000..7ecd545 --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/test/keys.js @@ -0,0 +1,29 @@ +var assert = require('assert'); +var Traverse = require('../'); + +exports['sort test'] = function () { + var acc = []; + Traverse({ + a: 30, + b: 22, + id: 9 + }).forEach(function (node) { + if ((! Array.isArray(node)) && typeof node === 'object') { + this.before(function(node) { + this.keys = Object.keys(node); + this.keys.sort(function(a, b) { + a = [a === "id" ? 0 : 1, a]; + b = [b === "id" ? 0 : 1, b]; + return a < b ? -1 : a > b ? 1 : 0; + }); + }); + } + if (this.isLeaf) acc.push(node); + }); + + assert.equal( + acc.join(' '), + '9 30 22', + 'Traversal in a custom order' + ); +}; diff --git a/node_modules/burrito/node_modules/traverse/test/leaves.js b/node_modules/burrito/node_modules/traverse/test/leaves.js new file mode 100644 index 0000000..e520b72 --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/test/leaves.js @@ -0,0 +1,21 @@ +var assert = require('assert'); +var Traverse = require('../'); + +exports['leaves test'] = function () { + var acc = []; + Traverse({ + a : [1,2,3], + b : 4, + c : [5,6], + d : { e : [7,8], f : 9 } + }).forEach(function (x) { + if (this.isLeaf) acc.push(x); + }); + + assert.equal( + acc.join(' '), + '1 2 3 4 5 6 7 8 9', + 'Traversal in the right(?) order' + ); +}; + diff --git a/node_modules/burrito/node_modules/traverse/test/lib/deep_equal.js b/node_modules/burrito/node_modules/traverse/test/lib/deep_equal.js new file mode 100644 index 0000000..4fa07bb --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/test/lib/deep_equal.js @@ -0,0 +1,92 @@ +var traverse = require('../../'); + +module.exports = function (a, b) { + if (arguments.length !== 2) { + throw new Error( + 'deepEqual requires exactly two objects to compare against' + ); + } + + var equal = true; + var node = b; + + traverse(a).forEach(function (y) { + var notEqual = (function () { + equal = false; + //this.stop(); + return undefined; + }).bind(this); + + //if (node === undefined || node === null) return notEqual(); + + if (!this.isRoot) { + /* + if (!Object.hasOwnProperty.call(node, this.key)) { + return notEqual(); + } + */ + if (typeof node !== 'object') return notEqual(); + node = node[this.key]; + } + + var x = node; + + this.post(function () { + node = x; + }); + + var toS = function (o) { + return Object.prototype.toString.call(o); + }; + + if (this.circular) { + if (traverse(b).get(this.circular.path) !== x) notEqual(); + } + else if (typeof x !== typeof y) { + notEqual(); + } + else if (x === null || y === null || x === undefined || y === undefined) { + if (x !== y) notEqual(); + } + else if (x.__proto__ !== y.__proto__) { + notEqual(); + } + else if (x === y) { + // nop + } + else if (typeof x === 'function') { + if (x instanceof RegExp) { + // both regexps on account of the __proto__ check + if (x.toString() != y.toString()) notEqual(); + } + else if (x !== y) notEqual(); + } + else if (typeof x === 'object') { + if (toS(y) === '[object Arguments]' + || toS(x) === '[object Arguments]') { + if (toS(x) !== toS(y)) { + notEqual(); + } + } + else if (x instanceof Date || y instanceof Date) { + if (!(x instanceof Date) || !(y instanceof Date) + || x.getTime() !== y.getTime()) { + notEqual(); + } + } + else { + var kx = Object.keys(x); + var ky = Object.keys(y); + if (kx.length !== ky.length) return notEqual(); + for (var i = 0; i < kx.length; i++) { + var k = kx[i]; + if (!Object.hasOwnProperty.call(y, k)) { + notEqual(); + } + } + } + } + }); + + return equal; +}; diff --git a/node_modules/burrito/node_modules/traverse/test/mutability.js b/node_modules/burrito/node_modules/traverse/test/mutability.js new file mode 100644 index 0000000..2236f56 --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/test/mutability.js @@ -0,0 +1,252 @@ +var assert = require('assert'); +var Traverse = require('../'); +var deepEqual = require('./lib/deep_equal'); + +exports.mutate = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).forEach(function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + assert.deepEqual(obj, res); + assert.deepEqual(obj, { a : 1, b : 20, c : [ 3, 40 ] }); +}; + +exports.mutateT = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse.forEach(obj, function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + assert.deepEqual(obj, res); + assert.deepEqual(obj, { a : 1, b : 20, c : [ 3, 40 ] }); +}; + +exports.map = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).map(function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + assert.deepEqual(obj, { a : 1, b : 2, c : [ 3, 4 ] }); + assert.deepEqual(res, { a : 1, b : 20, c : [ 3, 40 ] }); +}; + +exports.mapT = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse.map(obj, function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + assert.deepEqual(obj, { a : 1, b : 2, c : [ 3, 4 ] }); + assert.deepEqual(res, { a : 1, b : 20, c : [ 3, 40 ] }); +}; + +exports.clone = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).clone(); + assert.deepEqual(obj, res); + assert.ok(obj !== res); + obj.a ++; + assert.deepEqual(res.a, 1); + obj.c.push(5); + assert.deepEqual(res.c, [ 3, 4 ]); +}; + +exports.cloneT = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse.clone(obj); + assert.deepEqual(obj, res); + assert.ok(obj !== res); + obj.a ++; + assert.deepEqual(res.a, 1); + obj.c.push(5); + assert.deepEqual(res.c, [ 3, 4 ]); +}; + +exports.reduce = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).reduce(function (acc, x) { + if (this.isLeaf) acc.push(x); + return acc; + }, []); + assert.deepEqual(obj, { a : 1, b : 2, c : [ 3, 4 ] }); + assert.deepEqual(res, [ 1, 2, 3, 4 ]); +}; + +exports.reduceInit = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).reduce(function (acc, x) { + if (this.isRoot) assert.fail('got root'); + return acc; + }); + assert.deepEqual(obj, { a : 1, b : 2, c : [ 3, 4 ] }); + assert.deepEqual(res, obj); +}; + +exports.remove = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + Traverse(obj).forEach(function (x) { + if (this.isLeaf && x % 2 == 0) this.remove(); + }); + + assert.deepEqual(obj, { a : 1, c : [ 3 ] }); +}; + +exports.removeNoStop = function() { + var obj = { a : 1, b : 2, c : { d: 3, e: 4 }, f: 5 }; + + var keys = []; + Traverse(obj).forEach(function (x) { + keys.push(this.key) + if (this.key == 'c') this.remove(); + }); + + assert.deepEqual(keys, [undefined, 'a', 'b', 'c', 'd', 'e', 'f']) +} + +exports.removeStop = function() { + var obj = { a : 1, b : 2, c : { d: 3, e: 4 }, f: 5 }; + + var keys = []; + Traverse(obj).forEach(function (x) { + keys.push(this.key) + if (this.key == 'c') this.remove(true); + }); + + assert.deepEqual(keys, [undefined, 'a', 'b', 'c', 'f']) +} + +exports.removeMap = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).map(function (x) { + if (this.isLeaf && x % 2 == 0) this.remove(); + }); + + assert.deepEqual(obj, { a : 1, b : 2, c : [ 3, 4 ] }); + assert.deepEqual(res, { a : 1, c : [ 3 ] }); +}; + +exports.delete = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + Traverse(obj).forEach(function (x) { + if (this.isLeaf && x % 2 == 0) this.delete(); + }); + + assert.ok(!deepEqual( + obj, { a : 1, c : [ 3, undefined ] } + )); + + assert.ok(deepEqual( + obj, { a : 1, c : [ 3 ] } + )); + + assert.ok(!deepEqual( + obj, { a : 1, c : [ 3, null ] } + )); +}; + +exports.deleteNoStop = function() { + var obj = { a : 1, b : 2, c : { d: 3, e: 4 } }; + + var keys = []; + Traverse(obj).forEach(function (x) { + keys.push(this.key) + if (this.key == 'c') this.delete(); + }); + + assert.deepEqual(keys, [undefined, 'a', 'b', 'c', 'd', 'e']) +} + +exports.deleteStop = function() { + var obj = { a : 1, b : 2, c : { d: 3, e: 4 } }; + + var keys = []; + Traverse(obj).forEach(function (x) { + keys.push(this.key) + if (this.key == 'c') this.delete(true); + }); + + assert.deepEqual(keys, [undefined, 'a', 'b', 'c']) +} + +exports.deleteRedux = function () { + var obj = { a : 1, b : 2, c : [ 3, 4, 5 ] }; + Traverse(obj).forEach(function (x) { + if (this.isLeaf && x % 2 == 0) this.delete(); + }); + + assert.ok(!deepEqual( + obj, { a : 1, c : [ 3, undefined, 5 ] } + )); + + assert.ok(deepEqual( + obj, { a : 1, c : [ 3 ,, 5 ] } + )); + + assert.ok(!deepEqual( + obj, { a : 1, c : [ 3, null, 5 ] } + )); + + assert.ok(!deepEqual( + obj, { a : 1, c : [ 3, 5 ] } + )); +}; + +exports.deleteMap = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).map(function (x) { + if (this.isLeaf && x % 2 == 0) this.delete(); + }); + + assert.ok(deepEqual( + obj, + { a : 1, b : 2, c : [ 3, 4 ] } + )); + + var xs = [ 3, 4 ]; + delete xs[1]; + + assert.ok(deepEqual( + res, { a : 1, c : xs } + )); + + assert.ok(deepEqual( + res, { a : 1, c : [ 3, ] } + )); + + assert.ok(deepEqual( + res, { a : 1, c : [ 3 ] } + )); +}; + +exports.deleteMapRedux = function () { + var obj = { a : 1, b : 2, c : [ 3, 4, 5 ] }; + var res = Traverse(obj).map(function (x) { + if (this.isLeaf && x % 2 == 0) this.delete(); + }); + + assert.ok(deepEqual( + obj, + { a : 1, b : 2, c : [ 3, 4, 5 ] } + )); + + var xs = [ 3, 4, 5 ]; + delete xs[1]; + + assert.ok(deepEqual( + res, { a : 1, c : xs } + )); + + assert.ok(!deepEqual( + res, { a : 1, c : [ 3, 5 ] } + )); + + assert.ok(deepEqual( + res, { a : 1, c : [ 3 ,, 5 ] } + )); +}; diff --git a/node_modules/burrito/node_modules/traverse/test/negative.js b/node_modules/burrito/node_modules/traverse/test/negative.js new file mode 100644 index 0000000..f92dfb0 --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/test/negative.js @@ -0,0 +1,20 @@ +var Traverse = require('../'); +var assert = require('assert'); + +exports['negative update test'] = function () { + var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + var fixed = Traverse.map(obj, function (x) { + if (x < 0) this.update(x + 128); + }); + + assert.deepEqual(fixed, + [ 5, 6, 125, [ 7, 8, 126, 1 ], { f: 10, g: 115 } ], + 'Negative values += 128' + ); + + assert.deepEqual(obj, + [ 5, 6, -3, [ 7, 8, -2, 1 ], { f: 10, g: -13 } ], + 'Original references not modified' + ); +} + diff --git a/node_modules/burrito/node_modules/traverse/test/obj.js b/node_modules/burrito/node_modules/traverse/test/obj.js new file mode 100644 index 0000000..d46fd38 --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/test/obj.js @@ -0,0 +1,15 @@ +var assert = require('assert'); +var Traverse = require('../'); + +exports['traverse an object with nested functions'] = function () { + var to = setTimeout(function () { + assert.fail('never ran'); + }, 1000); + + function Cons (x) { + clearTimeout(to); + assert.equal(x, 10); + }; + Traverse(new Cons(10)); +}; + diff --git a/node_modules/burrito/node_modules/traverse/test/siblings.js b/node_modules/burrito/node_modules/traverse/test/siblings.js new file mode 100644 index 0000000..99c0f1b --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/test/siblings.js @@ -0,0 +1,35 @@ +var assert = require('assert'); +var traverse = require('../'); + +exports.siblings = function () { + var obj = { a : 1, b : 2, c : [ 4, 5, 6 ] }; + + var res = traverse(obj).reduce(function (acc, x) { + var p = '/' + this.path.join('/'); + if (this.parent) { + acc[p] = { + siblings : this.parent.keys, + key : this.key, + index : this.parent.keys.indexOf(this.key) + }; + } + else { + acc[p] = { + siblings : [], + key : this.key, + index : -1 + } + } + return acc; + }, {}); + + assert.deepEqual(res, { + '/' : { siblings : [], key : undefined, index : -1 }, + '/a' : { siblings : [ 'a', 'b', 'c' ], key : 'a', index : 0 }, + '/b' : { siblings : [ 'a', 'b', 'c' ], key : 'b', index : 1 }, + '/c' : { siblings : [ 'a', 'b', 'c' ], key : 'c', index : 2 }, + '/c/0' : { siblings : [ '0', '1', '2' ], key : '0', index : 0 }, + '/c/1' : { siblings : [ '0', '1', '2' ], key : '1', index : 1 }, + '/c/2' : { siblings : [ '0', '1', '2' ], key : '2', index : 2 } + }); +}; diff --git a/node_modules/burrito/node_modules/traverse/test/stop.js b/node_modules/burrito/node_modules/traverse/test/stop.js new file mode 100644 index 0000000..3529847 --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/test/stop.js @@ -0,0 +1,41 @@ +var assert = require('assert'); +var traverse = require('../'); + +exports.stop = function () { + var visits = 0; + traverse('abcdefghij'.split('')).forEach(function (node) { + if (typeof node === 'string') { + visits ++; + if (node === 'e') this.stop() + } + }); + + assert.equal(visits, 5); +}; + +exports.stopMap = function () { + var s = traverse('abcdefghij'.split('')).map(function (node) { + if (typeof node === 'string') { + if (node === 'e') this.stop() + return node.toUpperCase(); + } + }).join(''); + + assert.equal(s, 'ABCDEfghij'); +}; + +exports.stopReduce = function () { + var obj = { + a : [ 4, 5 ], + b : [ 6, [ 7, 8, 9 ] ] + }; + var xs = traverse(obj).reduce(function (acc, node) { + if (this.isLeaf) { + if (node === 7) this.stop(); + else acc.push(node) + } + return acc; + }, []); + + assert.deepEqual(xs, [ 4, 5, 6 ]); +}; diff --git a/node_modules/burrito/node_modules/traverse/test/stringify.js b/node_modules/burrito/node_modules/traverse/test/stringify.js new file mode 100644 index 0000000..932f5d3 --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/test/stringify.js @@ -0,0 +1,36 @@ +var assert = require('assert'); +var Traverse = require('../'); + +exports.stringify = function () { + var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + + var s = ''; + Traverse(obj).forEach(function (node) { + if (Array.isArray(node)) { + this.before(function () { s += '[' }); + this.post(function (child) { + if (!child.isLast) s += ','; + }); + this.after(function () { s += ']' }); + } + else if (typeof node == 'object') { + this.before(function () { s += '{' }); + this.pre(function (x, key) { + s += '"' + key + '"' + ':'; + }); + this.post(function (child) { + if (!child.isLast) s += ','; + }); + this.after(function () { s += '}' }); + } + else if (typeof node == 'function') { + s += 'null'; + } + else { + s += node.toString(); + } + }); + + assert.equal(s, JSON.stringify(obj)); +} + diff --git a/node_modules/burrito/node_modules/traverse/test/subexpr.js b/node_modules/burrito/node_modules/traverse/test/subexpr.js new file mode 100644 index 0000000..a217beb --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/test/subexpr.js @@ -0,0 +1,34 @@ +var traverse = require('../'); +var assert = require('assert'); + +exports.subexpr = function () { + var obj = [ 'a', 4, 'b', 5, 'c', 6 ]; + var r = traverse(obj).map(function (x) { + if (typeof x === 'number') { + this.update([ x - 0.1, x, x + 0.1 ], true); + } + }); + + assert.deepEqual(obj, [ 'a', 4, 'b', 5, 'c', 6 ]); + assert.deepEqual(r, [ + 'a', [ 3.9, 4, 4.1 ], + 'b', [ 4.9, 5, 5.1 ], + 'c', [ 5.9, 6, 6.1 ], + ]); +}; + +exports.block = function () { + var obj = [ [ 1 ], [ 2 ], [ 3 ] ]; + var r = traverse(obj).map(function (x) { + if (Array.isArray(x) && !this.isRoot) { + if (x[0] === 5) this.block() + else this.update([ [ x[0] + 1 ] ]) + } + }); + + assert.deepEqual(r, [ + [ [ [ [ [ 5 ] ] ] ] ], + [ [ [ [ 5 ] ] ] ], + [ [ [ 5 ] ] ], + ]); +}; diff --git a/node_modules/burrito/node_modules/traverse/test/super_deep.js b/node_modules/burrito/node_modules/traverse/test/super_deep.js new file mode 100644 index 0000000..acac2fd --- /dev/null +++ b/node_modules/burrito/node_modules/traverse/test/super_deep.js @@ -0,0 +1,55 @@ +var assert = require('assert'); +var traverse = require('../'); +var deepEqual = require('./lib/deep_equal'); + +exports.super_deep = function () { + var util = require('util'); + var a0 = make(); + var a1 = make(); + assert.ok(deepEqual(a0, a1)); + + a0.c.d.moo = true; + assert.ok(!deepEqual(a0, a1)); + + a1.c.d.moo = true; + assert.ok(deepEqual(a0, a1)); + + // TODO: this one + //a0.c.a = a1; + //assert.ok(!deepEqual(a0, a1)); +}; + +function make () { + var a = { self : 'a' }; + var b = { self : 'b' }; + var c = { self : 'c' }; + var d = { self : 'd' }; + var e = { self : 'e' }; + + a.a = a; + a.b = b; + a.c = c; + + b.a = a; + b.b = b; + b.c = c; + + c.a = a; + c.b = b; + c.c = c; + c.d = d; + + d.a = a; + d.b = b; + d.c = c; + d.d = d; + d.e = e; + + e.a = a; + e.b = b; + e.c = c; + e.d = d; + e.e = e; + + return a; +} diff --git a/node_modules/burrito/package.json b/node_modules/burrito/package.json new file mode 100644 index 0000000..bd27547 --- /dev/null +++ b/node_modules/burrito/package.json @@ -0,0 +1,43 @@ +{ + "name" : "burrito", + "description" : "Wrap up expressions with a trace function while walking the AST with rice and beans on the side", + "version" : "0.2.12", + "repository" : { + "type" : "git", + "url" : "git://github.com/substack/node-burrito.git" + }, + "main" : "./index.js", + "keywords" : [ + "trace", + "ast", + "walk", + "syntax", + "source", + "tree", + "uglify" + ], + "directories" : { + "lib" : ".", + "example" : "example", + "test" : "test" + }, + "scripts" : { + "test" : "tap test/*.js" + }, + "dependencies" : { + "traverse" : "~0.5.1", + "uglify-js" : "~1.1.1" + }, + "devDependencies" : { + "tap" : "~0.2.5" + }, + "engines" : { + "node" : ">=0.4.0" + }, + "license" : "BSD", + "author" : { + "name" : "James Halliday", + "email" : "mail@substack.net", + "url" : "http://substack.net" + } +} diff --git a/node_modules/burrito/test/ast.js b/node_modules/burrito/test/ast.js new file mode 100644 index 0000000..503b5ab --- /dev/null +++ b/node_modules/burrito/test/ast.js @@ -0,0 +1,31 @@ +var test = require('tap').test; +var burrito = require('../'); +var vm = require('vm'); + +test('ast', function (t) { + t.plan(2); + + var ast = burrito.parse('f(g(h(5)))', false, true); + var src = burrito(ast, function (node) { + if (node.name === 'call') { + node.wrap(function (s) { + return 'z(' + s + ')'; + }); + } + }); + + var times = 0; + t.equal( + vm.runInNewContext(src, { + f : function (x) { return x + 1 }, + g : function (x) { return x + 2 }, + h : function (x) { return x + 3 }, + z : function (x) { + times ++; + return x * 10; + }, + }), + (((((5 + 3) * 10) + 2) * 10) + 1) * 10 + ); + t.equal(times, 3); +}); diff --git a/node_modules/burrito/test/err.js b/node_modules/burrito/test/err.js new file mode 100644 index 0000000..af1611d --- /dev/null +++ b/node_modules/burrito/test/err.js @@ -0,0 +1,52 @@ +var test = require('tap').test; +var burrito = require('../'); + +test('wrap error', function (t) { + t.plan(6); + + try { + var src = burrito('f() && g()', function (node) { + if (node.name === 'binary') node.wrap('h(%a, %b') + }); + t.fail('should have blown up'); + } + catch (err) { + t.ok(err.message.match(/unexpected/i)); + t.ok(err instanceof SyntaxError); + t.ok(!err.stack.match(/uglify-js/)); + t.equal(err.line, 0); + t.equal(err.col, 10); + t.equal(err.pos, 10); + } +}); + +test('non string', function (t) { + t.plan(3); + + t.throws(function () { + burrito.parse(new Buffer('[]')); + }); + + t.throws(function () { + burrito.parse(new String('[]')); + }); + + t.throws(function () { + burrito.parse(); + }); +}); + +test('syntax error', function (t) { + t.plan(3); + try { + var src = burrito('f() && g())', function (node) { + if (node.name === 'binary') node.wrap('h(%a, %b)') + }); + assert.fail('should have blown up'); + } + catch (err) { + t.ok(err.message.match(/unexpected/i)); + t.ok(err instanceof SyntaxError); + t.ok(!err.stack.match(/uglify-js/)); + } +}); diff --git a/node_modules/burrito/test/fail.js b/node_modules/burrito/test/fail.js new file mode 100644 index 0000000..70d453f --- /dev/null +++ b/node_modules/burrito/test/fail.js @@ -0,0 +1,9 @@ +var burrito = require('../'); +var test = require('tap').test; +var fs = require('fs'); +var src = fs.readFileSync(__dirname + '/fail/src.js', 'utf8'); + +test('fail', function (t) { + burrito(src, function (node) {}); + t.end(); +}); diff --git a/node_modules/burrito/test/fail/src.js b/node_modules/burrito/test/fail/src.js new file mode 100644 index 0000000..eb02736 --- /dev/null +++ b/node_modules/burrito/test/fail/src.js @@ -0,0 +1,60 @@ +var path = require('path') + +module.exports = function(fs, ready) { + var global_files = {} + + var recurse = function(dir, okay) { + fs.readdir(dir, function(err, dir_files) { + var countdown = 0 + , files = [] + , dirs = [] + , checked = 0 + dir_files.forEach(function(file, idx, all) { + fs.stat(path.join(dir, file), function(err, stat) { + if(stat.isDirectory() && !/node_modules/g.test(dir)) { + dirs.push(file) + } else if(/\.js$/g.test(file)) { + files.push(file) + } + + if(++checked >= dir_files.length) + recurse_dirs() + }) + }) + + function recurse_dirs() { + var total = 0 + dirs.forEach(function(this_dir) { + recurse(path.join(dir, this_dir), function(err, data) { + if(++total >= dirs.length) + recurse_files() + }) + }) + + if(!dirs.length) + recurse_files() + } + + function recurse_files() { + var total = 0 + files.forEach(function(file) { + fs.readFile(path.join(dir, file), 'utf8', function(err, src) { + global_files[path.join(dir, file)] = src + ++total >= files.length && + okay(null, global_files) + }) + }) + + if(!files.length) + okay(null, global_files) + } + + if(!dir_files.length) + okay(null, global_files) + }) + } + + recurse('.', ready) +} + + diff --git a/node_modules/burrito/test/label.js b/node_modules/burrito/test/label.js new file mode 100644 index 0000000..368d7c4 --- /dev/null +++ b/node_modules/burrito/test/label.js @@ -0,0 +1,92 @@ +var test = require('tap').test; +var burrito = require('../'); + +test('call label', function (t) { + t.plan(1); + + burrito('foo(10)', function (node) { + if (node.name === 'call') { + t.equal(node.label(), 'foo'); + } + }); +}); + +test('var label', function (t) { + t.plan(1); + + burrito('var x = 2', function (node) { + if (node.name === 'var') { + t.same(node.label(), [ 'x' ]); + } + }); +}); + +test('vars label', function (t) { + t.plan(1); + + burrito('var x = 2, y = 3', function (node) { + if (node.name === 'var') { + t.same(node.label(), [ 'x', 'y' ]); + } + }); +}); + +test('defun label', function (t) { + t.plan(1); + + burrito('function moo () {}', function (node) { + if (node.name === 'defun') { + t.same(node.label(), 'moo'); + } + }); +}); + +test('function label', function (t) { + t.plan(1); + + burrito('(function zzz () {})()', function (node) { + if (node.name === 'function') { + t.same(node.label(), 'zzz'); + } + }); +}); + +test('anon function label', function (t) { + t.plan(1); + + burrito('(function () {})()', function (node) { + if (node.name === 'function') { + t.equal(node.label(), null); + } + }); +}); + +test('dot call label', function (t) { + t.plan(1); + + burrito('process.nextTick(fn)', function (node) { + if (node.name === 'call') { + t.equal(node.label(), 'nextTick'); + } + }); +}); + +test('triple dot label', function (t) { + t.plan(1); + + burrito('a.b.c(fn)', function (node) { + if (node.name === 'call') { + t.equal(node.label(), 'c'); + } + }); +}); + +test('expr label', function (t) { + t.plan(1); + + burrito('a.b[x+1](fn)', function (node) { + if (node.name === 'call') { + t.ok(node.label() === null); + } + }); +}); diff --git a/node_modules/burrito/test/microwave.js b/node_modules/burrito/test/microwave.js new file mode 100644 index 0000000..43f80a7 --- /dev/null +++ b/node_modules/burrito/test/microwave.js @@ -0,0 +1,34 @@ +var test = require('tap').test; +var burrito = require('../'); + +test('microwave', function (t) { + t.plan(4); + + var context = { + f : function (x) { return x + 1 }, + g : function (x) { return x + 2 }, + h : function (x) { return x + 3 }, + z : function (x) { + t.ok(true); // 3 times + return x * 10; + }, + }; + + var res = burrito.microwave('f(g(h(5)))', context, function (node) { + if (node.name === 'call') { + node.wrap(function (s) { + return 'z(' + s + ')'; + }); + } + }); + + t.equal(res, (((((5 + 3) * 10) + 2) * 10) + 1) * 10); +}); + +test('empty context', function (t) { + var res = burrito.microwave('Math.sin(2)', function (node) { + if (node.name === 'num') node.wrap('Math.PI / %s'); + }); + t.equal(res, 1); + t.end(); +}); diff --git a/node_modules/burrito/test/parent.js b/node_modules/burrito/test/parent.js new file mode 100644 index 0000000..2d613af --- /dev/null +++ b/node_modules/burrito/test/parent.js @@ -0,0 +1,27 @@ +var test = require('tap').test; +var burrito = require('../'); + +test('check parent', function (t) { + t.plan(5); + var src = 'Math.tan(0) + Math.sin(0)'; + + var res = burrito.microwave(src, function (node) { + if (node.name === 'binary') { + node.wrap('%a - %b'); + } + else if (node.name === 'num') { + t.equal(node.parent().value[0][0], 'dot'); + + var fn = node.parent().value[0][2]; + if (fn === 'sin') { + node.wrap('Math.PI / 2'); + } + else if (fn === 'tan') { + node.wrap('Math.PI / 4'); + } + else t.fail('Unknown fn'); + } + }); + + t.equal(res, Math.tan(Math.PI / 4) - Math.sin(Math.PI / 2)); // ~ 0 +}); diff --git a/node_modules/burrito/test/wrap.js b/node_modules/burrito/test/wrap.js new file mode 100644 index 0000000..b9eda49 --- /dev/null +++ b/node_modules/burrito/test/wrap.js @@ -0,0 +1,159 @@ +var test = require('tap').test; +var burrito = require('../'); +var vm = require('vm'); + +test('preserve ternary parentheses', function (t) { + var originalSource = '"anything" + (x ? y : z) + "anything"'; + var burritoSource = burrito(originalSource, function (node) { + // do nothing. we just want to check that ternary parens are persisted + }); + + var ctxt = { + x : false, + y : 'y_'+~~(Math.random()*10), + z : 'z_'+~~(Math.random()*10) + }; + + var expectedOutput = vm.runInNewContext(originalSource, ctxt); + var burritoOutput = vm.runInNewContext(burritoSource, ctxt); + + t.equal(burritoOutput, expectedOutput); + + ctxt.x = true; + + expectedOutput = vm.runInNewContext(originalSource, ctxt); + burritoOutput = vm.runInNewContext(burritoSource, ctxt); + + t.equal(burritoOutput, expectedOutput); + t.end(); +}); + +test('wrap calls', function (t) { + t.plan(20); + var src = burrito('f() && g(h())\nfoo()', function (node) { + if (node.name === 'call') node.wrap('qqq(%s)'); + if (node.name === 'binary') node.wrap('bbb(%s)'); + t.ok(node.state); + t.equal(this, node.state); + }); + + var times = { bbb : 0, qqq : 0 }; + + var res = []; + vm.runInNewContext(src, { + bbb : function (x) { + times.bbb ++; + res.push(x); + return x; + }, + qqq : function (x) { + times.qqq ++; + res.push(x); + return x; + }, + f : function () { return true }, + g : function (h) { + t.equal(h, 7); + return h !== 7 + }, + h : function () { return 7 }, + foo : function () { return 'foo!' }, + }); + + t.same(res, [ + true, // f() + 7, // h() + false, // g(h()) + false, // f() && g(h()) + 'foo!', // foo() + ]); + t.equal(times.bbb, 1); + t.equal(times.qqq, 4); + t.end(); +}); + +test('wrap fn', function (t) { + var src = burrito('f(g(h(5)))', function (node) { + if (node.name === 'call') { + node.wrap(function (s) { + return 'z(' + s + ')'; + }); + } + }); + + var times = 0; + t.equal( + vm.runInNewContext(src, { + f : function (x) { return x + 1 }, + g : function (x) { return x + 2 }, + h : function (x) { return x + 3 }, + z : function (x) { + times ++; + return x * 10; + }, + }), + (((((5 + 3) * 10) + 2) * 10) + 1) * 10 + ); + t.equal(times, 3); + t.end(); +}); + +test('binary string', function (t) { + var src = 'z(x + y)'; + var context = { + x : 3, + y : 4, + z : function (n) { return n * 10 }, + }; + + var res = burrito.microwave(src, context, function (node) { + if (node.name === 'binary') { + node.wrap('%a*2 - %b*2'); + } + }); + + t.equal(res, 10 * (3*2 - 4*2)); + t.end(); +}); + +test('binary fn', function (t) { + var src = 'z(x + y)'; + var context = { + x : 3, + y : 4, + z : function (n) { return n * 10 }, + }; + + var res = burrito.microwave(src, context, function (node) { + if (node.name === 'binary') { + node.wrap(function (expr, a, b) { + return '(' + a + ')*2 - ' + '(' + b + ')*2'; + }); + } + }); + + t.equal(res, 10 * (3*2 - 4*2)); + t.end(); +}); + +test('intersperse', function (t) { + var src = '(' + (function () { + f(); + g(); + }).toString() + ')()'; + + var times = { f : 0, g : 0, zzz : 0 }; + + var context = { + f : function () { times.f ++ }, + g : function () { times.g ++ }, + zzz : function () { times.zzz ++ }, + }; + + burrito.microwave(src, context, function (node) { + if (node.name === 'stat') node.wrap('{ zzz(); %s }'); + }); + + t.same(times, { f : 1, g : 1, zzz : 3 }); + t.end(); +}); diff --git a/node_modules/charm/README.markdown b/node_modules/charm/README.markdown new file mode 100644 index 0000000..a0648ff --- /dev/null +++ b/node_modules/charm/README.markdown @@ -0,0 +1,216 @@ +charm +===== + +Use +[ansi terminal characters](http://www.termsys.demon.co.uk/vtansi.htm) +to write colors and cursor positions. + +![me lucky charms](http://substack.net/images/charms.png) + +example +======= + +lucky +----- + +````javascript +var charm = require('charm')(); +charm.pipe(process.stdout); +charm.reset(); + +var colors = [ 'red', 'cyan', 'yellow', 'green', 'blue' ]; +var text = 'Always after me lucky charms.'; + +var offset = 0; +var iv = setInterval(function () { + var y = 0, dy = 1; + for (var i = 0; i < 40; i++) { + var color = colors[(i + offset) % colors.length]; + var c = text[(i + offset) % text.length]; + charm + .move(1, dy) + .foreground(color) + .write(c) + ; + y += dy; + if (y <= 0 || y >= 5) dy *= -1; + } + charm.position(0, 1); + offset ++; +}, 150); +```` + +events +====== + +Charm objects pass along the data events from their input stream except for +events generated from querying the terminal device. + +Because charm puts stdin into raw mode, charm emits two special events: "^C" and +"^D" when the user types those combos. It's super convenient with these events +to do: + +````javascript +charm.on('^C', process.exit) +```` + +The above is set on all `charm` streams. If you want to add your own handling for these +special events simply: + +````javascript +charm.removeAllListeners('^C') +charm.on('^C', function () { + // Don't exit. Do some mad science instead. +}) +```` + +methods +======= + +var charm = require('charm')(param or stream, ...) +-------------------------------------------------- + +Create a new readable/writable `charm` stream. + +You can pass in readable or writable streams as parameters and they will be +piped to or from accordingly. You can also pass `process` in which case +`process.stdin` and `process.stdout` will be used. + +You can `pipe()` to and from the `charm` object you get back. + +charm.reset() +------------- + +Reset the entire screen, like the /usr/bin/reset command. + +charm.destroy(), charm.end() +---------------------------- + +Emit an `"end"` event downstream. + +charm.write(msg) +---------------- + +Pass along `msg` to the output stream. + +charm.position(x, y) +-------------------- + +Set the cursor position to the absolute coordinates `x, y`. + +charm.position(cb) +------------------ + +Query the absolute cursor position from the input stream through the output +stream (the shell does this automatically) and get the response back as +`cb(x, y)`. + +charm.move(x, y) +---------------- + +Move the cursor position by the relative coordinates `x, y`. + +charm.up(y) +----------- + +Move the cursor up by `y` rows. + +charm.down(y) +------------- + +Move the cursor down by `y` rows. + +charm.left(x) +------------- + +Move the cursor left by `x` columns. + +charm.right(x) +-------------- + +Move the cursor right by `x` columns. + +charm.push(withAttributes=false) +-------------------------------- + +Push the cursor state and optionally the attribute state. + +charm.pop(withAttributes=false) +------------------------------- + +Pop the cursor state and optionally the attribute state. + +charm.erase(s) +-------------- + +Erase a region defined by the string `s`. + +`s` can be: + +* end - erase from the cursor to the end of the line +* start - erase from the cursor to the start of the line +* line - erase the current line +* down - erase everything below the current line +* up - erase everything above the current line +* screen - erase the entire screen + +charm.display(attr) +------------------- + +Set the display mode with the string `attr`. + +`attr` can be: + +* reset +* bright +* dim +* underscore +* blink +* reverse +* hidden + +charm.foreground(color) +----------------------- + +Set the foreground color with the string `color`, which can be: + +* red +* yellow +* green +* blue +* cyan +* magenta +* black +* white + +or `color` can be an integer from 0 to 255, inclusive. + +charm.background(color) +----------------------- + +Set the background color with the string `color`, which can be: + +* red +* yellow +* green +* blue +* cyan +* magenta +* black +* white + +or `color` can be an integer from 0 to 255, inclusive. + +charm.cursor(visible) +--------------------- + +Set the cursor visibility with a boolean `visible`. + +install +======= + +With [npm](http://npmjs.org) do: + +``` +npm install charm +``` diff --git a/node_modules/charm/example/256.js b/node_modules/charm/example/256.js new file mode 100644 index 0000000..6851386 --- /dev/null +++ b/node_modules/charm/example/256.js @@ -0,0 +1,17 @@ +var charm = require('../')(process); + +function exit () { + charm.display('reset'); + process.exit(); +} +charm.on('^C', exit); + +var ix = 0; +var iv = setInterval(function () { + charm.background(ix++).write(' '); + if (ix === 256) { + clearInterval(iv); + charm.write('\n'); + exit(); + } +}, 10); diff --git a/node_modules/charm/example/column.js b/node_modules/charm/example/column.js new file mode 100644 index 0000000..2647e71 --- /dev/null +++ b/node_modules/charm/example/column.js @@ -0,0 +1,11 @@ +var charm = require('../')(); +charm.pipe(process.stdout); + +charm + .column(16) + .write('beep') + .down() + .column(32) + .write('boop\n') + .end() +; diff --git a/node_modules/charm/example/cursor.js b/node_modules/charm/example/cursor.js new file mode 100644 index 0000000..0c565b0 --- /dev/null +++ b/node_modules/charm/example/cursor.js @@ -0,0 +1,22 @@ +var charm = require('../')(process); + +charm.position(5, 10); + +charm.position(function (x, y) { + console.dir([ x, y ]); + + charm.move(7,2); + charm.push(); + process.stdout.write('lul'); + + charm.left(3).up(1).foreground('magenta'); + process.stdout.write('v'); + charm.left(1).up(1).display('reset'); + process.stdout.write('|'); + + charm.down(3); + charm.pop().background('blue'); + process.stdout.write('popped\npow'); + charm.display('reset').erase('line'); + charm.destroy(); +}); diff --git a/node_modules/charm/example/http_spin.js b/node_modules/charm/example/http_spin.js new file mode 100644 index 0000000..727e3e8 --- /dev/null +++ b/node_modules/charm/example/http_spin.js @@ -0,0 +1,36 @@ +var http = require('http'); +var charmer = require('../'); + +http.createServer(function (req, res) { + res.setHeader('content-type', 'text/ansi'); + + var charm = charmer(); + charm.pipe(res); + charm.reset(); + + var radius = 10; + var theta = 0; + var points = []; + + var iv = setInterval(function () { + var x = 2 + (radius + Math.cos(theta) * radius) * 2; + var y = 2 + radius + Math.sin(theta) * radius; + + points.unshift([ x, y ]); + var colors = [ 'red', 'yellow', 'green', 'cyan', 'blue', 'magenta' ]; + + points.forEach(function (p, i) { + charm.position(p[0], p[1]); + var c = colors[Math.floor(i / 12)]; + charm.background(c).write(' ') + }); + points = points.slice(0, 12 * colors.length - 1); + + theta += Math.PI / 40; + }, 50); + + req.connection.on('end', function () { + clearInterval(iv); + charm.end(); + }); +}).listen(8081); diff --git a/node_modules/charm/example/lucky.js b/node_modules/charm/example/lucky.js new file mode 100644 index 0000000..01fe801 --- /dev/null +++ b/node_modules/charm/example/lucky.js @@ -0,0 +1,24 @@ +var charm = require('../')(); +charm.pipe(process.stdout); +charm.reset(); + +var colors = [ 'red', 'cyan', 'yellow', 'green', 'blue' ]; +var text = 'Always after me lucky charms.'; + +var offset = 0; +var iv = setInterval(function () { + var y = 0, dy = 1; + for (var i = 0; i < 40; i++) { + var color = colors[(i + offset) % colors.length]; + var c = text[(i + offset) % text.length]; + charm + .move(1, dy) + .foreground(color) + .write(c) + ; + y += dy; + if (y <= 0 || y >= 5) dy *= -1; + } + charm.position(0, 1); + offset ++; +}, 150); diff --git a/node_modules/charm/example/position.js b/node_modules/charm/example/position.js new file mode 100644 index 0000000..2c5ae9b --- /dev/null +++ b/node_modules/charm/example/position.js @@ -0,0 +1,7 @@ +var charm = require('charm')(process); + +charm.on('^C', process.exit); + +charm.position(function (x, y) { + console.log('(%d, %d)', x, y); +}); diff --git a/node_modules/charm/example/progress.js b/node_modules/charm/example/progress.js new file mode 100644 index 0000000..9da3c13 --- /dev/null +++ b/node_modules/charm/example/progress.js @@ -0,0 +1,18 @@ +var charm = require('../')(); +charm.pipe(process.stdout); + +charm.write('Progress: 0 %'); +var i = 0; + +var iv = setInterval(function () { + charm.left(i.toString().length + 2); + i ++; + charm.write(i + ' %'); + if (i === 100) { + charm.end('\nDone!\n'); + clearInterval(iv); + } +}, 25); + +charm.on('^C',process.exit); + diff --git a/node_modules/charm/example/resize.js b/node_modules/charm/example/resize.js new file mode 100644 index 0000000..bda80b6 --- /dev/null +++ b/node_modules/charm/example/resize.js @@ -0,0 +1,62 @@ +var c = require('../')(); +c.pipe(process.stdout); +c.on('^C', process.exit); + +var queue = (function () { + var tasks = []; + var pending = false; + + return { + abort : function () { + tasks = []; + next(); + }, + push : function (t) { + tasks.push(t); + if (!pending) next(); + } + }; + + function next () { + pending = true; + process.nextTick(function () { + if (tasks.length === 0) return; + var t = tasks.shift(); + t(); + pending = false; + next(); + }); + } +})(); + +process.stdout.on('resize', draw); +draw(); +setInterval(function () {}, 1e8); + +function draw () { + var cols = process.stdout.columns; + var rows = process.stdout.rows; + queue.abort(); + + queue.push(function () { + c.reset(); + c.background('blue'); + c.position(1, 1); + c.write(Array(cols + 1).join(' ')); + }); + + for (var y = 1; y < rows; y++) { + queue.push(function () { + c.position(1, y); + c.write(' '); + c.position(cols, y); + c.write(' '); + }); + } + + queue.push(function () { + c.position(1, rows); + c.write(Array(cols + 1).join(' ')); + c.display('reset'); + }); +} diff --git a/node_modules/charm/example/spin.js b/node_modules/charm/example/spin.js new file mode 100644 index 0000000..fd3e23a --- /dev/null +++ b/node_modules/charm/example/spin.js @@ -0,0 +1,23 @@ +var charm = require('../')(process); +charm.reset(); + +var radius = 10; +var theta = 0; +var points = []; + +var iv = setInterval(function () { + var x = 2 + (radius + Math.cos(theta) * radius) * 2; + var y = 2 + radius + Math.sin(theta) * radius; + + points.unshift([ x, y ]); + var colors = [ 'red', 'yellow', 'green', 'cyan', 'blue', 'magenta' ]; + + points.forEach(function (p, i) { + charm.position(p[0], p[1]); + var c = colors[Math.floor(i / 12)]; + charm.background(c).write(' ') + }); + points = points.slice(0, 12 * colors.length - 1); + + theta += Math.PI / 40; +}, 50); diff --git a/node_modules/charm/index.js b/node_modules/charm/index.js new file mode 100644 index 0000000..e1e7bdc --- /dev/null +++ b/node_modules/charm/index.js @@ -0,0 +1,305 @@ +var tty = require('tty'); +var encode = require('./lib/encode'); +var Stream = require('stream').Stream; + +var exports = module.exports = function () { + var input = null; + function setInput (s) { + if (input) throw new Error('multiple inputs specified') + else input = s + } + + var output = null; + function setOutput (s) { + if (output) throw new Error('multiple outputs specified') + else output = s + } + + for (var i = 0; i < arguments.length; i++) { + var arg = arguments[i]; + if (!arg) continue; + if (arg.readable) setInput(arg) + else if (arg.stdin || arg.input) setInput(arg.stdin || arg.input) + + if (arg.writable) setOutput(arg) + else if (arg.stdout || arg.output) setOutput(arg.stdout || arg.output) + + } + + if (input && typeof input.fd === 'number' && tty.isatty(input.fd)) { + if (process.stdin.setRawMode) { + process.stdin.setRawMode(true); + } + else tty.setRawMode(true); + } + + var charm = new Charm; + if (input) { + input.pipe(charm); + } + + if (output) { + charm.pipe(output); + } + + charm.once('^C', process.exit); + charm.once('end', function () { + if (input) { + if (typeof input.fd === 'number' && tty.isatty(input.fd)) { + if (process.stdin.setRawMode) { + process.stdin.setRawMode(false); + } + else tty.setRawMode(false); + } + input.destroy(); + } + }); + + return charm; +}; + +var Charm = exports.Charm = function Charm () { + this.writable = true; + this.readable = true; + this.pending = []; +} + +Charm.prototype = new Stream; + +Charm.prototype.write = function (buf) { + var self = this; + + if (self.pending.length) { + var codes = extractCodes(buf); + var matched = false; + + for (var i = 0; i < codes.length; i++) { + for (var j = 0; j < self.pending.length; j++) { + var cb = self.pending[j]; + if (cb(codes[i])) { + matched = true; + self.pending.splice(j, 1); + break; + } + } + } + + if (matched) return; + } + + if (buf.length === 1) { + if (buf[0] === 3) self.emit('^C'); + if (buf[0] === 4) self.emit('^D'); + } + + self.emit('data', buf); + + return self; +}; + + +Charm.prototype.destroy = function () { + this.end(); +}; + +Charm.prototype.end = function (buf) { + if (buf) this.write(buf); + this.emit('end'); +}; + +Charm.prototype.reset = function (cb) { + this.write(encode('c')); + return this; +}; + +Charm.prototype.position = function (x, y) { + // get/set absolute coordinates + if (typeof x === 'function') { + var cb = x; + this.pending.push(function (buf) { + if (buf[0] === 27 && buf[1] === encode.ord('[') + && buf[buf.length-1] === encode.ord('R')) { + var pos = buf.toString() + .slice(2,-1) + .split(';') + .map(Number) + ; + cb(pos[1], pos[0]); + return true; + } + }); + this.write(encode('[6n')); + } + else { + this.write(encode( + '[' + Math.floor(y) + ';' + Math.floor(x) + 'f' + )); + } + return this; +}; + +Charm.prototype.move = function (x, y) { + // set relative coordinates + var bufs = []; + + if (y < 0) this.up(-y) + else if (y > 0) this.down(y) + + if (x > 0) this.right(x) + else if (x < 0) this.left(-x) + + return this; +}; + +Charm.prototype.up = function (y) { + if (y === undefined) y = 1; + this.write(encode('[' + Math.floor(y) + 'A')); + return this; +}; + +Charm.prototype.down = function (y) { + if (y === undefined) y = 1; + this.write(encode('[' + Math.floor(y) + 'B')); + return this; +}; + +Charm.prototype.right = function (x) { + if (x === undefined) x = 1; + this.write(encode('[' + Math.floor(x) + 'C')); + return this; +}; + +Charm.prototype.left = function (x) { + if (x === undefined) x = 1; + this.write(encode('[' + Math.floor(x) + 'D')); + return this; +}; + +Charm.prototype.column = function (x) { + this.write(encode('[' + Math.floor(x) + 'G')); + return this; +}; + +Charm.prototype.push = function (withAttributes) { + this.write(encode(withAttributes ? '7' : '[s')); + return this; +}; + +Charm.prototype.pop = function (withAttributes) { + this.write(encode(withAttributes ? '8' : '[u')); + return this; +}; + +Charm.prototype.erase = function (s) { + if (s === 'end' || s === '$') { + this.write(encode('[K')); + } + else if (s === 'start' || s === '^') { + this.write(encode('[1K')); + } + else if (s === 'line') { + this.write(encode('[2K')); + } + else if (s === 'down') { + this.write(encode('[J')); + } + else if (s === 'up') { + this.write(encode('[1J')); + } + else if (s === 'screen') { + this.write(encode('[1J')); + } + else { + this.emit('error', new Error('Unknown erase type: ' + s)); + } + return this; +}; + +Charm.prototype.display = function (attr) { + var c = { + reset : 0, + bright : 1, + dim : 2, + underscore : 4, + blink : 5, + reverse : 7, + hidden : 8 + }[attr]; + if (c === undefined) { + this.emit('error', new Error('Unknown attribute: ' + attr)); + } + this.write(encode('[' + c + 'm')); + return this; +}; + +Charm.prototype.foreground = function (color) { + if (typeof color === 'number') { + if (color < 0 || color >= 256) { + this.emit('error', new Error('Color out of range: ' + color)); + } + this.write(encode('[38;5;' + color + 'm')); + } + else { + var c = { + black : 30, + red : 31, + green : 32, + yellow : 33, + blue : 34, + magenta : 35, + cyan : 36, + white : 37 + }[color.toLowerCase()]; + + if (!c) this.emit('error', new Error('Unknown color: ' + color)); + this.write(encode('[' + c + 'm')); + } + return this; +}; + +Charm.prototype.background = function (color) { + if (typeof color === 'number') { + if (color < 0 || color >= 256) { + this.emit('error', new Error('Color out of range: ' + color)); + } + this.write(encode('[48;5;' + color + 'm')); + } + else { + var c = { + black : 40, + red : 41, + green : 42, + yellow : 43, + blue : 44, + magenta : 45, + cyan : 46, + white : 47 + }[color.toLowerCase()]; + + if (!c) this.emit('error', new Error('Unknown color: ' + color)); + this.write(encode('[' + c + 'm')); + } + return this; +}; + +Charm.prototype.cursor = function (visible) { + this.write(encode(visible ? '[?25h' : '[?25l')); + return this; +}; + +var extractCodes = exports.extractCodes = function (buf) { + var codes = []; + var start = -1; + + for (var i = 0; i < buf.length; i++) { + if (buf[i] === 27) { + if (start >= 0) codes.push(buf.slice(start, i)); + start = i; + } + else if (start >= 0 && i === buf.length - 1) { + codes.push(buf.slice(start)); + } + } + + return codes; +} diff --git a/node_modules/charm/lib/encode.js b/node_modules/charm/lib/encode.js new file mode 100644 index 0000000..3b6417a --- /dev/null +++ b/node_modules/charm/lib/encode.js @@ -0,0 +1,18 @@ +var encode = module.exports = function (xs) { + function bytes (s) { + if (typeof s === 'string') { + return s.split('').map(ord); + } + else if (Array.isArray(s)) { + return s.reduce(function (acc, c) { + return acc.concat(bytes(c)); + }, []); + } + } + + return new Buffer([ 0x1b ].concat(bytes(xs))); +}; + +var ord = encode.ord = function ord (c) { + return c.charCodeAt(0) +}; diff --git a/node_modules/charm/package.json b/node_modules/charm/package.json new file mode 100644 index 0000000..b635f60 --- /dev/null +++ b/node_modules/charm/package.json @@ -0,0 +1,32 @@ +{ + "name" : "charm", + "version" : "0.1.2", + "description" : "ansi control sequences for terminal cursor hopping and colors", + "main" : "index.js", + "directories" : { + "lib" : ".", + "example" : "example", + "test" : "test" + }, + "repository" : { + "type" : "git", + "url" : "http://github.com/substack/node-charm.git" + }, + "keywords" : [ + "terminal", + "ansi", + "cursor", + "color", + "console", + "control", + "escape", + "sequence" + ], + "author" : { + "name" : "James Halliday", + "email" : "mail@substack.net", + "url" : "http://substack.net" + }, + "license" : "MIT/X11", + "engine" : { "node" : ">=0.4" } +} diff --git a/node_modules/deep-equal/README.markdown b/node_modules/deep-equal/README.markdown new file mode 100644 index 0000000..c3293d3 --- /dev/null +++ b/node_modules/deep-equal/README.markdown @@ -0,0 +1,55 @@ +deep-equal +========== + +Node's `assert.deepEqual() algorithm` as a standalone module. + +example +======= + +``` js +var equal = require('deep-equal'); +console.dir([ + equal( + { a : [ 2, 3 ], b : [ 4 ] }, + { a : [ 2, 3 ], b : [ 4 ] } + ), + equal( + { x : 5, y : [6] }, + { x : 5, y : 6 } + ) +]); +``` + +methods +======= + +var deepEqual = require('deep-equal') + +deepEqual(a, b) +--------------- + +Compare objects `a` and `b`, returning whether they are equal according to a +recursive equality algorithm. + +install +======= + +With [npm](http://npmjs.org) do: + +``` +npm install deep-equal +``` + +test +==== + +With [npm](http://npmjs.org) do: + +``` +npm test +``` + +license +======= + +MIT. Derived largely from node's assert module. diff --git a/node_modules/deep-equal/example/cmp.js b/node_modules/deep-equal/example/cmp.js new file mode 100644 index 0000000..67014b8 --- /dev/null +++ b/node_modules/deep-equal/example/cmp.js @@ -0,0 +1,11 @@ +var equal = require('../'); +console.dir([ + equal( + { a : [ 2, 3 ], b : [ 4 ] }, + { a : [ 2, 3 ], b : [ 4 ] } + ), + equal( + { x : 5, y : [6] }, + { x : 5, y : 6 } + ) +]); diff --git a/node_modules/deep-equal/index.js b/node_modules/deep-equal/index.js new file mode 100644 index 0000000..e4e37be --- /dev/null +++ b/node_modules/deep-equal/index.js @@ -0,0 +1,84 @@ +var pSlice = Array.prototype.slice; +var Object_keys = typeof Object.keys === 'function' + ? Object.keys + : function (obj) { + var keys = []; + for (var key in obj) keys.push(key); + return keys; + } +; + +var deepEqual = module.exports = function (actual, expected) { + // 7.1. All identical values are equivalent, as determined by ===. + if (actual === expected) { + return true; + + } else if (actual instanceof Date && expected instanceof Date) { + return actual.getTime() === expected.getTime(); + + // 7.3. Other pairs that do not both pass typeof value == 'object', + // equivalence is determined by ==. + } else if (typeof actual != 'object' && typeof expected != 'object') { + return actual == expected; + + // 7.4. For all other Object pairs, including Array objects, equivalence is + // determined by having the same number of owned properties (as verified + // with Object.prototype.hasOwnProperty.call), the same set of keys + // (although not necessarily the same order), equivalent values for every + // corresponding key, and an identical 'prototype' property. Note: this + // accounts for both named and indexed properties on Arrays. + } else { + return objEquiv(actual, expected); + } +} + +function isUndefinedOrNull(value) { + return value === null || value === undefined; +} + +function isArguments(object) { + return Object.prototype.toString.call(object) == '[object Arguments]'; +} + +function objEquiv(a, b) { + if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) + return false; + // an identical 'prototype' property. + if (a.prototype !== b.prototype) return false; + //~~~I've managed to break Object.keys through screwy arguments passing. + // Converting to array solves the problem. + if (isArguments(a)) { + if (!isArguments(b)) { + return false; + } + a = pSlice.call(a); + b = pSlice.call(b); + return deepEqual(a, b); + } + try { + var ka = Object_keys(a), + kb = Object_keys(b), + key, i; + } catch (e) {//happens when one is a string literal and the other isn't + return false; + } + // having the same number of owned properties (keys incorporates + // hasOwnProperty) + if (ka.length != kb.length) + return false; + //the same set of keys (although not necessarily the same order), + ka.sort(); + kb.sort(); + //~~~cheap key test + for (i = ka.length - 1; i >= 0; i--) { + if (ka[i] != kb[i]) + return false; + } + //equivalent values for every corresponding key, and + //~~~possibly expensive deep test + for (i = ka.length - 1; i >= 0; i--) { + key = ka[i]; + if (!deepEqual(a[key], b[key])) return false; + } + return true; +} diff --git a/node_modules/deep-equal/package.json b/node_modules/deep-equal/package.json new file mode 100644 index 0000000..9020c5b --- /dev/null +++ b/node_modules/deep-equal/package.json @@ -0,0 +1,33 @@ +{ + "name" : "deep-equal", + "version" : "0.0.0", + "description" : "node's assert.deepEqual algorithm", + "main" : "index.js", + "directories" : { + "lib" : ".", + "example" : "example", + "test" : "test" + }, + "scripts" : { + "test" : "tap test/*.js" + }, + "devDependencies" : { + "tap" : "0.0.x" + }, + "repository" : { + "type" : "git", + "url" : "http://github.com/substack/node-deep-equal.git" + }, + "keywords" : [ + "equality", + "equal", + "compare" + ], + "author" : { + "name" : "James Halliday", + "email" : "mail@substack.net", + "url" : "http://substack.net" + }, + "license" : "MIT/X11", + "engine" : { "node" : ">=0.4" } +} diff --git a/node_modules/deep-equal/test/cmp.js b/node_modules/deep-equal/test/cmp.js new file mode 100644 index 0000000..8418f0f --- /dev/null +++ b/node_modules/deep-equal/test/cmp.js @@ -0,0 +1,18 @@ +var test = require('tap').test; +var equal = require('../'); + +test('equal', function (t) { + t.ok(equal( + { a : [ 2, 3 ], b : [ 4 ] }, + { a : [ 2, 3 ], b : [ 4 ] } + )); + t.end(); +}); + +test('not equal', function (t) { + t.notOk(equal( + { x : 5, y : [6] }, + { x : 5, y : 6 } + )); + t.end(); +}); diff --git a/node_modules/deep-is/.travis.yml b/node_modules/deep-is/.travis.yml new file mode 100644 index 0000000..58f2371 --- /dev/null +++ b/node_modules/deep-is/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - 0.6 + - 0.8 + - 0.10 diff --git a/node_modules/deep-is/LICENSE b/node_modules/deep-is/LICENSE new file mode 100644 index 0000000..c38f840 --- /dev/null +++ b/node_modules/deep-is/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2012, 2013 Thorsten Lorenz +Copyright (c) 2012 James Halliday +Copyright (c) 2009 Thomas Robinson <280north.com> + +This software is released under the MIT license: + +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/deep-is/README.markdown b/node_modules/deep-is/README.markdown new file mode 100644 index 0000000..eb69a83 --- /dev/null +++ b/node_modules/deep-is/README.markdown @@ -0,0 +1,70 @@ +deep-is +========== + +Node's `assert.deepEqual() algorithm` as a standalone module. Exactly like +[deep-equal](https://github.com/substack/node-deep-equal) except for the fact that `deepEqual(NaN, NaN) === true`. + +This module is around [5 times faster](https://gist.github.com/2790507) +than wrapping `assert.deepEqual()` in a `try/catch`. + +[![browser support](http://ci.testling.com/thlorenz/deep-is.png)](http://ci.testling.com/thlorenz/deep-is) + +[![build status](https://secure.travis-ci.org/thlorenz/deep-is.png)](http://travis-ci.org/thlorenz/deep-is) + +example +======= + +``` js +var equal = require('deep-is'); +console.dir([ + equal( + { a : [ 2, 3 ], b : [ 4 ] }, + { a : [ 2, 3 ], b : [ 4 ] } + ), + equal( + { x : 5, y : [6] }, + { x : 5, y : 6 } + ) +]); +``` + +methods +======= + +var deepIs = require('deep-is') + +deepIs(a, b) +--------------- + +Compare objects `a` and `b`, returning whether they are equal according to a +recursive equality algorithm. + +install +======= + +With [npm](http://npmjs.org) do: + +``` +npm install deep-is +``` + +test +==== + +With [npm](http://npmjs.org) do: + +``` +npm test +``` + +license +======= + +Copyright (c) 2012, 2013 Thorsten Lorenz +Copyright (c) 2012 James Halliday + +Derived largely from node's assert module, which has the copyright statement: + +Copyright (c) 2009 Thomas Robinson <280north.com> + +Released under the MIT license, see LICENSE for details. diff --git a/node_modules/deep-is/example/cmp.js b/node_modules/deep-is/example/cmp.js new file mode 100644 index 0000000..67014b8 --- /dev/null +++ b/node_modules/deep-is/example/cmp.js @@ -0,0 +1,11 @@ +var equal = require('../'); +console.dir([ + equal( + { a : [ 2, 3 ], b : [ 4 ] }, + { a : [ 2, 3 ], b : [ 4 ] } + ), + equal( + { x : 5, y : [6] }, + { x : 5, y : 6 } + ) +]); diff --git a/node_modules/deep-is/index.js b/node_modules/deep-is/index.js new file mode 100644 index 0000000..506fe27 --- /dev/null +++ b/node_modules/deep-is/index.js @@ -0,0 +1,102 @@ +var pSlice = Array.prototype.slice; +var Object_keys = typeof Object.keys === 'function' + ? Object.keys + : function (obj) { + var keys = []; + for (var key in obj) keys.push(key); + return keys; + } +; + +var deepEqual = module.exports = function (actual, expected) { + // enforce Object.is +0 !== -0 + if (actual === 0 && expected === 0) { + return areZerosEqual(actual, expected); + + // 7.1. All identical values are equivalent, as determined by ===. + } else if (actual === expected) { + return true; + + } else if (actual instanceof Date && expected instanceof Date) { + return actual.getTime() === expected.getTime(); + + } else if (isNumberNaN(actual)) { + return isNumberNaN(expected); + + // 7.3. Other pairs that do not both pass typeof value == 'object', + // equivalence is determined by ==. + } else if (typeof actual != 'object' && typeof expected != 'object') { + return actual == expected; + + // 7.4. For all other Object pairs, including Array objects, equivalence is + // determined by having the same number of owned properties (as verified + // with Object.prototype.hasOwnProperty.call), the same set of keys + // (although not necessarily the same order), equivalent values for every + // corresponding key, and an identical 'prototype' property. Note: this + // accounts for both named and indexed properties on Arrays. + } else { + return objEquiv(actual, expected); + } +}; + +function isUndefinedOrNull(value) { + return value === null || value === undefined; +} + +function isArguments(object) { + return Object.prototype.toString.call(object) == '[object Arguments]'; +} + +function isNumberNaN(value) { + // NaN === NaN -> false + return typeof value == 'number' && value !== value; +} + +function areZerosEqual(zeroA, zeroB) { + // (1 / +0|0) -> Infinity, but (1 / -0) -> -Infinity and (Infinity !== -Infinity) + return (1 / zeroA) === (1 / zeroB); +} + +function objEquiv(a, b) { + if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) + return false; + + // an identical 'prototype' property. + if (a.prototype !== b.prototype) return false; + //~~~I've managed to break Object.keys through screwy arguments passing. + // Converting to array solves the problem. + if (isArguments(a)) { + if (!isArguments(b)) { + return false; + } + a = pSlice.call(a); + b = pSlice.call(b); + return deepEqual(a, b); + } + try { + var ka = Object_keys(a), + kb = Object_keys(b), + key, i; + } catch (e) {//happens when one is a string literal and the other isn't + return false; + } + // having the same number of owned properties (keys incorporates + // hasOwnProperty) + if (ka.length != kb.length) + return false; + //the same set of keys (although not necessarily the same order), + ka.sort(); + kb.sort(); + //~~~cheap key test + for (i = ka.length - 1; i >= 0; i--) { + if (ka[i] != kb[i]) + return false; + } + //equivalent values for every corresponding key, and + //~~~possibly expensive deep test + for (i = ka.length - 1; i >= 0; i--) { + key = ka[i]; + if (!deepEqual(a[key], b[key])) return false; + } + return true; +} diff --git a/node_modules/deep-is/package.json b/node_modules/deep-is/package.json new file mode 100644 index 0000000..dae72d7 --- /dev/null +++ b/node_modules/deep-is/package.json @@ -0,0 +1,58 @@ +{ + "name": "deep-is", + "version": "0.1.4", + "description": "node's assert.deepEqual algorithm except for NaN being equal to NaN", + "main": "index.js", + "directories": { + "lib": ".", + "example": "example", + "test": "test" + }, + "scripts": { + "test": "tape test/*.js" + }, + "devDependencies": { + "tape": "~1.0.2" + }, + "repository": { + "type": "git", + "url": "http://github.com/thlorenz/deep-is.git" + }, + "keywords": [ + "equality", + "equal", + "compare" + ], + "author": { + "name": "Thorsten Lorenz", + "email": "thlorenz@gmx.de", + "url": "http://thlorenz.com" + }, + "license": "MIT", + "testling": { + "files": "test/*.js", + "browsers": { + "ie": [ + 6, + 7, + 8, + 9 + ], + "ff": [ + 3.5, + 10, + 15 + ], + "chrome": [ + 10, + 22 + ], + "safari": [ + 5.1 + ], + "opera": [ + 12 + ] + } + } +} diff --git a/node_modules/deep-is/test/NaN.js b/node_modules/deep-is/test/NaN.js new file mode 100644 index 0000000..ddaa5a7 --- /dev/null +++ b/node_modules/deep-is/test/NaN.js @@ -0,0 +1,16 @@ +var test = require('tape'); +var equal = require('../'); + +test('NaN and 0 values', function (t) { + t.ok(equal(NaN, NaN)); + t.notOk(equal(0, NaN)); + t.ok(equal(0, 0)); + t.notOk(equal(0, 1)); + t.end(); +}); + + +test('nested NaN values', function (t) { + t.ok(equal([ NaN, 1, NaN ], [ NaN, 1, NaN ])); + t.end(); +}); diff --git a/node_modules/deep-is/test/cmp.js b/node_modules/deep-is/test/cmp.js new file mode 100644 index 0000000..3071013 --- /dev/null +++ b/node_modules/deep-is/test/cmp.js @@ -0,0 +1,23 @@ +var test = require('tape'); +var equal = require('../'); + +test('equal', function (t) { + t.ok(equal( + { a : [ 2, 3 ], b : [ 4 ] }, + { a : [ 2, 3 ], b : [ 4 ] } + )); + t.end(); +}); + +test('not equal', function (t) { + t.notOk(equal( + { x : 5, y : [6] }, + { x : 5, y : 6 } + )); + t.end(); +}); + +test('nested nulls', function (t) { + t.ok(equal([ null, null, null ], [ null, null, null ])); + t.end(); +}); diff --git a/node_modules/deep-is/test/neg-vs-pos-0.js b/node_modules/deep-is/test/neg-vs-pos-0.js new file mode 100644 index 0000000..ac26130 --- /dev/null +++ b/node_modules/deep-is/test/neg-vs-pos-0.js @@ -0,0 +1,15 @@ +var test = require('tape'); +var equal = require('../'); + +test('0 values', function (t) { + t.ok(equal( 0, 0), ' 0 === 0'); + t.ok(equal( 0, +0), ' 0 === +0'); + t.ok(equal(+0, +0), '+0 === +0'); + t.ok(equal(-0, -0), '-0 === -0'); + + t.notOk(equal(-0, 0), '-0 !== 0'); + t.notOk(equal(-0, +0), '-0 !== +0'); + + t.end(); +}); + diff --git a/node_modules/difflet/.travis.yml b/node_modules/difflet/.travis.yml new file mode 100644 index 0000000..09d3ef3 --- /dev/null +++ b/node_modules/difflet/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.8 + - 0.10 diff --git a/node_modules/difflet/README.markdown b/node_modules/difflet/README.markdown new file mode 100644 index 0000000..9ad4303 --- /dev/null +++ b/node_modules/difflet/README.markdown @@ -0,0 +1,116 @@ +difflet +======= + +Create colorful diffs for javascript objects. + +example +======= + +string.js +--------- + +``` js +var difflet = require('difflet'); + +var s = difflet.compare({ a : 2, c : 5 }, { a : 3, b : 4 }); +process.stdout.write(s); +``` + +output: + +![colorful output](http://substack.net/images/screenshots/difflet_string.png) + +colors.js +--------- + +``` js +var diff = require('difflet')({ indent : 2 }); + +var prev = { + yy : 6, + zz : 5, + a : [1,2,3], + fn : 'beep', + c : { x : 7, z : 3 } +}; + +var next = { + a : [ 1, 2, "z", /beep/, new Buffer(3) ], + fn : function qqq () {}, + b : [5,6,7], + c : { x : 8, y : 5 } +}; + +diff(prev, next).pipe(process.stdout); +``` + +output: + +![colorful output](http://substack.net/images/screenshots/difflet_colors.png) + +green for inserts, blue for updates, red for deletes + +methods +======= + +var difflet = require('difflet') + +var diff = difflet(opts={}) +--------------------------- + +Create a difflet from optional options `opts`. + +With `opts.start(type, stream)` and `opts.stop(type, stream)`, +you can write custom handlers for all the types of differences: +`'inserted'`, `'updated'`, and `'deleted'`. +By default green is used for insertions, blue for updates, and red for +deletions. + +If `opts.indent` is set, output will span multiple lines and `opts.indent` +spaces will be used for leading whitespace. + +If `opts.comma === 'first'` then commas will be placed at the start of lines. + +Setting `opts.comment` to `true` will turn on comments with the previous +contents like this: + +![object comments](http://substack.net/images/screenshots/difflet_object_comments.png) + +diff(prev, next) +---------------- + +Return a stream with the colorful changes between objects `prev` and `next`. + +diff.compare(prev, next) +------------------------ + +Return a string with the colorful changes between `prev` and `next`. + +difflet.compare(prev, next) +--------------------------- + +Return a string with the colorful changes between `prev` and `next` with the +default options. + +install +======= + +With [npm](http://npmjs.org) do: + +``` +npm install difflet +``` + +test +==== + +With [npm](http://npmjs.org) do: + +``` +npm test +``` + +license +======= + +MIT/X11 diff --git a/node_modules/difflet/example/cmp_array.js b/node_modules/difflet/example/cmp_array.js new file mode 100644 index 0000000..bc5733f --- /dev/null +++ b/node_modules/difflet/example/cmp_array.js @@ -0,0 +1,6 @@ +var difflet = require('../'); +var s = difflet({ indent : 2, comment : true }).compare( + [ 1, [2,3,{a:4}], 3 ], + [ 1, [[5],6,7], 4 ] +); +process.stdout.write(s); diff --git a/node_modules/difflet/example/cmp_object.js b/node_modules/difflet/example/cmp_object.js new file mode 100644 index 0000000..5e00e2c --- /dev/null +++ b/node_modules/difflet/example/cmp_object.js @@ -0,0 +1,6 @@ +var difflet = require('../'); +var s = difflet({ indent : 2, comment : true }).compare( + { z : [6,7], a : 'abcdefgh', b : [ 31, 'xxt' ] }, + { x : 5, a : 'abdcefg', b : [ 51, 'xxs' ] } +); +console.log(s); diff --git a/node_modules/difflet/example/colors.js b/node_modules/difflet/example/colors.js new file mode 100644 index 0000000..332bbae --- /dev/null +++ b/node_modules/difflet/example/colors.js @@ -0,0 +1,18 @@ +var diff = require('../')({ indent : 2 }); + +var prev = { + yy : 6, + zz : 5, + a : [1,2,3], + fn : 'beep', + c : { x : 7, z : 3 } +}; + +var next = { + a : [ 1, 2, "z", /beep/, new Buffer(3) ], + fn : function qqq () {}, + b : [5,6,7], + c : { x : 8, y : 5 } +}; + +diff(prev, next).pipe(process.stdout); diff --git a/node_modules/difflet/example/comma_first.js b/node_modules/difflet/example/comma_first.js new file mode 100644 index 0000000..67ece23 --- /dev/null +++ b/node_modules/difflet/example/comma_first.js @@ -0,0 +1,12 @@ +var diff = require('../')({ + indent : 2, + comma : 'first', +}); + +var prev = { yy : 6, zz : 5, a : [1,2,3] }; +var next = { + a : [ 1, 2, 3, [4], "z", /beep/, new Buffer(3) ], + fn : 8, + b : [5,6,7] +}; +diff(prev, next).pipe(process.stdout); diff --git a/node_modules/difflet/example/diff.js b/node_modules/difflet/example/diff.js new file mode 100644 index 0000000..08f6e7a --- /dev/null +++ b/node_modules/difflet/example/diff.js @@ -0,0 +1,15 @@ +var difflet = require('../'); +var a = { + x : 4, + z : 8, + xs : [ 5, 2, 1, { 0 : 'c' } ], +}; + +var b = { + x : 4, + y : 5, + xs : [ 5, 2, 2, { c : 5 } ], +}; + +var s = difflet({ comment : true, indent : 2 }).compare(a, b); +console.log(s); diff --git a/node_modules/difflet/example/html.js b/node_modules/difflet/example/html.js new file mode 100644 index 0000000..9ff4a29 --- /dev/null +++ b/node_modules/difflet/example/html.js @@ -0,0 +1,34 @@ +var difflet = require('../'); +var ent = require('ent'); + +var tags = { + inserted : '', + updated : '', + deleted : '', +}; +var diff = difflet({ + start : function (t, s) { + s.write(tags[t]); + }, + stop : function (t, s) { + s.write(''); + }, + write : function (buf) { + stream.write(ent.encode(buf)) + }, +}); + +var prev = { + yy : 6, + zz : 5, + a : [1,2,3], + fn : function qq () {} +}; +var next = { + a : [ 1, 2, 3, [4], "z", /beep/, new Buffer([0,1,2]) ], + fn : 'I <3 robots', + b : [5,6,7] +}; + +var stream = diff(prev, next); +stream.pipe(process.stdout, { end : false }); diff --git a/node_modules/difflet/example/string.js b/node_modules/difflet/example/string.js new file mode 100644 index 0000000..6cff6cb --- /dev/null +++ b/node_modules/difflet/example/string.js @@ -0,0 +1,4 @@ +var difflet = require('../'); + +var s = difflet.compare({ a : 2, c : 5 }, { a : 3, b : 4 }); +process.stdout.write(s); diff --git a/node_modules/difflet/index.js b/node_modules/difflet/index.js new file mode 100644 index 0000000..278e6b9 --- /dev/null +++ b/node_modules/difflet/index.js @@ -0,0 +1,377 @@ +var traverse = require('traverse'); +var Stream = require('stream').Stream; +var charm = require('charm'); +var deepEqual = require('deep-is'); + +var exports = module.exports = function (opts_) { + var fn = difflet.bind(null, opts_); + fn.compare = function (prev, next) { + var opts = Object.keys(opts_ || {}).reduce(function (acc, key) { + acc[key] = opts_[key]; + return acc; + }, {}); + var s = opts.stream = new Stream; + var data = ''; + s.write = function (buf) { data += buf }; + s.end = function () {}; + s.readable = true; + s.writable = true; + + difflet(opts, prev, next); + return data; + }; + return fn; +}; + +exports.compare = function (prev, next) { + return exports({}).compare(prev, next); +}; + +function difflet (opts, prev, next) { + var stream = opts.stream || new Stream; + if (!opts.stream) { + stream.readable = true; + stream.writable = true; + stream.write = function (buf) { this.emit('data', buf) }; + stream.end = function () { this.emit('end') }; + } + + if (!opts) opts = {}; + if (opts.start === undefined && opts.stop === undefined) { + var c = charm(stream); + opts.start = function (type) { + c.foreground({ + inserted : 'green', + updated : 'blue', + deleted : 'red', + comment : 'cyan', + }[type]); + c.display('bright'); + }; + opts.stop = function (type) { + c.display('reset'); + }; + } + var write = function (buf) { + if (opts.write) opts.write(buf, stream) + else stream.write(buf) + }; + + var commaFirst = opts.comma === 'first'; + + var stringify = function (node, params) { + return stringifier.call(this, true, node, params || opts); + }; + var plainStringify = function (node, params) { + return stringifier.call(this, false, node, params || opts); + }; + + var levels = 0; + function set (type) { + if (levels === 0) opts.start(type, stream); + levels ++; + } + + function unset (type) { + if (--levels === 0) opts.stop(type, stream); + } + + function stringifier (insertable, node, opts) { + var indent = opts.indent; + + if (insertable) { + var prevNode = traverse.get(prev, this.path || []); + } + var inserted = insertable && prevNode === undefined; + + var indentx; + try { + indentx = indent ? Array( + ((this.path || []).length + 1) * indent + 1 + ).join(' ') : ''; + } catch (e) { + // at times we get an invalid Array size here and need to prevent crashing + indentx = ''; + } + if (commaFirst) indentx = indentx.slice(indent); + + if (Array.isArray(node)) { + var updated = (prevNode || traverse.has(prev, this.path)) + && !Array.isArray(prevNode); + if (updated) { + set('updated'); + } + + if (opts.comment && !Array.isArray(prevNode)) { + indent = 0; + } + + this.before(function () { + if (inserted) set('inserted'); + if (indent && commaFirst) { + if ((this.path || []).length === 0 + || Array.isArray(this.parent.node)) { + write('[ '); + } + else write('\n' + indentx + '[ '); + } + else if (indent) { + write('[\n' + indentx); + } + else { + write('['); + } + }); + + this.post(function (child) { + if (!child.isLast && !(indent && commaFirst)) { + write(','); + } + + var prev = prevNode && prevNode[child.key]; + if (indent && opts.comment && child.node !== prev + && (typeof child.node !== 'object' || typeof prev !== 'object') + ) { + set('comment'); + write(' // != '); + traverse(prev).forEach(function (x) { + plainStringify.call(this, x, { indent : 0 }); + }); + unset('comment'); + } + + if (!child.isLast) { + if (indent && commaFirst) { + write('\n' + indentx + ', '); + } + else if (indent) { + write('\n' + indentx); + } + } + }); + + this.after(function () { + if (indent && commaFirst) write('\n' + indentx); + else if (indent) write('\n' + indentx.slice(indent)); + + write(']'); + if (updated) unset('updated'); + if (inserted) unset('inserted'); + }); + } + else if (isRegExp(node)) { + this.block(); + + if (inserted) { + set('inserted'); + write(node.toString()); + unset('inserted'); + } + else if (insertable && prevNode !== node) { + set('updated'); + write(node.toString()); + unset('updated'); + } + else write(node.toString()); + } + else if (typeof node === 'object' + && node && typeof node.inspect === 'function') { + this.block(); + if (inserted) { + set('inserted'); + write(node.inspect()); + unset('inserted'); + } + else if (!(prevNode && typeof prevNode.inspect === 'function' + && prevNode.inspect() === node.inspect())) { + set('updated'); + write(node.inspect()); + unset('updated'); + } + else write(node.inspect()); + } + else if (typeof node == 'object' && node !== null) { + var insertedKey = false; + var deleted = insertable && typeof prevNode === 'object' && prevNode + ? Object.keys(prevNode).filter(function (key) { + return !Object.hasOwnProperty.call(node, key); + }) + : [] + ; + + this.before(function () { + if (inserted) set('inserted'); + write(indent && commaFirst && !this.isRoot + ? '\n' + indentx + '{ ' + : '{' + ); + }); + + this.pre(function (x, key) { + if (insertable) { + var obj = traverse.get(prev, this.path.concat(key)); + if (obj === undefined) { + insertedKey = true; + set('inserted'); + } + } + + if (indent && !commaFirst) write('\n' + indentx); + + plainStringify(key); + write(indent ? ' : ' : ':'); + }); + + this.post(function (child) { + if (!child.isLast && !(indent && commaFirst)) { + write(','); + } + + if (child.isLast && deleted.length) { + if (insertedKey) unset('inserted'); + insertedKey = false; + } + else if (insertedKey) { + unset('inserted'); + insertedKey = false; + } + + var prev = prevNode && prevNode[child.key]; + if (indent && opts.comment && child.node !== prev + && (typeof child.node !== 'object' || typeof prev !== 'object') + ) { + set('comment'); + write(' // != '); + traverse(prev).forEach(function (x) { + plainStringify.call(this, x, { indent : 0 }); + }); + unset('comment'); + } + + if (child.isLast && deleted.length) { + if (insertedKey) unset('inserted'); + insertedKey = false; + + if (indent && commaFirst) { + write('\n' + indentx + ', ') + } + else if (opts.comment && indent) { + write('\n' + indentx); + } + else if (indent) { + write(',\n' + indentx); + } + else write(','); + } + else { + if (!child.isLast) { + if (indent && commaFirst) { + write('\n' + indentx + ', '); + } + } + } + }); + + this.after(function () { + if (inserted) unset('inserted'); + + if (deleted.length) { + if (indent && !commaFirst + && Object.keys(node).length === 0) { + write('\n' + indentx); + } + + set('deleted'); + deleted.forEach(function (key, ix) { + if (indent && opts.comment) { + unset('deleted'); + set('comment'); + write('// '); + unset('comment'); + set('deleted'); + } + + plainStringify(key); + write(indent ? ' : ' : ':'); + traverse(prevNode[key]).forEach(function (x) { + plainStringify.call(this, x, { indent : 0 }); + }); + + var last = ix === deleted.length - 1; + if (insertable && !last) { + if (indent && commaFirst) { + write('\n' + indentx + ', '); + } + else if (indent) { + write(',\n' + indentx); + } + else write(','); + } + }); + unset('deleted'); + } + + if (commaFirst && indent) { + write(indentx.slice(indent) + ' }'); + } + else if (indent) { + write('\n' + indentx.slice(indent) + '}'); + } + else write('}'); + }); + } + else { + var changed = false; + + if (inserted) set('inserted'); + else if (insertable && !deepEqual(prevNode, node)) { + changed = true; + set('updated'); + } + + if (typeof node === 'string') { + write('"' + node.toString().replace(/"/g, '\\"') + '"'); + } + else if (isRegExp(node)) { + write(node.toString()); + } + else if (typeof node === 'function') { + write(node.name + ? '[Function: ' + node.name + ']' + : '[Function]' + ); + } + else if (node === undefined) { + write('undefined'); + } + else if (node === null) { + write('null'); + } + else { + write(node.toString()); + } + + if (inserted) unset('inserted'); + else if (changed) unset('updated'); + } + } + + if (opts.stream) { + traverse(next).forEach(stringify); + } + else process.nextTick(function () { + traverse(next).forEach(stringify); + stream.emit('end'); + }); + + return stream; +} + +function isRegExp (node) { + return node instanceof RegExp || (node + && typeof node.test === 'function' + && typeof node.exec === 'function' + && typeof node.compile === 'function' + && node.constructor && node.constructor.name === 'RegExp' + ); +} diff --git a/node_modules/difflet/package.json b/node_modules/difflet/package.json new file mode 100644 index 0000000..ac804db --- /dev/null +++ b/node_modules/difflet/package.json @@ -0,0 +1,41 @@ +{ + "name" : "difflet", + "description" : "colorful diffs for javascript objects", + "version" : "0.2.6", + "repository" : { + "type" : "git", + "url" : "git://github.com/substack/difflet.git" + }, + "main" : "index.js", + "keywords" : [ + "diff", + "object", + "compare" + ], + "directories" : { + "lib" : ".", + "example" : "example", + "test" : "test" + }, + "scripts" : { + "test" : "tap test/*.js" + }, + "dependencies" : { + "traverse" : "0.6.x", + "charm" : "0.1.x", + "deep-is" : "0.1.x" + }, + "devDependencies" : { + "tap" : "0.1.x", + "ent" : "0.0.x" + }, + "engines" : { + "node" : ">=0.4.0" + }, + "license" : "MIT", + "author" : { + "name" : "James Halliday", + "email" : "mail@substack.net", + "url" : "http://substack.net" + } +} diff --git a/node_modules/difflet/test/diffing-NaN.js b/node_modules/difflet/test/diffing-NaN.js new file mode 100644 index 0000000..d29e6e1 --- /dev/null +++ b/node_modules/difflet/test/diffing-NaN.js @@ -0,0 +1,17 @@ +var difflet = require('../'); +var diff = difflet(); +var test = require('tap').test; + +test('diffing NaN against NaN', function (t) { + t.plan(1); + var d = diff.compare(NaN, NaN); + + t.equal(d, 'NaN'); +}); + +test('diffing { o: NaN } against { o: NaN }', function (t) { + t.plan(1); + var d = diff.compare({ o: NaN }, { o: NaN }); + + t.equal(d, '{"o":NaN}'); +}); diff --git a/node_modules/difflet/test/html.js b/node_modules/difflet/test/html.js new file mode 100644 index 0000000..26d2ed4 --- /dev/null +++ b/node_modules/difflet/test/html.js @@ -0,0 +1,80 @@ +var difflet = require('../'); +var test = require('tap').test; +var ent = require('ent'); + +var tags = { + inserted : 'g', + updated : 'b', + deleted : 'r', +}; + +test('html output', function (t) { + t.plan(1); + var diff = difflet({ + start : function (t, s) { + s.write('<' + tags[t] + '>'); + }, + stop : function (t, s) { + s.write(''); + }, + write : function (buf, s) { + s.write(ent.encode(buf)); + } + }); + + var stream = diff( + { yy : 6, zz : 5, a : [1,2,3], fn : function qqq () {} }, + { + a : [ 1, 2, 3, [4], "z", /beep/, new Buffer([0,1,2]) ], + fn : function rrr () {}, + b : [5,6,7] + } + ); + + var data = '' + stream.on('data', function (buf) { data += buf }); + stream.on('end', function () { + t.equal(data, + '{"a":[1,2,3,[4],"z",' + + '/beep/,<Buffer 00 01 02>],' + + '"fn":[Function: rrr],' + + '"b":[5,6,7],"yy":6,' + + '"zz":5}' + ); + t.end(); + }); +}); + +test('compare html output', function (t) { + t.plan(1); + + var diff = difflet({ + start : function (t, s) { + s.write('<' + tags[t] + '>'); + }, + stop : function (t, s) { + s.write(''); + }, + write : function (buf, s) { + s.write(ent.encode(buf)); + } + }); + + var data = diff.compare( + { yy : 6, zz : 5, a : [1,2,3], fn : function qqq () {} }, + { + a : [ 1, 2, 3, [4], "z", /beep/, new Buffer([0,1,2]) ], + fn : function rrr () {}, + b : [5,6,7] + } + ); + + t.equal(data, + '{"a":[1,2,3,[4],"z",' + + '/beep/,<Buffer 00 01 02>],' + + '"fn":[Function: rrr],' + + '"b":[5,6,7],"yy":6,' + + '"zz":5}' + ); + t.end(); +}); diff --git a/node_modules/lnsocket/.envrc b/node_modules/lnsocket/.envrc new file mode 100644 index 0000000..db6b53e --- /dev/null +++ b/node_modules/lnsocket/.envrc @@ -0,0 +1,6 @@ +#use nix + +export PATH=$PWD:$PATH +export TODO_FILE=$PWD/TODO + +todo.sh ls || : diff --git a/node_modules/lnsocket/.gitmodules b/node_modules/lnsocket/.gitmodules new file mode 100644 index 0000000..967defe --- /dev/null +++ b/node_modules/lnsocket/.gitmodules @@ -0,0 +1,3 @@ +[submodule "deps/secp256k1"] + path = deps/secp256k1 + url = https://github.com/bitcoin-core/secp256k1 diff --git a/node_modules/lnsocket/LICENSE b/node_modules/lnsocket/LICENSE new file mode 100644 index 0000000..0a6688b --- /dev/null +++ b/node_modules/lnsocket/LICENSE @@ -0,0 +1,22 @@ +Copyright 2022 William Casarin. MIT license + +This license applies to everywhere in the codebase, but files with licenses at +the top of the file override this for those files. + +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/lnsocket/Makefile b/node_modules/lnsocket/Makefile new file mode 100644 index 0000000..47b2a7c --- /dev/null +++ b/node_modules/lnsocket/Makefile @@ -0,0 +1,210 @@ + +CFLAGS=-Wall -Os -Ideps/secp256k1/include -Ideps/libsodium/src/libsodium/include -Ideps +LDFLAGS= + +SUBMODULES=deps/secp256k1 + +# Build for the simulator +XCODEDIR=$(shell xcode-select -p) +SIM_SDK=$(XCODEDIR)/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk +IOS_SDK=$(XCODEDIR)/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk + +HEADERS=config.h deps/secp256k1/include/secp256k1.h deps/libsodium/src/libsodium/include/sodium/crypto_aead_chacha20poly1305.h +ARS=libsecp256k1.a libsodium.a lnsocket.a +WASM_ARS=target/js/libsecp256k1.a target/js/libsodium.a target/js/lnsocket.a +OBJS=sha256.o hkdf.o hmac.o sha512.o lnsocket.o error.o handshake.o crypto.o bigsize.o commando.o bech32.o +ARM64_OBJS=$(OBJS:.o=-arm64.o) +X86_64_OBJS=$(OBJS:.o=-x86_64.o) +WASM_OBJS=$(OBJS:.o=-wasm.o) lnsocket_wasm-wasm.o +BINS=test lnrpc + +DEPS=$(OBJS) $(ARS) $(HEADERS) + +all: $(BINS) $(ARS) + +ios: target/ios/lnsocket.a target/ios/libsodium.a target/ios/libsecp256k1.a + +js: target/js/lnsocket.js target/js/lnsocket.wasm + +node: target/node/lnsocket.js target/node/lnsocket.wasm + +target/node/lnsocket.js: target/tmp/node/lnsocket.js lnsocket_lib.js + @mkdir -p target/node + cat $^ > $@ + +target/js/lnsocket.js: target/tmp/js/lnsocket.js lnsocket_lib.js + @mkdir -p target/js + cat $^ > $@ + +libsodium-1.0.18-stable.tar.gz: + wget https://download.libsodium.org/libsodium/releases/libsodium-1.0.18-stable.tar.gz + +deps/libsodium/configure: libsodium-1.0.18-stable.tar.gz + tar xvf $^; \ + mkdir -p deps; \ + mv libsodium-stable deps/libsodium + +deps/secp256k1/.git: + @tools/refresh-submodules.sh $(SUBMODULES) + +lnsocket.a: $(OBJS) + ar rcs $@ $(OBJS) + +target/arm64/lnsocket.a: $(ARM64_OBJS) + @mkdir -p target/arm64 + ar rcs $@ $^ + +target/x86_64/lnsocket.a: $(X86_64_OBJS) + @mkdir -p target/x86_64 + ar rcs $@ $^ + +target/js/lnsocket.a: $(WASM_OBJS) + @mkdir -p target/js + emar rcs $@ $^ + +target/ios/lnsocket.a: target/x86_64/lnsocket.a target/arm64/lnsocket.a + @mkdir -p target/ios + lipo -create $^ -output $@ + +%-arm64.o: %.c config.h + @echo "cc $@" + @$(CC) $(CFLAGS) -c $< -o $@ -arch arm64 -isysroot $(IOS_SDK) -target arm64-apple-ios -fembed-bitcode + +%-wasm.o: %.c config.h + @echo "emcc $@" + @emcc $(CFLAGS) -c $< -o $@ + +%-x86_64.o: %.c config.h + @echo "cc $@" + @$(CC) $(CFLAGS) -c $< -o $@ -arch x86_64 -isysroot $(SIM_SDK) -mios-simulator-version-min=6.0.0 -target x86_64-apple-ios-simulator + +# TODO cross compiled config?? +config.h: configurator + ./configurator > $@ + +configurator: configurator.c + $(CC) $< -o $@ + +%.o: %.c $(HEADERS) + @echo "cc $@" + @$(CC) $(CFLAGS) -c $< -o $@ + +deps/secp256k1/include/secp256k1.h: deps/secp256k1/.git + +deps/libsodium/src/libsodium/include/sodium/crypto_aead_chacha20poly1305.h: deps/libsodium/configure + +deps/secp256k1/config.log: deps/secp256k1/configure + cd deps/secp256k1; \ + ./configure --disable-shared --enable-module-ecdh + +deps/libsodium/config.status: deps/libsodium/configure + cd deps/libsodium; \ + ./configure --disable-shared --enable-minimal + +deps/secp256k1/configure: deps/secp256k1/.git + cd deps/secp256k1; \ + patch -p1 < ../../tools/0001-configure-customizable-AR-and-RANLIB.patch; \ + ./autogen.sh + +deps/libsodium/config.log: deps/libsodium/configure + cd deps/libsodium; \ + ./configure + +deps/secp256k1/.libs/libsecp256k1.a: deps/secp256k1/config.log + cd deps/secp256k1; \ + make -j libsecp256k1.la + +libsecp256k1.a: deps/secp256k1/.libs/libsecp256k1.a + cp $< $@ + +libsodium.a: deps/libsodium/src/libsodium/.libs/libsodium.a + cp $< $@ + +target/ios/libsodium.a: deps/libsodium/libsodium-ios/lib/libsodium.a + @mkdir -p target/ios + cp $< $@ + +target/ios/libsecp256k1.a: deps/secp256k1/libsecp256k1-ios/lib/libsecp256k1.a + @mkdir -p target/ios + cp $< $@ + +target/js/libsecp256k1.a: deps/secp256k1/libsecp256k1-wasm/lib/libsecp256k1.a + @mkdir -p target/js + cp $< $@ + +target/js/libsodium.a: deps/libsodium/libsodium-js/lib/libsodium.a + @mkdir -p target/js + cp $< $@ + +deps/libsodium/libsodium-ios/lib/libsodium.a: deps/libsodium/configure + cd deps/libsodium; \ + ./dist-build/ios.sh + +deps/secp256k1/libsecp256k1-ios/lib/libsecp256k1.a: deps/secp256k1/configure + ./tools/secp-ios.sh + +deps/secp256k1/libsecp256k1-wasm/lib/libsecp256k1.a: deps/secp256k1/configure + ./tools/secp-wasm.sh + +deps/libsodium/libsodium-js/lib/libsodium.a: deps/libsodium/configure + cd deps/libsodium; \ + ./dist-build/emscripten.sh --standard + +deps/libsodium/src/libsodium/.libs/libsodium.a: deps/libsodium/config.log + cd deps/libsodium/src/libsodium; \ + make -j libsodium.la + +install: $(DEPS) + mkdir -p $(PREFIX)/lib $(PREFIX)/include + cp lnsocket.h $(PREFIX)/include + cp lnsocket.a libsecp256k1.a libsodium.a $(PREFIX)/lib + +install-js: js + mkdir -p $(PREFIX)/share/lnsocket + cp target/js/lnsocket.wasm target/js/lnsocket.js $(PREFIX)/share/lnsocket + +dist-node: node + @mkdir -p dist/node + cp target/node/lnsocket.wasm target/node/lnsocket.js dist/node + +install-all: install install-js + +check: test + @./test + +gocheck: + go test ./lnsocket.go + +test: test.o $(DEPS) + @echo "ld test" + @$(CC) $(CFLAGS) test.o $(OBJS) $(ARS) $(LDFLAGS) -o $@ + +lnrpc: lnrpc.o $(DEPS) + @echo "ld lnrpc" + @$(CC) $(CFLAGS) lnrpc.o $(OBJS) $(ARS) $(LDFLAGS) -o $@ + +target/js/lnsocket.wasm: target/tmp/js/lnsocket.js + cp target/tmp/js/lnsocket.wasm target/js/lnsocket.wasm + +target/node/lnsocket.wasm: target/tmp/node/lnsocket.js + cp target/tmp/node/lnsocket.wasm target/node/lnsocket.wasm + +target/tmp/node/lnsocket.js: $(WASM_ARS) lnsocket_pre.js + @mkdir -p target/tmp/node + emcc --pre-js lnsocket_pre.js -s MODULARIZE -flto -s 'EXPORTED_FUNCTIONS=["_malloc", "_free"]' -s EXPORTED_RUNTIME_METHODS=ccall,cwrap $(CFLAGS) -Wl,-whole-archive $(WASM_ARS) -Wl,-no-whole-archive -o $@ + +target/tmp/js/lnsocket.js: $(WASM_ARS) lnsocket_pre.js + @mkdir -p target/tmp/js + emcc --pre-js lnsocket_pre.js -s ENVIRONMENT=web -s MODULARIZE -flto -s 'EXPORTED_FUNCTIONS=["_malloc", "_free"]' -s EXPORTED_RUNTIME_METHODS=ccall,cwrap $(CFLAGS) -Wl,-whole-archive $(WASM_ARS) -Wl,-no-whole-archive -o $@ + +tags: fake + find . -name '*.c' -or -name '*.h' | xargs ctags + +clean: fake + rm -rf $(BINS) config.h $(OBJS) $(ARM64_OBJS) $(X86_64_OBJS) $(WASM_OBJS) target + +distclean: clean + rm -rf $(ARS) deps target + + +.PHONY: fake diff --git a/node_modules/lnsocket/README.md b/node_modules/lnsocket/README.md new file mode 100644 index 0000000..36735a9 --- /dev/null +++ b/node_modules/lnsocket/README.md @@ -0,0 +1,82 @@ + +# lnsocket + +A simple C library for sending messages over the lightning network + +Thanks to Rusty and the clightning project for much of this code, I have +adapted it to be more library friendly. + + +## Motivation + +I wanted a way to send custom messages to my lightning node, such as RPC. +Building this as a simple C library will allow you to speak the lightning +network in native applications, like on mobile. + + +## Dependencies + +You'll need `libtool`, `autoconf`, and `automake` for the `libsodium` & +`secp256k1` submodules, but otherwise there are no dependencies. + +You'll need `emscripten` for the `wasm` build. + +## Building + + $ make + +### iOS + + $ make ios + +This will build `lnsocket.a`, `libsodium.a` and `libsecp256k1.a` under +`target/ios` for `arm64` and `ios-sim-x86`. + + +### WASM/JS/Web + + $ make js + +This will build `lnsocket.js` and `lnsocket.wasm` in `target/js` so that you +can connect to the lightning network from your browser via websockets. See +[examples/websockets.js](examples/websockets.js) for a demo. + +### NodeJS + + $ npm install --save lnsocket + +See [examples/node.js](examples/node.js) + +### Go + +There is a Go version of lnsocket written using lnd's brontide[^3]. + +You can import it via: + + import "github.com/jb55/lnsocket/go" + +It is currently used in fiatjaf's makeinvoice go library[^4] if you want an +example of its usage. + +## C Examples + +* See [test.c](test.c) for a ping/pong example + +* See [lnrpc.c](lnrpc.c) for an RPC example + +## Contributing + +Send patches to `jb55@jb55.com` + + $ git config format.subjectPrefix 'PATCH lnsocket' + $ git config sendemail.to 'William Casarin ' + $ git send-email --annotate HEAD^ + +See git-send-email.io[^1] for configuring your mailer + +You can open a PR on github[^2] as well + +[^1]: https://git-send-email.io/ +[^2]: https://github.com/jb55/lnsocket +[^3]: https://github.com/lightningnetwork/lnd/tree/master/brontide +[^4]: https://github.com/fiatjaf/makeinvoice/blob/d523b35084af04883f94323dc11a50c2a99d253d/makeinvoice.go#L366 diff --git a/node_modules/lnsocket/TODO b/node_modules/lnsocket/TODO new file mode 100644 index 0000000..84db60b --- /dev/null +++ b/node_modules/lnsocket/TODO @@ -0,0 +1,7 @@ +dynamic lib +automatic towire/fromwire serialization +better helpers for building tlvs +(C) python bindings +(A) websocket test suite +(B) nodejs tests +C tests diff --git a/node_modules/lnsocket/bech32.c b/node_modules/lnsocket/bech32.c new file mode 100644 index 0000000..d660c39 --- /dev/null +++ b/node_modules/lnsocket/bech32.c @@ -0,0 +1,211 @@ +/* Stolen from https://github.com/sipa/bech32/blob/master/ref/c/segwit_addr.c, + * with only the two ' > 90' checks hoisted, and more internals exposed */ + +/* Copyright (c) 2017, 2021 Pieter Wuille + * + * 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. + */ + +#include "config.h" +#include +#include +#include "bech32.h" + +static uint32_t bech32_polymod_step(uint32_t pre) { + uint8_t b = pre >> 25; + return ((pre & 0x1FFFFFF) << 5) ^ + (-((b >> 0) & 1) & 0x3b6a57b2UL) ^ + (-((b >> 1) & 1) & 0x26508e6dUL) ^ + (-((b >> 2) & 1) & 0x1ea119faUL) ^ + (-((b >> 3) & 1) & 0x3d4233ddUL) ^ + (-((b >> 4) & 1) & 0x2a1462b3UL); +} + +static uint32_t bech32_final_constant(bech32_encoding enc) { + if (enc == BECH32_ENCODING_BECH32) return 1; + if (enc == BECH32_ENCODING_BECH32M) return 0x2bc830a3; + assert(0); +} + +const char bech32_charset[] = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"; + +const int8_t bech32_charset_rev[128] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 15, -1, 10, 17, 21, 20, 26, 30, 7, 5, -1, -1, -1, -1, -1, -1, + -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1, + 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1, + -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1, + 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1 +}; + +int bech32_encode(char *output, const char *hrp, const uint8_t *data, size_t data_len, size_t max_input_len, bech32_encoding enc) { + uint32_t chk = 1; + size_t i = 0; + while (hrp[i] != 0) { + int ch = hrp[i]; + if (ch < 33 || ch > 126) { + return 0; + } + + if (ch >= 'A' && ch <= 'Z') return 0; + chk = bech32_polymod_step(chk) ^ (ch >> 5); + ++i; + } + if (i + 7 + data_len > max_input_len) return 0; + chk = bech32_polymod_step(chk); + while (*hrp != 0) { + chk = bech32_polymod_step(chk) ^ (*hrp & 0x1f); + *(output++) = *(hrp++); + } + *(output++) = '1'; + for (i = 0; i < data_len; ++i) { + if (*data >> 5) return 0; + chk = bech32_polymod_step(chk) ^ (*data); + *(output++) = bech32_charset[*(data++)]; + } + for (i = 0; i < 6; ++i) { + chk = bech32_polymod_step(chk); + } + chk ^= bech32_final_constant(enc); + for (i = 0; i < 6; ++i) { + *(output++) = bech32_charset[(chk >> ((5 - i) * 5)) & 0x1f]; + } + *output = 0; + return 1; +} + +bech32_encoding bech32_decode(char* hrp, uint8_t *data, size_t *data_len, const char *input, size_t max_input_len) { + uint32_t chk = 1; + size_t i; + size_t input_len = strlen(input); + size_t hrp_len; + int have_lower = 0, have_upper = 0; + if (input_len < 8 || input_len > max_input_len) { + return BECH32_ENCODING_NONE; + } + *data_len = 0; + while (*data_len < input_len && input[(input_len - 1) - *data_len] != '1') { + ++(*data_len); + } + hrp_len = input_len - (1 + *data_len); + if (1 + *data_len >= input_len || *data_len < 6) { + return BECH32_ENCODING_NONE; + } + *(data_len) -= 6; + for (i = 0; i < hrp_len; ++i) { + int ch = input[i]; + if (ch < 33 || ch > 126) { + return BECH32_ENCODING_NONE; + } + if (ch >= 'a' && ch <= 'z') { + have_lower = 1; + } else if (ch >= 'A' && ch <= 'Z') { + have_upper = 1; + ch = (ch - 'A') + 'a'; + } + hrp[i] = ch; + chk = bech32_polymod_step(chk) ^ (ch >> 5); + } + hrp[i] = 0; + chk = bech32_polymod_step(chk); + for (i = 0; i < hrp_len; ++i) { + chk = bech32_polymod_step(chk) ^ (input[i] & 0x1f); + } + ++i; + while (i < input_len) { + int v = (input[i] & 0x80) ? -1 : bech32_charset_rev[(int)input[i]]; + if (input[i] >= 'a' && input[i] <= 'z') have_lower = 1; + if (input[i] >= 'A' && input[i] <= 'Z') have_upper = 1; + if (v == -1) { + return BECH32_ENCODING_NONE; + } + chk = bech32_polymod_step(chk) ^ v; + if (i + 6 < input_len) { + data[i - (1 + hrp_len)] = v; + } + ++i; + } + if (have_lower && have_upper) { + return BECH32_ENCODING_NONE; + } + if (chk == bech32_final_constant(BECH32_ENCODING_BECH32)) { + return BECH32_ENCODING_BECH32; + } else if (chk == bech32_final_constant(BECH32_ENCODING_BECH32M)) { + return BECH32_ENCODING_BECH32M; + } else { + return BECH32_ENCODING_NONE; + } +} + +int bech32_convert_bits(uint8_t* out, size_t* outlen, int outbits, const uint8_t* in, size_t inlen, int inbits, int pad) { + uint32_t val = 0; + int bits = 0; + uint32_t maxv = (((uint32_t)1) << outbits) - 1; + while (inlen--) { + val = (val << inbits) | *(in++); + bits += inbits; + while (bits >= outbits) { + bits -= outbits; + out[(*outlen)++] = (val >> bits) & maxv; + } + } + if (pad) { + if (bits) { + out[(*outlen)++] = (val << (outbits - bits)) & maxv; + } + } else if (((val << (outbits - bits)) & maxv) || bits >= inbits) { + return 0; + } + return 1; +} + +int segwit_addr_encode(char *output, const char *hrp, int witver, const uint8_t *witprog, size_t witprog_len) { + uint8_t data[65]; + size_t datalen = 0; + bech32_encoding enc = BECH32_ENCODING_BECH32; + if (witver > 16) return 0; + if (witver == 0 && witprog_len != 20 && witprog_len != 32) return 0; + if (witprog_len < 2 || witprog_len > 40) return 0; + if (witver > 0) enc = BECH32_ENCODING_BECH32M; + data[0] = witver; + bech32_convert_bits(data + 1, &datalen, 5, witprog, witprog_len, 8, 1); + ++datalen; + return bech32_encode(output, hrp, data, datalen, 90, enc); +} + +int segwit_addr_decode(int* witver, uint8_t* witdata, size_t* witdata_len, const char* hrp, const char* addr) { + uint8_t data[84]; + char hrp_actual[84]; + size_t data_len; + bech32_encoding enc = bech32_decode(hrp_actual, data, &data_len, addr, 90); + if (enc == BECH32_ENCODING_NONE) return 0; + if (data_len == 0 || data_len > 65) return 0; + if (strncmp(hrp, hrp_actual, 84) != 0) return 0; + if (data[0] > 16) return 0; + if (data[0] == 0 && enc != BECH32_ENCODING_BECH32) return 0; + if (data[0] > 0 && enc != BECH32_ENCODING_BECH32M) return 0; + *witdata_len = 0; + if (!bech32_convert_bits(witdata, witdata_len, 8, data + 1, data_len - 1, 5, 0)) return 0; + if (*witdata_len < 2 || *witdata_len > 40) return 0; + if (data[0] == 0 && *witdata_len != 20 && *witdata_len != 32) return 0; + *witver = data[0]; + return 1; +} diff --git a/node_modules/lnsocket/bech32.h b/node_modules/lnsocket/bech32.h new file mode 100644 index 0000000..614ad32 --- /dev/null +++ b/node_modules/lnsocket/bech32.h @@ -0,0 +1,134 @@ +/* Stolen from https://github.com/sipa/bech32/blob/master/ref/c/segwit_addr.h, + * with only the two ' > 90' checks hoisted */ + +/* Copyright (c) 2017, 2021 Pieter Wuille + * + * 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. + */ + +#ifndef LIGHTNING_COMMON_BECH32_H +#define LIGHTNING_COMMON_BECH32_H +#include "config.h" + +#include +#include + +/** Encode a SegWit address + * + * Out: output: Pointer to a buffer of size 73 + strlen(hrp) that will be + * updated to contain the null-terminated address. + * In: hrp: Pointer to the null-terminated human readable part to use + * (chain/network specific). + * ver: Version of the witness program (between 0 and 16 inclusive). + * prog: Data bytes for the witness program (between 2 and 40 bytes). + * prog_len: Number of data bytes in prog. + * Returns 1 if successful. + */ +int segwit_addr_encode( + char *output, + const char *hrp, + int ver, + const uint8_t *prog, + size_t prog_len +); + +/** Decode a SegWit address + * + * Out: ver: Pointer to an int that will be updated to contain the witness + * program version (between 0 and 16 inclusive). + * prog: Pointer to a buffer of size 40 that will be updated to + * contain the witness program bytes. + * prog_len: Pointer to a size_t that will be updated to contain the length + * of bytes in prog. + * hrp: Pointer to the null-terminated human readable part that is + * expected (chain/network specific). + * addr: Pointer to the null-terminated address. + * Returns 1 if successful. + */ +int segwit_addr_decode( + int* ver, + uint8_t* prog, + size_t* prog_len, + const char* hrp, + const char* addr +); + +/** Supported encodings. */ +typedef enum { + BECH32_ENCODING_NONE, + BECH32_ENCODING_BECH32, + BECH32_ENCODING_BECH32M +} bech32_encoding; + +/** Encode a Bech32 or Bech32m string + * + * Out: output: Pointer to a buffer of size strlen(hrp) + data_len + 8 that + * will be updated to contain the null-terminated Bech32 string. + * In: hrp : Pointer to the null-terminated human readable part. + * data : Pointer to an array of 5-bit values. + * data_len: Length of the data array. + * max_input_len: Maximum valid length of input (90 for segwit usage). + * enc: Which encoding to use (BECH32_ENCODING_BECH32{,M}). + * Returns 1 if successful. + */ +int bech32_encode( + char *output, + const char *hrp, + const uint8_t *data, + size_t data_len, + size_t max_input_len, + bech32_encoding enc +); + +/** Decode a Bech32 or Bech32m string + * + * Out: hrp: Pointer to a buffer of size strlen(input) - 6. Will be + * updated to contain the null-terminated human readable part. + * data: Pointer to a buffer of size strlen(input) - 8 that will + * hold the encoded 5-bit data values. + * data_len: Pointer to a size_t that will be updated to be the number + * of entries in data. + * In: input: Pointer to a null-terminated Bech32 string. + * max_input_len: Maximum valid length of input (90 for segwit usage). + * Returns BECH32_ENCODING_BECH32{,M} to indicate decoding was successful + * with the specified encoding standard. BECH32_ENCODING_NONE is returned if + * decoding failed. + */ +bech32_encoding bech32_decode( + char *hrp, + uint8_t *data, + size_t *data_len, + const char *input, + size_t max_input_len +); + +/* Helper from bech32: translates inbits-bit bytes to outbits-bit bytes. + * @outlen is incremented as bytes are added. + * @pad is true if we're to pad, otherwise truncate last byte if necessary + */ +int bech32_convert_bits(uint8_t* out, size_t* outlen, int outbits, + const uint8_t* in, size_t inlen, int inbits, + int pad); + +/* The charset, and reverse mapping */ +extern const char bech32_charset[32]; +extern const int8_t bech32_charset_rev[128]; + +#endif /* LIGHTNING_COMMON_BECH32_H */ + diff --git a/node_modules/lnsocket/bigsize.c b/node_modules/lnsocket/bigsize.c new file mode 100644 index 0000000..ea8d238 --- /dev/null +++ b/node_modules/lnsocket/bigsize.c @@ -0,0 +1,140 @@ +/* Copyright Rusty Russell (Blockstream) 2015. + William Casarin 2022 + +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. +*/ + + +#include +#include "config.h" +#include "bigsize.h" + +#ifndef SUPERVERBOSE +#define SUPERVERBOSE(...) +#endif + +size_t bigsize_len(bigsize_t v) +{ + if (v < 0xfd) { + return 1; + } else if (v <= 0xffff) { + return 3; + } else if (v <= 0xffffffff) { + return 5; + } else { + return 9; + } +} + +size_t bigsize_put(u8 buf[BIGSIZE_MAX_LEN], bigsize_t v) +{ + u8 *p = buf; + + if (v < 0xfd) { + *(p++) = v; + } else if (v <= 0xffff) { + (*p++) = 0xfd; + (*p++) = v >> 8; + (*p++) = v; + } else if (v <= 0xffffffff) { + (*p++) = 0xfe; + (*p++) = v >> 24; + (*p++) = v >> 16; + (*p++) = v >> 8; + (*p++) = v; + } else { + (*p++) = 0xff; + (*p++) = v >> 56; + (*p++) = v >> 48; + (*p++) = v >> 40; + (*p++) = v >> 32; + (*p++) = v >> 24; + (*p++) = v >> 16; + (*p++) = v >> 8; + (*p++) = v; + } + return p - buf; +} + +size_t bigsize_get(const u8 *p, size_t max, bigsize_t *val) +{ + if (max < 1) { + SUPERVERBOSE("EOF"); + return 0; + } + + switch (*p) { + case 0xfd: + if (max < 3) { + SUPERVERBOSE("unexpected EOF"); + return 0; + } + *val = ((u64)p[1] << 8) + p[2]; + if (*val < 0xfd) { + SUPERVERBOSE("decoded bigsize is not canonical"); + return 0; + } + return 3; + case 0xfe: + if (max < 5) { + SUPERVERBOSE("unexpected EOF"); + return 0; + } + *val = ((u64)p[1] << 24) + ((u64)p[2] << 16) + + ((u64)p[3] << 8) + p[4]; + if ((*val >> 16) == 0) { + SUPERVERBOSE("decoded bigsize is not canonical"); + return 0; + } + return 5; + case 0xff: + if (max < 9) { + SUPERVERBOSE("unexpected EOF"); + return 0; + } + *val = ((u64)p[1] << 56) + ((u64)p[2] << 48) + + ((u64)p[3] << 40) + ((u64)p[4] << 32) + + ((u64)p[5] << 24) + ((u64)p[6] << 16) + + ((u64)p[7] << 8) + p[8]; + if ((*val >> 32) == 0) { + SUPERVERBOSE("decoded bigsize is not canonical"); + return 0; + } + return 9; + default: + *val = *p; + return 1; + } +} + +int cursor_pull_bigsize(struct cursor *cur, bigsize_t *out) +{ + return bigsize_get(cur->p, cur->end - cur->p, out); +} + +int cursor_push_bigsize(struct cursor *cur, const bigsize_t val) +{ + u8 buf[BIGSIZE_MAX_LEN]; + size_t len; + + len = bigsize_put(buf, val); + + return cursor_push(cur, buf, len); +} + diff --git a/node_modules/lnsocket/bigsize.h b/node_modules/lnsocket/bigsize.h new file mode 100644 index 0000000..a630789 --- /dev/null +++ b/node_modules/lnsocket/bigsize.h @@ -0,0 +1,31 @@ +#ifndef LNSOCKET_BIGSIZE_H +#define LNSOCKET_BIGSIZE_H +#include "config.h" +#include "cursor.h" +#include + +/* typedef for clarity. */ +typedef u64 bigsize_t; + +#define BIGSIZE_MAX_LEN 9 + +/* Returns length of buf used. */ +size_t bigsize_put(unsigned char buf[BIGSIZE_MAX_LEN], bigsize_t v); + +/* Returns 0 on failure, otherwise length (<= max) used. */ +size_t bigsize_get(const unsigned char *p, size_t max, bigsize_t *val); + +/* How many bytes does it take to encode v? */ +size_t bigsize_len(bigsize_t v); + +/* Used for wire generation */ +typedef bigsize_t bigsize; + +/* marshal/unmarshal functions */ +void towire_bigsize(unsigned char **pptr, const bigsize_t val); +bigsize_t fromwire_bigsize(const unsigned char **cursor, size_t *max); + +int cursor_pull_bigsize(struct cursor *cur, bigsize_t *out); +int cursor_push_bigsize(struct cursor *cur, const bigsize_t val); + +#endif /* LNSOCKET_BIGSIZE_H */ diff --git a/node_modules/lnsocket/commando.c b/node_modules/lnsocket/commando.c new file mode 100644 index 0000000..cab71da --- /dev/null +++ b/node_modules/lnsocket/commando.c @@ -0,0 +1,36 @@ + +#include "lnsocket.h" +#include "cursor.h" +#include "endian.h" +#include "commando.h" +#include "export.h" + +int EXPORT commando_make_rpc_msg(const char *method, const char *params, + const char *rune, unsigned int req_id, unsigned char *buf, int buflen) +{ + struct cursor msgbuf; + int ok; + + make_cursor(buf, buf+buflen, &msgbuf); + + params = (params == NULL || params[0] == '\0') ? "[]" : params; + + if (!cursor_push_u16(&msgbuf, COMMANDO_CMD)) + return 0; + + if (!cursor_push_u64(&msgbuf, (u64)req_id)) + return 0; + + ok = cursor_push_str(&msgbuf, "{\"method\":\"") && + cursor_push_str(&msgbuf, method) && + cursor_push_str(&msgbuf, "\",\"params\":") && + cursor_push_str(&msgbuf, params) && + cursor_push_str(&msgbuf, ",\"rune\":\"") && + cursor_push_str(&msgbuf, rune) && + cursor_push_str(&msgbuf, "\"}"); + + if (!ok) + return 0; + + return msgbuf.p - msgbuf.start; +} diff --git a/node_modules/lnsocket/commando.h b/node_modules/lnsocket/commando.h new file mode 100644 index 0000000..1e4d211 --- /dev/null +++ b/node_modules/lnsocket/commando.h @@ -0,0 +1,14 @@ + +#ifndef LNSOCKET_COMMANDO +#define LNSOCKET_COMMANDO + +#include +#include "export.h" + +#define COMMANDO_CMD 0x4c4f +#define COMMANDO_REPLY_CONTINUES 0x594b +#define COMMANDO_REPLY_TERM 0x594d + +int EXPORT commando_make_rpc_msg(const char *method, const char *params, const char *rune, unsigned int req_id, unsigned char *buf, int buflen); + +#endif /* LNSOCKET_COMMANDO */ diff --git a/node_modules/lnsocket/compiler.h b/node_modules/lnsocket/compiler.h new file mode 100644 index 0000000..deb0621 --- /dev/null +++ b/node_modules/lnsocket/compiler.h @@ -0,0 +1,85 @@ + +#ifndef COMPILER_H +#define COMPILER_H + +#include +#include +#include +#include "config.h" + +#if HAVE_UNALIGNED_ACCESS +#define alignment_ok(p, n) 1 +#else +#define alignment_ok(p, n) ((size_t)(p) % (n) == 0) +#endif + +#define UNUSED __attribute__((__unused__)) + +/** + * BUILD_ASSERT - assert a build-time dependency. + * @cond: the compile-time condition which must be true. + * + * Your compile will fail if the condition isn't true, or can't be evaluated + * by the compiler. This can only be used within a function. + * + * Example: + * #include + * ... + * static char *foo_to_char(struct foo *foo) + * { + * // This code needs string to be at start of foo. + * BUILD_ASSERT(offsetof(struct foo, string) == 0); + * return (char *)foo; + * } + */ +#define BUILD_ASSERT(cond) \ + do { (void) sizeof(char [1 - 2*!(cond)]); } while(0) + +/** + * BUILD_ASSERT_OR_ZERO - assert a build-time dependency, as an expression. + * @cond: the compile-time condition which must be true. + * + * Your compile will fail if the condition isn't true, or can't be evaluated + * by the compiler. This can be used in an expression: its value is "0". + * + * Example: + * #define foo_to_char(foo) \ + * ((char *)(foo) \ + * + BUILD_ASSERT_OR_ZERO(offsetof(struct foo, string) == 0)) + */ +#define BUILD_ASSERT_OR_ZERO(cond) \ + (sizeof(char [1 - 2*!(cond)]) - 1) + +#define memclear(mem, size) memset(mem, 0, size) +#define memclear_2(m1, s1, m2, s2) { memclear(m1, s1); memclear(m2, s2); } +#define memclear_3(m1, s1, m2, s2, m3, s3) { memclear(m1, s1); memclear(m2, s2); memclear(m3, s3); } + +static inline void *memcheck_(const void *data, size_t len) +{ + (void)len; + return (void *)data; +} + +#if HAVE_TYPEOF +/** + * memcheck - check that a memory region is initialized + * @data: start of region + * @len: length in bytes + * + * When running under valgrind, this causes an error to be printed + * if the entire region is not defined. Otherwise valgrind only + * reports an error when an undefined value is used for a branch, or + * written out. + * + * Example: + * // Search for space, but make sure it's all initialized. + * if (memchr(memcheck(somebytes, bytes_len), ' ', bytes_len)) { + * printf("space was found!\n"); + * } + */ +#define memcheck(data, len) ((__typeof__((data)+0))memcheck_((data), (len))) +#else +#define memcheck(data, len) memcheck_((data), (len)) +#endif + +#endif /* COMPILER_H */ diff --git a/node_modules/lnsocket/configurator.c b/node_modules/lnsocket/configurator.c new file mode 100644 index 0000000..68d7fc6 --- /dev/null +++ b/node_modules/lnsocket/configurator.c @@ -0,0 +1,1110 @@ +/* Simple tool to create config.h. + * Would be much easier with ccan modules, but deliberately standalone. + * + * Copyright 2011 Rusty Russell . MIT license. + * + * c12r_err, c12r_errx functions copied from ccan/err/err.c + * Copyright Rusty Russell . CC0 (Public domain) License. + * + * 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. + */ +#define _POSIX_C_SOURCE 200809L /* For pclose, popen, strdup */ + +#define EXIT_BAD_USAGE 1 +#define EXIT_TROUBLE_RUNNING 2 +#define EXIT_BAD_TEST 3 +#define EXIT_BAD_INPUT 4 + +#include +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +#define popen _popen +#define pclose _pclose +#endif + +#ifdef _MSC_VER +#define DEFAULT_COMPILER "cl" +/* Note: Dash options avoid POSIX path conversion when used under msys bash + * and are therefore preferred to slash (e.g. -nologo over /nologo) + * Note: Disable Warning 4200 "nonstandard extension used : zero-sized array + * in struct/union" for flexible array members. + */ +#define DEFAULT_FLAGS "-nologo -Zi -W4 -wd4200 " \ + "-D_CRT_NONSTDC_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS" +#define DEFAULT_OUTPUT_EXE_FLAG "-Fe:" +#else +#define DEFAULT_COMPILER "cc" +#define DEFAULT_FLAGS "-g3 -ggdb -Wall -Wundef -Wmissing-prototypes -Wmissing-declarations -Wstrict-prototypes -Wold-style-definition" +#define DEFAULT_OUTPUT_EXE_FLAG "-o" +#endif + +#define OUTPUT_FILE "configurator.out" +#define INPUT_FILE "configuratortest.c" + +#ifdef _WIN32 +#define DIR_SEP "\\" +#else +#define DIR_SEP "/" +#endif + +static const char *progname = ""; +static int verbose; +static bool like_a_libtool = false; + +struct test { + const char *name; + const char *desc; + /* + * Template style flags (pick one): + * OUTSIDE_MAIN: + * - put a simple boilerplate main below it. + * DEFINES_FUNC: + * - defines a static function called func; adds ref to avoid warnings + * INSIDE_MAIN: + * - put this inside main(). + * DEFINES_EVERYTHING: + * - don't add any boilerplate at all. + * + * Execution flags: + * EXECUTE: + * - a runtime test; must compile, exit 0 means flag is set. + * MAY_NOT_COMPILE: + * - Only useful with EXECUTE: don't get upset if it doesn't compile. + * : + * - a compile test, if it compiles must run and exit 0. + */ + const char *style; + const char *depends; + const char *link; + const char *fragment; + const char *flags; + const char *overrides; /* On success, force this to '1' */ + bool done; + bool answer; +}; + +/* Terminated by a NULL name */ +static struct test *tests; + +static const struct test base_tests[] = { + { "HAVE_UNALIGNED_ACCESS", "unaligned access to int", + "DEFINES_EVERYTHING|EXECUTE", NULL, NULL, + "#include \n" + "int main(int argc, char *argv[]) {\n" + " (void)argc;\n" + " char pad[sizeof(int *) * 1];\n" + " memcpy(pad, argv[0], sizeof(pad));\n" + " int *x = (int *)pad, *y = (int *)(pad + 1);\n" + " return *x == *y;\n" + "}\n" }, + { "HAVE_TYPEOF", "__typeof__ support", + "INSIDE_MAIN", NULL, NULL, + "__typeof__(argc) i; i = argc; return i == argc ? 0 : 1;" }, + { "HAVE_BIG_ENDIAN", "big endian", + "INSIDE_MAIN|EXECUTE", NULL, NULL, + "union { int i; char c[sizeof(int)]; } u;\n" + "u.i = 0x01020304;\n" + "return u.c[0] == 0x01 && u.c[1] == 0x02 && u.c[2] == 0x03 && u.c[3] == 0x04 ? 0 : 1;" }, + { "HAVE_BYTESWAP_H", "", + "OUTSIDE_MAIN", NULL, NULL, + "#include \n" }, + { "HAVE_BSWAP_64", "bswap64 in byteswap.h", + "DEFINES_FUNC", "HAVE_BYTESWAP_H", NULL, + "#include \n" + "static int func(int x) { return bswap_64(x); }" }, + { "HAVE_LITTLE_ENDIAN", "little endian", + "INSIDE_MAIN|EXECUTE", NULL, NULL, + "union { int i; char c[sizeof(int)]; } u;\n" + "u.i = 0x01020304;\n" + "return u.c[0] == 0x04 && u.c[1] == 0x03 && u.c[2] == 0x02 && u.c[3] == 0x01 ? 0 : 1;" }, + /* + { "HAVE_32BIT_OFF_T", "off_t is 32 bits", + "DEFINES_EVERYTHING|EXECUTE|MAY_NOT_COMPILE", NULL, NULL, + "#include \n" + "int main(void) {\n" + " return sizeof(off_t) == 4 ? 0 : 1;\n" + "}\n" }, + { "HAVE_ALIGNOF", "__alignof__ support", + "INSIDE_MAIN", NULL, NULL, + "return __alignof__(double) > 0 ? 0 : 1;" }, + { "HAVE_ASPRINTF", "asprintf() declaration", + "DEFINES_FUNC", NULL, NULL, + "#ifndef _GNU_SOURCE\n" + "#define _GNU_SOURCE\n" + "#endif\n" + "#include \n" + "static char *func(int x) {" + " char *p;\n" + " if (asprintf(&p, \"%u\", x) == -1) \n" + " p = NULL;\n" + " return p;\n" + "}" }, + { "HAVE_ATTRIBUTE_COLD", "__attribute__((cold)) support", + "DEFINES_FUNC", NULL, NULL, + "static int __attribute__((cold)) func(int x) { return x; }" }, + { "HAVE_ATTRIBUTE_CONST", "__attribute__((const)) support", + "DEFINES_FUNC", NULL, NULL, + "static int __attribute__((const)) func(int x) { return x; }" }, + { "HAVE_ATTRIBUTE_DEPRECATED", "__attribute__((deprecated)) support", + "DEFINES_FUNC", NULL, NULL, + "static int __attribute__((deprecated)) func(int x) { return x; }" }, + { "HAVE_ATTRIBUTE_NONNULL", "__attribute__((nonnull)) support", + "DEFINES_FUNC", NULL, NULL, + "static char *__attribute__((nonnull)) func(char *p) { return p; }" }, + { "HAVE_ATTRIBUTE_RETURNS_NONNULL", "__attribute__((returns_nonnull)) support", + "DEFINES_FUNC", NULL, NULL, + "static const char *__attribute__((returns_nonnull)) func(void) { return \"hi\"; }" }, + { "HAVE_ATTRIBUTE_SENTINEL", "__attribute__((sentinel)) support", + "DEFINES_FUNC", NULL, NULL, + "static int __attribute__((sentinel)) func(int i, ...) { return i; }" }, + { "HAVE_ATTRIBUTE_PURE", "__attribute__((pure)) support", + "DEFINES_FUNC", NULL, NULL, + "static int __attribute__((pure)) func(int x) { return x; }" }, + { "HAVE_ATTRIBUTE_MAY_ALIAS", "__attribute__((may_alias)) support", + "OUTSIDE_MAIN", NULL, NULL, + "typedef short __attribute__((__may_alias__)) short_a;" }, + { "HAVE_ATTRIBUTE_NORETURN", "__attribute__((noreturn)) support", + "DEFINES_FUNC", NULL, NULL, + "#include \n" + "static void __attribute__((noreturn)) func(int x) { exit(x); }" }, + { "HAVE_ATTRIBUTE_PRINTF", "__attribute__ format printf support", + "DEFINES_FUNC", NULL, NULL, + "static void __attribute__((format(__printf__, 1, 2))) func(const char *fmt, ...) { (void)fmt; }" }, + { "HAVE_ATTRIBUTE_UNUSED", "__attribute__((unused)) support", + "OUTSIDE_MAIN", NULL, NULL, + "static int __attribute__((unused)) func(int x) { return x; }" }, + { "HAVE_ATTRIBUTE_USED", "__attribute__((used)) support", + "OUTSIDE_MAIN", NULL, NULL, + "static int __attribute__((used)) func(int x) { return x; }" }, + { "HAVE_BACKTRACE", "backtrace() in ", + "DEFINES_FUNC", NULL, NULL, + "#include \n" + "static int func(int x) {" + " void *bt[10];\n" + " return backtrace(bt, 10) < x;\n" + "}" }, + { "HAVE_BUILTIN_CHOOSE_EXPR", "__builtin_choose_expr support", + "INSIDE_MAIN", NULL, NULL, + "return __builtin_choose_expr(1, 0, \"garbage\");" }, + { "HAVE_BUILTIN_CLZ", "__builtin_clz support", + "INSIDE_MAIN", NULL, NULL, + "return __builtin_clz(1) == (sizeof(int)*8 - 1) ? 0 : 1;" }, + { "HAVE_BUILTIN_CLZL", "__builtin_clzl support", + "INSIDE_MAIN", NULL, NULL, + "return __builtin_clzl(1) == (sizeof(long)*8 - 1) ? 0 : 1;" }, + { "HAVE_BUILTIN_CLZLL", "__builtin_clzll support", + "INSIDE_MAIN", NULL, NULL, + "return __builtin_clzll(1) == (sizeof(long long)*8 - 1) ? 0 : 1;" }, + { "HAVE_BUILTIN_CTZ", "__builtin_ctz support", + "INSIDE_MAIN", NULL, NULL, + "return __builtin_ctz(1 << (sizeof(int)*8 - 1)) == (sizeof(int)*8 - 1) ? 0 : 1;" }, + { "HAVE_BUILTIN_CTZL", "__builtin_ctzl support", + "INSIDE_MAIN", NULL, NULL, + "return __builtin_ctzl(1UL << (sizeof(long)*8 - 1)) == (sizeof(long)*8 - 1) ? 0 : 1;" }, + { "HAVE_BUILTIN_CTZLL", "__builtin_ctzll support", + "INSIDE_MAIN", NULL, NULL, + "return __builtin_ctzll(1ULL << (sizeof(long long)*8 - 1)) == (sizeof(long long)*8 - 1) ? 0 : 1;" }, + { "HAVE_BUILTIN_CONSTANT_P", "__builtin_constant_p support", + "INSIDE_MAIN", NULL, NULL, + "return __builtin_constant_p(1) ? 0 : 1;" }, + { "HAVE_BUILTIN_EXPECT", "__builtin_expect support", + "INSIDE_MAIN", NULL, NULL, + "return __builtin_expect(argc == 1, 1) ? 0 : 1;" }, + { "HAVE_BUILTIN_FFS", "__builtin_ffs support", + "INSIDE_MAIN", NULL, NULL, + "return __builtin_ffs(0) == 0 ? 0 : 1;" }, + { "HAVE_BUILTIN_FFSL", "__builtin_ffsl support", + "INSIDE_MAIN", NULL, NULL, + "return __builtin_ffsl(0L) == 0 ? 0 : 1;" }, + { "HAVE_BUILTIN_FFSLL", "__builtin_ffsll support", + "INSIDE_MAIN", NULL, NULL, + "return __builtin_ffsll(0LL) == 0 ? 0 : 1;" }, + { "HAVE_BUILTIN_POPCOUNT", "__builtin_popcount support", + "INSIDE_MAIN", NULL, NULL, + "return __builtin_popcount(255) == 8 ? 0 : 1;" }, + { "HAVE_BUILTIN_POPCOUNTL", "__builtin_popcountl support", + "INSIDE_MAIN", NULL, NULL, + "return __builtin_popcountl(255L) == 8 ? 0 : 1;" }, + { "HAVE_BUILTIN_POPCOUNTLL", "__builtin_popcountll support", + "INSIDE_MAIN", NULL, NULL, + "return __builtin_popcountll(255LL) == 8 ? 0 : 1;" }, + { "HAVE_BUILTIN_TYPES_COMPATIBLE_P", "__builtin_types_compatible_p support", + "INSIDE_MAIN", NULL, NULL, + "return __builtin_types_compatible_p(char *, int) ? 1 : 0;" }, + { "HAVE_ICCARM_INTRINSICS", "", + "DEFINES_FUNC", NULL, NULL, + "#include \n" + "int func(int v) {\n" + " return __CLZ(__RBIT(v));\n" + "}" }, + { "HAVE_CLOCK_GETTIME", "clock_gettime() declaration", + "DEFINES_FUNC", "HAVE_STRUCT_TIMESPEC", NULL, + "#include \n" + "static struct timespec func(void) {\n" + " struct timespec ts;\n" + " clock_gettime(CLOCK_REALTIME, &ts);\n" + " return ts;\n" + "}\n" }, + { "HAVE_CLOCK_GETTIME_IN_LIBRT", "clock_gettime() in librt", + "DEFINES_FUNC", + "HAVE_STRUCT_TIMESPEC !HAVE_CLOCK_GETTIME", + "-lrt", + "#include \n" + "static struct timespec func(void) {\n" + " struct timespec ts;\n" + " clock_gettime(CLOCK_REALTIME, &ts);\n" + " return ts;\n" + "}\n", + "HAVE_CLOCK_GETTIME" }, + { "HAVE_COMPOUND_LITERALS", "compound literal support", + "INSIDE_MAIN", NULL, NULL, + "int *foo = (int[]) { 1, 2, 3, 4 };\n" + "return foo[0] ? 0 : 1;" }, + { "HAVE_FCHDIR", "fchdir support", + "DEFINES_EVERYTHING|EXECUTE|MAY_NOT_COMPILE", NULL, NULL, + "#include \n" + "#include \n" + "#include \n" + "#include \n" + "int main(void) {\n" + " int fd = open(\"..\", O_RDONLY);\n" + " return fchdir(fd) == 0 ? 0 : 1;\n" + "}\n" }, + { "HAVE_ERR_H", "", + "DEFINES_FUNC", NULL, NULL, + "#include \n" + "static void func(int arg) {\n" + " if (arg == 0)\n" + " err(1, \"err %u\", arg);\n" + " if (arg == 1)\n" + " errx(1, \"err %u\", arg);\n" + " if (arg == 3)\n" + " warn(\"warn %u\", arg);\n" + " if (arg == 4)\n" + " warnx(\"warn %u\", arg);\n" + "}\n" }, + { "HAVE_FILE_OFFSET_BITS", "_FILE_OFFSET_BITS to get 64-bit offsets", + "DEFINES_EVERYTHING|EXECUTE|MAY_NOT_COMPILE", + "HAVE_32BIT_OFF_T", NULL, + "#define _FILE_OFFSET_BITS 64\n" + "#include \n" + "int main(void) {\n" + " return sizeof(off_t) == 8 ? 0 : 1;\n" + "}\n" }, + { "HAVE_FOR_LOOP_DECLARATION", "for loop declaration support", + "INSIDE_MAIN", NULL, NULL, + "int ret = 1;\n" + "for (int i = 0; i < argc; i++) { ret = 0; };\n" + "return ret;" }, + { "HAVE_FLEXIBLE_ARRAY_MEMBER", "flexible array member support", + "OUTSIDE_MAIN", NULL, NULL, + "struct foo { unsigned int x; int arr[]; };" }, + { "HAVE_GETPAGESIZE", "getpagesize() in ", + "DEFINES_FUNC", NULL, NULL, + "#include \n" + "static int func(void) { return getpagesize(); }" }, + { "HAVE_ISBLANK", "isblank() in ", + "DEFINES_FUNC", NULL, NULL, + "#ifndef _GNU_SOURCE\n" + "#define _GNU_SOURCE\n" + "#endif\n" + "#include \n" + "static int func(void) { return isblank(' '); }" }, + { "HAVE_MEMMEM", "memmem in ", + "DEFINES_FUNC", NULL, NULL, + "#ifndef _GNU_SOURCE\n" + "#define _GNU_SOURCE\n" + "#endif\n" + "#include \n" + "static void *func(void *h, size_t hl, void *n, size_t nl) {\n" + "return memmem(h, hl, n, nl);" + "}\n", }, + { "HAVE_MEMRCHR", "memrchr in ", + "DEFINES_FUNC", NULL, NULL, + "#ifndef _GNU_SOURCE\n" + "#define _GNU_SOURCE\n" + "#endif\n" + "#include \n" + "static void *func(void *s, int c, size_t n) {\n" + "return memrchr(s, c, n);" + "}\n", }, + { "HAVE_MMAP", "mmap() declaration", + "DEFINES_FUNC", NULL, NULL, + "#include \n" + "static void *func(int fd) {\n" + " return mmap(0, 65536, PROT_READ, MAP_SHARED, fd, 0);\n" + "}" }, + { "HAVE_PROC_SELF_MAPS", "/proc/self/maps exists", + "DEFINES_EVERYTHING|EXECUTE|MAY_NOT_COMPILE", NULL, NULL, + "#include \n" + "#include \n" + "#include \n" + "int main(void) {\n" + " return open(\"/proc/self/maps\", O_RDONLY) != -1 ? 0 : 1;\n" + "}\n" }, + { "HAVE_QSORT_R_PRIVATE_LAST", "qsort_r cmp takes trailing arg", + "DEFINES_EVERYTHING|EXECUTE|MAY_NOT_COMPILE", NULL, NULL, + "#ifndef _GNU_SOURCE\n" + "#define _GNU_SOURCE\n" + "#endif\n" + "#include \n" + "static int cmp(const void *lp, const void *rp, void *priv) {\n" + " *(unsigned int *)priv = 1;\n" + " return *(const int *)lp - *(const int *)rp; }\n" + "int main(void) {\n" + " int array[] = { 9, 2, 5 };\n" + " unsigned int called = 0;\n" + " qsort_r(array, 3, sizeof(int), cmp, &called);\n" + " return called && array[0] == 2 && array[1] == 5 && array[2] == 9 ? 0 : 1;\n" + "}\n" }, + { "HAVE_STRUCT_TIMESPEC", "struct timespec declaration", + "DEFINES_FUNC", NULL, NULL, + "#include \n" + "static void func(void) {\n" + " struct timespec ts;\n" + " ts.tv_sec = ts.tv_nsec = 1;\n" + "}\n" }, + { "HAVE_SECTION_START_STOP", "__attribute__((section)) and __start/__stop", + "DEFINES_FUNC", NULL, NULL, + "static void *__attribute__((__section__(\"mysec\"))) p = &p;\n" + "static int func(void) {\n" + " extern void *__start_mysec[], *__stop_mysec[];\n" + " return __stop_mysec - __start_mysec;\n" + "}\n" }, + { "HAVE_STACK_GROWS_UPWARDS", "stack grows upwards", + "DEFINES_EVERYTHING|EXECUTE", NULL, NULL, + "#include \n" + "static ptrdiff_t nest(const void *base, unsigned int i)\n" + "{\n" + " if (i == 0)\n" + " return (const char *)&i - (const char *)base;\n" + " return nest(base, i-1);\n" + "}\n" + "int main(int argc, char *argv[]) {\n" + " (void)argv;\n" + " return (nest(&argc, argc) > 0) ? 0 : 1;\n" + "}\n" }, + { "HAVE_STATEMENT_EXPR", "statement expression support", + "INSIDE_MAIN", NULL, NULL, + "return ({ int x = argc; x == argc ? 0 : 1; });" }, + { "HAVE_SYS_FILIO_H", "", + "OUTSIDE_MAIN", NULL, NULL, + "#include \n" }, + { "HAVE_SYS_TERMIOS_H", "", + "OUTSIDE_MAIN", NULL, NULL, + "#include \n" }, + { "HAVE_SYS_UNISTD_H", "", + "OUTSIDE_MAIN", NULL, NULL, + "#include \n" }, + { "HAVE_UTIME", "utime() declaration", + "DEFINES_FUNC", NULL, NULL, + "#include \n" + "#include \n" + "static int func(const char *filename) {\n" + " struct utimbuf times = { 0 };\n" + " return utime(filename, ×);\n" + "}" }, + { "HAVE_WARN_UNUSED_RESULT", "__attribute__((warn_unused_result))", + "DEFINES_FUNC", NULL, NULL, + "#include \n" + "#include \n" + "static __attribute__((warn_unused_result)) int func(int i) {\n" + " return i + 1;\n" + "}" }, + { "HAVE_OPENMP", "#pragma omp and -fopenmp support", + "INSIDE_MAIN|EXECUTE|MAY_NOT_COMPILE", NULL, NULL, + "int i;\n" + "#pragma omp parallel for\n" + "for(i = 0; i < 0; i++) {};\n" + "return 0;\n", + "-Werror -fopenmp" }, + { "HAVE_VALGRIND_MEMCHECK_H", "", + "OUTSIDE_MAIN", NULL, NULL, + "#include \n" }, + { "HAVE_UCONTEXT", "working \n" + "static int x = 0;\n" + "static char stack[2048];\n" + "static ucontext_t a, b;\n" + "static void fn(void) {\n" + " x |= 2;\n" + " setcontext(&b);\n" + " x |= 4;\n" + "}\n" + "int main(void) {\n" + " x |= 1;\n" + " getcontext(&a);\n" + " a.uc_stack.ss_sp = stack;\n" + " a.uc_stack.ss_size = sizeof(stack);\n" + " makecontext(&a, fn, 0);\n" + " swapcontext(&b, &a);\n" + " return (x == 3) ? 0 : 1;\n" + "}\n" + }, + { "HAVE_POINTER_SAFE_MAKECONTEXT", "passing pointers via makecontext()", + "DEFINES_EVERYTHING|EXECUTE|MAY_NOT_COMPILE", + "HAVE_UCONTEXT", NULL, + "#include \n" + "#include \n" + "static int worked = 0;\n" + "static char stack[1024];\n" + "static ucontext_t a, b;\n" + "static void fn(void *p, void *q) {\n" + " void *cp = &worked;\n" + " void *cq = (void *)(~((ptrdiff_t)cp));\n" + " if ((p == cp) && (q == cq))\n" + " worked = 1;\n" + " setcontext(&b);\n" + "}\n" + "int main(void) {\n" + " void *ap = &worked;\n" + " void *aq = (void *)(~((ptrdiff_t)ap));\n" + " getcontext(&a);\n" + " a.uc_stack.ss_sp = stack;\n" + " a.uc_stack.ss_size = sizeof(stack);\n" + " makecontext(&a, (void (*)(void))fn, 2, ap, aq);\n" + " swapcontext(&b, &a);\n" + " return worked ? 0 : 1;\n" + "}\n" + }, + { "HAVE_BUILTIN_CPU_SUPPORTS", "__builtin_cpu_supports()", + "DEFINES_FUNC", NULL, NULL, + "#include \n" + "static bool func(void) {\n" + " return __builtin_cpu_supports(\"mmx\");\n" + "}" + }, + { "HAVE_CLOSEFROM", "closefrom() offered by system", + "DEFINES_EVERYTHING", NULL, NULL, + "#include \n" + "#include \n" + "int main(void) {\n" + " closefrom(STDERR_FILENO + 1);\n" + " return 0;\n" + "}\n" + }, + { "HAVE_F_CLOSEM", "F_CLOSEM defined for fctnl.", + "DEFINES_EVERYTHING", NULL, NULL, + "#include \n" + "#include \n" + "int main(void) {\n" + " int res = fcntl(STDERR_FILENO + 1, F_CLOSEM, 0);\n" + " return res < 0;\n" + "}\n" + }, + { "HAVE_NR_CLOSE_RANGE", "close_range syscall available as __NR_close_range.", + "DEFINES_EVERYTHING", NULL, NULL, + "#include \n" + "#include \n" + "#include \n" + "int main(void) {\n" + " int res = syscall(__NR_close_range, STDERR_FILENO + 1, INT_MAX, 0);\n" + " return res < 0;\n" + "}\n" + }, + { "HAVE_F_MAXFD", "F_MAXFD defined for fcntl.", + "DEFINES_EVERYTHING", NULL, NULL, + "#include \n" + "#include \n" + "int main(void) {\n" + " int res = fcntl(0, F_MAXFD);\n" + " return res < 0;\n" + "}\n" + }, + */ +}; + +static void c12r_err(int eval, const char *fmt, ...) +{ + int err_errno = errno; + va_list ap; + + fprintf(stderr, "%s: ", progname); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, ": %s\n", strerror(err_errno)); + exit(eval); +} + +static void c12r_errx(int eval, const char *fmt, ...) +{ + va_list ap; + + fprintf(stderr, "%s: ", progname); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); + exit(eval); +} + +static void start_test(const char *what, const char *why) +{ + if (like_a_libtool) { + printf("%s%s... ", what, why); + fflush(stdout); + } +} + +static void end_test(bool result) +{ + if (like_a_libtool) + printf("%s\n", result ? "yes" : "no"); +} + +static size_t fcopy(FILE *fsrc, FILE *fdst) +{ + char buffer[BUFSIZ]; + size_t rsize, wsize; + size_t copied = 0; + + while ((rsize = fread(buffer, 1, BUFSIZ, fsrc)) > 0) { + wsize = fwrite(buffer, 1, rsize, fdst); + copied += wsize; + if (wsize != rsize) + break; + } + + return copied; +} + +static char *grab_stream(FILE *file) +{ + size_t max, ret, size = 0; + char *buffer; + + max = BUFSIZ; + buffer = malloc(max); + while ((ret = fread(buffer+size, 1, max - size, file)) == max - size) { + size += ret; + buffer = realloc(buffer, max *= 2); + } + size += ret; + if (ferror(file)) + c12r_err(EXIT_TROUBLE_RUNNING, "reading from command"); + buffer[size] = '\0'; + return buffer; +} + +static char *run(const char *cmd, int *exitstatus) +{ + static const char redir[] = " 2>&1"; + size_t cmdlen; + char *cmdredir; + FILE *cmdout; + char *ret; + + cmdlen = strlen(cmd); + cmdredir = malloc(cmdlen + sizeof(redir)); + memcpy(cmdredir, cmd, cmdlen); + memcpy(cmdredir + cmdlen, redir, sizeof(redir)); + + cmdout = popen(cmdredir, "r"); + if (!cmdout) + c12r_err(EXIT_TROUBLE_RUNNING, "popen \"%s\"", cmdredir); + + free(cmdredir); + + ret = grab_stream(cmdout); + *exitstatus = pclose(cmdout); + return ret; +} + +static char *connect_args(const char *argv[], const char *outflag, + const char *files) +{ + unsigned int i; + char *ret; + size_t len = strlen(outflag) + strlen(files) + 1; + + for (i = 1; argv[i]; i++) + len += 1 + strlen(argv[i]); + + ret = malloc(len); + len = 0; + for (i = 1; argv[i]; i++) { + strcpy(ret + len, argv[i]); + len += strlen(argv[i]); + if (argv[i+1] || *outflag) + ret[len++] = ' '; + } + strcpy(ret + len, outflag); + len += strlen(outflag); + strcpy(ret + len, files); + return ret; +} + +static struct test *find_test(const char *name) +{ + unsigned int i; + + for (i = 0; tests[i].name; i++) { + if (strcmp(tests[i].name, name) == 0) + return &tests[i]; + } + c12r_errx(EXIT_BAD_TEST, "Unknown test %s", name); + abort(); +} + +#define PRE_BOILERPLATE "/* Test program generated by configurator. */\n" +#define MAIN_START_BOILERPLATE \ + "int main(int argc, char *argv[]) {\n" \ + " (void)argc;\n" \ + " (void)argv;\n" +#define USE_FUNC_BOILERPLATE "(void)func;\n" +#define MAIN_BODY_BOILERPLATE "return 0;\n" +#define MAIN_END_BOILERPLATE "}\n" + +static bool run_test(const char *cmd, const char *wrapper, struct test *test) +{ + char *output, *newcmd; + FILE *outf; + int status; + + if (test->done) + return test->answer; + + if (test->depends) { + size_t len; + const char *deps = test->depends; + char *dep; + + /* Space-separated dependencies, could be ! for inverse. */ + while ((len = strcspn(deps, " ")) != 0) { + bool positive = true; + if (deps[len]) { + dep = strdup(deps); + dep[len] = '\0'; + } else { + dep = (char *)deps; + } + + if (dep[0] == '!') { + dep++; + positive = false; + } + if (run_test(cmd, wrapper, find_test(dep)) != positive) { + test->answer = false; + test->done = true; + return test->answer; + } + if (deps[len]) + free(dep); + + deps += len; + deps += strspn(deps, " "); + } + } + + outf = fopen(INPUT_FILE, verbose > 1 ? "w+" : "w"); + if (!outf) + c12r_err(EXIT_TROUBLE_RUNNING, "creating %s", INPUT_FILE); + + fprintf(outf, "%s", PRE_BOILERPLATE); + + if (strstr(test->style, "INSIDE_MAIN")) { + fprintf(outf, "%s", MAIN_START_BOILERPLATE); + fprintf(outf, "%s", test->fragment); + fprintf(outf, "%s", MAIN_END_BOILERPLATE); + } else if (strstr(test->style, "OUTSIDE_MAIN")) { + fprintf(outf, "%s", test->fragment); + fprintf(outf, "%s", MAIN_START_BOILERPLATE); + fprintf(outf, "%s", MAIN_BODY_BOILERPLATE); + fprintf(outf, "%s", MAIN_END_BOILERPLATE); + } else if (strstr(test->style, "DEFINES_FUNC")) { + fprintf(outf, "%s", test->fragment); + fprintf(outf, "%s", MAIN_START_BOILERPLATE); + fprintf(outf, "%s", USE_FUNC_BOILERPLATE); + fprintf(outf, "%s", MAIN_BODY_BOILERPLATE); + fprintf(outf, "%s", MAIN_END_BOILERPLATE); + } else if (strstr(test->style, "DEFINES_EVERYTHING")) { + fprintf(outf, "%s", test->fragment); + } else + c12r_errx(EXIT_BAD_TEST, "Unknown style for test %s: %s", + test->name, test->style); + + if (verbose > 1) { + fseek(outf, 0, SEEK_SET); + fcopy(outf, stdout); + } + + fclose(outf); + + newcmd = strdup(cmd); + + if (test->flags) { + newcmd = realloc(newcmd, strlen(newcmd) + strlen(" ") + + strlen(test->flags) + 1); + strcat(newcmd, " "); + strcat(newcmd, test->flags); + if (verbose > 1) + printf("Extra flags line: %s", newcmd); + } + + if (test->link) { + newcmd = realloc(newcmd, strlen(newcmd) + strlen(" ") + + strlen(test->link) + 1); + strcat(newcmd, " "); + strcat(newcmd, test->link); + if (verbose > 1) + printf("Extra link line: %s", newcmd); + } + + start_test("checking for ", test->desc); + output = run(newcmd, &status); + + free(newcmd); + + if (status != 0 || strstr(output, "warning")) { + if (verbose) + printf("Compile %s for %s, status %i: %s\n", + status ? "fail" : "warning", + test->name, status, output); + if (strstr(test->style, "EXECUTE") + && !strstr(test->style, "MAY_NOT_COMPILE")) + c12r_errx(EXIT_BAD_TEST, + "Test for %s did not compile:\n%s", + test->name, output); + test->answer = false; + free(output); + } else { + /* Compile succeeded. */ + free(output); + /* We run INSIDE_MAIN tests for sanity checking. */ + if (strstr(test->style, "EXECUTE") + || strstr(test->style, "INSIDE_MAIN")) { + char *cmd = malloc(strlen(wrapper) + strlen(" ." DIR_SEP OUTPUT_FILE) + 1); + + strcpy(cmd, wrapper); + strcat(cmd, " ." DIR_SEP OUTPUT_FILE); + output = run(cmd, &status); + free(cmd); + if (!strstr(test->style, "EXECUTE") && status != 0) + c12r_errx(EXIT_BAD_TEST, + "Test for %s failed with %i:\n%s", + test->name, status, output); + if (verbose && status) + printf("%s exited %i\n", test->name, status); + free(output); + } + test->answer = (status == 0); + } + test->done = true; + end_test(test->answer); + + if (test->answer && test->overrides) { + struct test *override = find_test(test->overrides); + override->done = true; + override->answer = true; + } + return test->answer; +} + +static char *any_field(char **fieldname) +{ + char buf[1000]; + for (;;) { + char *p, *eq; + + if (!fgets(buf, sizeof(buf), stdin)) + return NULL; + + p = buf; + /* Ignore whitespace, lines starting with # */ + while (*p == ' ' || *p == '\t') + p++; + if (*p == '#' || *p == '\n') + continue; + + eq = strchr(p, '='); + if (!eq) + c12r_errx(EXIT_BAD_INPUT, "no = in line: %s", p); + *eq = '\0'; + *fieldname = strdup(p); + p = eq + 1; + if (strlen(p) && p[strlen(p)-1] == '\n') + p[strlen(p)-1] = '\0'; + return strdup(p); + } +} + +static char *read_field(const char *name, bool compulsory) +{ + char *fieldname, *value; + + value = any_field(&fieldname); + if (!value) { + if (!compulsory) + return NULL; + c12r_errx(EXIT_BAD_INPUT, "Could not read field %s", name); + } + if (strcmp(fieldname, name) != 0) + c12r_errx(EXIT_BAD_INPUT, + "Expected field %s not %s", name, fieldname); + return value; +} + +/* Test descriptions from stdin: + * Lines starting with # or whitespace-only are ignored. + * + * First three non-ignored lines must be: + * var= + * desc= + * style=OUTSIDE_MAIN DEFINES_FUNC INSIDE_MAIN DEFINES_EVERYTHING EXECUTE MAY_NOT_COMPILE + * + * Followed by optional lines: + * depends= + * link= + * flags= + * overrides= + * + * Finally a code line, either: + * code= OR + * code= + * + * + * + * And looks like this next comment: */ +/*END*/ +static bool read_test(struct test *test) +{ + char *field, *value; + char buf[1000]; + + memset(test, 0, sizeof(*test)); + test->name = read_field("var", false); + if (!test->name) + return false; + test->desc = read_field("desc", true); + test->style = read_field("style", true); + /* Read any optional fields. */ + while ((value = any_field(&field)) != NULL) { + if (strcmp(field, "depends") == 0) + test->depends = value; + else if (strcmp(field, "link") == 0) + test->link = value; + else if (strcmp(field, "flags") == 0) + test->flags = value; + else if (strcmp(field, "overrides") == 0) + test->overrides = value; + else if (strcmp(field, "code") == 0) + break; + else + c12r_errx(EXIT_BAD_INPUT, "Unknown field %s in %s", + field, test->name); + } + if (!value) + c12r_errx(EXIT_BAD_INPUT, "Missing code in %s", test->name); + + if (strlen(value) == 0) { + /* Multiline program, read to END comment */ + while (fgets(buf, sizeof(buf), stdin) != 0) { + size_t n; + if (strncmp(buf, "/*END*/", 7) == 0) + break; + n = strlen(value); + value = realloc(value, n + strlen(buf) + 1); + strcpy(value + n, buf); + n += strlen(buf); + } + } + test->fragment = value; + return true; +} + +static void read_tests(size_t num_tests) +{ + while (read_test(tests + num_tests)) { + num_tests++; + tests = realloc(tests, (num_tests + 1) * sizeof(tests[0])); + tests[num_tests].name = NULL; + } +} + +int main(int argc, const char *argv[]) +{ + char *cmd; + unsigned int i; + const char *default_args[] + = { "", DEFAULT_COMPILER, DEFAULT_FLAGS, NULL }; + const char *outflag = DEFAULT_OUTPUT_EXE_FLAG; + const char *configurator_cc = NULL; + const char *wrapper = ""; + const char *orig_cc; + const char *varfile = NULL; + const char *headerfile = NULL; + bool extra_tests = false; + FILE *outf; + + if (argc > 0) + progname = argv[0]; + + while (argc > 1) { + if (strcmp(argv[1], "--help") == 0) { + printf("Usage: configurator [-v] [--var-file=] [-O] [--configurator-cc=] [--wrapper=] [--autotools-style] [--extra-tests] [ ...]\n" + " will have \" \" appended\n" + "Default: %s %s %s\n", + DEFAULT_COMPILER, DEFAULT_FLAGS, + DEFAULT_OUTPUT_EXE_FLAG); + exit(0); + } + if (strncmp(argv[1], "-O", 2) == 0) { + argc--; + argv++; + outflag = argv[1] + 2; + if (!*outflag) { + fprintf(stderr, + "%s: option requires an argument -- O\n", + argv[0]); + exit(EXIT_BAD_USAGE); + } + } else if (strcmp(argv[1], "-v") == 0) { + argc--; + argv++; + verbose++; + } else if (strcmp(argv[1], "-vv") == 0) { + argc--; + argv++; + verbose += 2; + } else if (strncmp(argv[1], "--configurator-cc=", 18) == 0) { + configurator_cc = argv[1] + 18; + argc--; + argv++; + } else if (strncmp(argv[1], "--wrapper=", 10) == 0) { + wrapper = argv[1] + 10; + argc--; + argv++; + } else if (strncmp(argv[1], "--var-file=", 11) == 0) { + varfile = argv[1] + 11; + argc--; + argv++; + } else if (strcmp(argv[1], "--autotools-style") == 0) { + like_a_libtool = true; + argc--; + argv++; + } else if (strncmp(argv[1], "--header-file=", 14) == 0) { + headerfile = argv[1] + 14; + argc--; + argv++; + } else if (strcmp(argv[1], "--extra-tests") == 0) { + extra_tests = true; + argc--; + argv++; + } else if (strcmp(argv[1], "--") == 0) { + break; + } else if (argv[1][0] == '-') { + c12r_errx(EXIT_BAD_USAGE, "Unknown option %s", argv[1]); + } else { + break; + } + } + + if (argc == 1) + argv = default_args; + + /* Copy with NULL entry at end */ + tests = calloc(sizeof(base_tests)/sizeof(base_tests[0]) + 1, + sizeof(base_tests[0])); + memcpy(tests, base_tests, sizeof(base_tests)); + + if (extra_tests) + read_tests(sizeof(base_tests)/sizeof(base_tests[0])); + + orig_cc = argv[1]; + if (configurator_cc) + argv[1] = configurator_cc; + + cmd = connect_args(argv, outflag, OUTPUT_FILE " " INPUT_FILE); + if (like_a_libtool) { + start_test("Making autoconf users comfortable", ""); + sleep(1); + end_test(1); + } + for (i = 0; tests[i].name; i++) + run_test(cmd, wrapper, &tests[i]); + free(cmd); + + remove(OUTPUT_FILE); + remove(INPUT_FILE); + + if (varfile) { + FILE *vars; + + if (strcmp(varfile, "-") == 0) + vars = stdout; + else { + start_test("Writing variables to ", varfile); + vars = fopen(varfile, "a"); + if (!vars) + c12r_err(EXIT_TROUBLE_RUNNING, + "Could not open %s", varfile); + } + for (i = 0; tests[i].name; i++) + fprintf(vars, "%s=%u\n", tests[i].name, tests[i].answer); + if (vars != stdout) { + if (fclose(vars) != 0) + c12r_err(EXIT_TROUBLE_RUNNING, + "Closing %s", varfile); + end_test(1); + } + } + + if (headerfile) { + start_test("Writing header to ", headerfile); + outf = fopen(headerfile, "w"); + if (!outf) + c12r_err(EXIT_TROUBLE_RUNNING, + "Could not open %s", headerfile); + } else + outf = stdout; + + fprintf(outf, "/* Generated by CCAN configurator */\n" + "#ifndef CCAN_CONFIG_H\n" + "#define CCAN_CONFIG_H\n"); + fprintf(outf, "#ifndef _GNU_SOURCE\n"); + fprintf(outf, "#define _GNU_SOURCE /* Always use GNU extensions. */\n"); + fprintf(outf, "#endif\n"); + fprintf(outf, "#define CCAN_COMPILER \"%s\"\n", orig_cc); + cmd = connect_args(argv + 1, "", ""); + fprintf(outf, "#define CCAN_CFLAGS \"%s\"\n", cmd); + free(cmd); + fprintf(outf, "#define CCAN_OUTPUT_EXE_CFLAG \"%s\"\n\n", outflag); + /* This one implies "#include +#include + +void le64_nonce(unsigned char *npub, u64 nonce) +{ + /* BOLT #8: + * + * ...with nonce `n` encoded as 32 zero bits, followed by a + * *little-endian* 64-bit value. Note: this follows the Noise Protocol + * convention, rather than our normal endian + */ + le64 le_nonce = cpu_to_le64(nonce); + const size_t zerolen = crypto_aead_chacha20poly1305_ietf_NPUBBYTES - sizeof(le_nonce); + + BUILD_ASSERT(crypto_aead_chacha20poly1305_ietf_NPUBBYTES >= sizeof(le_nonce)); + /* First part is 0, followed by nonce. */ + memset(npub, 0, zerolen); + memcpy(npub + zerolen, &le_nonce, sizeof(le_nonce)); +} + +/* out1, out2 = HKDF(in1, in2)` */ +void hkdf_two_keys(struct secret *out1, struct secret *out2, + const struct secret *in1, + const struct secret *in2) +{ + /* BOLT #8: + * + * * `HKDF(salt,ikm)`: a function defined in `RFC 5869`[3](#reference-3), + * evaluated with a zero-length `info` field + * * All invocations of `HKDF` implicitly return 64 bytes + * of cryptographic randomness using the extract-and-expand + * component of the `HKDF`. + */ + struct secret okm[2]; + size_t in2_size = in2 == NULL ? 0 : sizeof(*in2); + + hkdf_sha256(okm, sizeof(okm), in1, sizeof(*in1), in2, in2_size, + NULL, 0); + *out1 = okm[0]; + *out2 = okm[1]; +} + + +static void maybe_rotate_key(u64 *n, struct secret *k, struct secret *ck) +{ + struct secret new_k, new_ck; + + /* BOLT #8: + * + * A key is to be rotated after a party encrypts or decrypts 1000 times + * with it (i.e. every 500 messages). This can be properly accounted + * for by rotating the key once the nonce dedicated to it + * exceeds 1000. + */ + if (*n != 1000) + return; + + /* BOLT #8: + * + * Key rotation for a key `k` is performed according to the following + * steps: + * + * 1. Let `ck` be the chaining key obtained at the end of Act Three. + * 2. `ck', k' = HKDF(ck, k)` + * 3. Reset the nonce for the key to `n = 0`. + * 4. `k = k'` + * 5. `ck = ck'` + */ + hkdf_two_keys(&new_ck, &new_k, ck, k); + + *ck = new_ck; + *k = new_k; + *n = 0; +} + +int cryptomsg_decrypt_body(struct crypto_state *cs, const u8 *in, size_t inlen, u8 *out, size_t outcap) +{ + unsigned char npub[crypto_aead_chacha20poly1305_ietf_NPUBBYTES]; + unsigned long long mlen; + + if (inlen < 16 || outcap < cryptomsg_decrypt_size(inlen)) + return 0; + + le64_nonce(npub, cs->rn++); + + /* BOLT #8: + * + * 5. Decrypt `c` (using `ChaCha20-Poly1305`, `rn`, and `rk`), to + * obtain decrypted plaintext packet `p`. + * * The nonce `rn` MUST be incremented after this step. + */ + if (crypto_aead_chacha20poly1305_ietf_decrypt(out, + &mlen, NULL, + memcheck(in, inlen), + inlen, + NULL, 0, + npub, cs->rk.data) != 0) { + /* FIXME: Report error! */ + return 0; + } + + assert(mlen == cryptomsg_decrypt_size(inlen)); + + maybe_rotate_key(&cs->rn, &cs->rk, &cs->r_ck); + + return 1; +} + +int cryptomsg_decrypt_header(struct crypto_state *cs, u8 hdr[18], u16 *lenp) +{ + unsigned char npub[crypto_aead_chacha20poly1305_ietf_NPUBBYTES]; + unsigned long long mlen; + be16 len; + + le64_nonce(npub, cs->rn++); + + /* BOLT #8: + * + * 2. Let the encrypted length prefix be known as `lc`. + * 3. Decrypt `lc` (using `ChaCha20-Poly1305`, `rn`, and `rk`), to + * obtain the size of the encrypted packet `l`. + * * A zero-length byte slice is to be passed as the AD + * (associated data). + * * The nonce `rn` MUST be incremented after this step. + */ + if (crypto_aead_chacha20poly1305_ietf_decrypt((unsigned char *)&len, + &mlen, NULL, + memcheck(hdr, 18), 18, + NULL, 0, + npub, cs->rk.data) != 0) { + return 0; + } + assert(mlen == sizeof(len)); + *lenp = be16_to_cpu(len); + return 1; +} + +u8 *cryptomsg_encrypt_msg(struct crypto_state *cs, const u8 *msg, unsigned long long mlen, u8 *out, size_t *outlen, size_t outcap) +{ + unsigned char npub[crypto_aead_chacha20poly1305_ietf_NPUBBYTES]; + unsigned long long clen; + be16 l; + int ret; + + *outlen = sizeof(l) + 16 + mlen + 16; + + if (outcap < mlen) { + *outlen = 0; + return NULL; + } + + /* BOLT #8: + * + * In order to encrypt and send a Lightning message (`m`) to the + * network stream, given a sending key (`sk`) and a nonce (`sn`), the + * following steps are completed: + * + * 1. Let `l = len(m)`. + * * where `len` obtains the length in bytes of the Lightning + * message + * + * 2. Serialize `l` into 2 bytes encoded as a big-endian integer. + */ + l = cpu_to_be16(mlen); + + /* BOLT #8: + * + * 3. Encrypt `l` (using `ChaChaPoly-1305`, `sn`, and `sk`), to obtain + * `lc` (18 bytes) + * * The nonce `sn` is encoded as a 96-bit little-endian number. As + * the decoded nonce is 64 bits, the 96-bit nonce is encoded as: + * 32 bits of leading 0s followed by a 64-bit value. + * * The nonce `sn` MUST be incremented after this step. + * * A zero-length byte slice is to be passed as the AD (associated + data). + */ + le64_nonce(npub, cs->sn++); + ret = crypto_aead_chacha20poly1305_ietf_encrypt(out, &clen, + (unsigned char *) + memcheck(&l, sizeof(l)), + sizeof(l), + NULL, 0, + NULL, npub, + cs->sk.data); + assert(ret == 0); + assert(clen == sizeof(l) + 16); + + /* BOLT #8: + * + * 4. Finally, encrypt the message itself (`m`) using the same + * procedure used to encrypt the length prefix. Let + * encrypted ciphertext be known as `c`. + * + * * The nonce `sn` MUST be incremented after this step. + */ + le64_nonce(npub, cs->sn++); + ret = crypto_aead_chacha20poly1305_ietf_encrypt(out + clen, &clen, + memcheck(msg, mlen), + mlen, + NULL, 0, + NULL, npub, + cs->sk.data); + assert(ret == 0); + assert(clen == mlen + 16); + + maybe_rotate_key(&cs->sn, &cs->sk, &cs->s_ck); + + return out; +} diff --git a/node_modules/lnsocket/crypto.h b/node_modules/lnsocket/crypto.h new file mode 100644 index 0000000..5a6e7d3 --- /dev/null +++ b/node_modules/lnsocket/crypto.h @@ -0,0 +1,55 @@ + +#ifndef LNSOCKET_CRYPTO_H +#define LNSOCKET_CRYPTO_H + +#include +#include "typedefs.h" + +#define PUBKEY_CMPR_LEN 33 + +struct secret { + u8 data[32]; +}; + +struct node_id { + u8 k[PUBKEY_CMPR_LEN]; +}; + +struct pubkey { + secp256k1_pubkey pubkey; +}; + +struct privkey { + struct secret secret; +}; + +struct keypair { + struct pubkey pub; + struct privkey priv; +}; + +struct crypto_state { + /* Received and sent nonces. */ + u64 rn, sn; + /* Sending and receiving keys. */ + struct secret sk, rk; + /* Chaining key for re-keying */ + struct secret s_ck, r_ck; +}; + +void le64_nonce(unsigned char *npub, u64 nonce); + +void hkdf_two_keys(struct secret *out1, struct secret *out2, + const struct secret *in1, + const struct secret *in2); + +int cryptomsg_decrypt_body(struct crypto_state *cs, const u8 *in, size_t inlen, u8 *out, size_t outcap); +int cryptomsg_decrypt_header(struct crypto_state *cs, u8 hdr[18], u16 *lenp); +unsigned char *cryptomsg_encrypt_msg(struct crypto_state *cs, const u8 *msg, unsigned long long mlen, u8 *out, size_t *outlen, size_t outcap); + +static inline int cryptomsg_decrypt_size(size_t inlen) +{ + return inlen - 16; +} + +#endif /* LNSOCKET_CRYPTO_H */ diff --git a/node_modules/lnsocket/cursor.h b/node_modules/lnsocket/cursor.h new file mode 100644 index 0000000..eb15a99 --- /dev/null +++ b/node_modules/lnsocket/cursor.h @@ -0,0 +1,393 @@ + + +#ifndef LNSOCKET_CURSOR_H +#define LNSOCKET_CURSOR_H + +#include "typedefs.h" +#include "varint.h" + +#include +#include +#include + +#define unlikely(x) __builtin_expect((x),0) +#define likely(x) __builtin_expect((x),1) + +struct cursor { + unsigned char *start; + unsigned char *p; + unsigned char *end; +}; + +struct array { + struct cursor cur; + unsigned int elem_size; +}; + +static inline void reset_cursor(struct cursor *cursor) +{ + cursor->p = cursor->start; +} + +static inline void wipe_cursor(struct cursor *cursor) +{ + reset_cursor(cursor); + memset(cursor->start, 0, cursor->end - cursor->start); +} + +static inline void make_cursor(u8 *start, u8 *end, struct cursor *cursor) +{ + cursor->start = start; + cursor->p = start; + cursor->end = end; +} + +static inline void make_array(struct array *a, u8* start, u8 *end, unsigned int elem_size) +{ + make_cursor(start, end, &a->cur); + a->elem_size = elem_size; +} + +static inline int cursor_eof(struct cursor *c) +{ + return c->p == c->end; +} + +static inline void *cursor_malloc(struct cursor *mem, unsigned long size) +{ + void *ret; + + if (mem->p + size > mem->end) { + return NULL; + } + + ret = mem->p; + mem->p += size; + + return ret; +} + +static inline void *cursor_alloc(struct cursor *mem, unsigned long size) +{ + void *ret; + if (!(ret = cursor_malloc(mem, size))) { + return 0; + } + + memset(ret, 0, size); + return ret; +} + +static inline int cursor_slice(struct cursor *mem, struct cursor *slice, size_t size) +{ + u8 *p; + if (!(p = cursor_alloc(mem, size))) { + return 0; + } + make_cursor(p, mem->p, slice); + return 1; +} + + +static inline void copy_cursor(struct cursor *src, struct cursor *dest) +{ + dest->start = src->start; + dest->p = src->p; + dest->end = src->end; +} + +static inline int pull_byte(struct cursor *cursor, u8 *c) +{ + if (unlikely(cursor->p + 1 > cursor->end)) + return 0; + + *c = *cursor->p; + cursor->p++; + + return 1; +} + +static inline int cursor_pull_c_str(struct cursor *cursor, const char **str) +{ + *str = (const char*)cursor->p; + + for (; cursor->p < cursor->end; cursor->p++) { + if (*cursor->p == 0) { + cursor->p++; + return 1; + } + } + + return 0; +} + + +static inline int cursor_push_byte(struct cursor *cursor, u8 c) +{ + if (unlikely(cursor->p + 1 > cursor->end)) { + return 0; + } + + *cursor->p = c; + cursor->p++; + + return 1; +} + +static inline int cursor_pull(struct cursor *cursor, u8 *data, int len) +{ + if (unlikely(cursor->p + len > cursor->end)) { + return 0; + } + + memcpy(data, cursor->p, len); + cursor->p += len; + + return 1; +} + +static inline int pull_data_into_cursor(struct cursor *cursor, + struct cursor *dest, + unsigned char **data, + int len) +{ + int ok; + + if (unlikely(dest->p + len > dest->end)) { + printf("not enough room in dest buffer\n"); + return 0; + } + + ok = cursor_pull(cursor, dest->p, len); + if (!ok) return 0; + + *data = dest->p; + dest->p += len; + + return 1; +} + +static inline int cursor_dropn(struct cursor *cur, int size, int n) +{ + if (n == 0) + return 1; + + if (unlikely(cur->p - size*n < cur->start)) { + return 0; + } + + cur->p -= size*n; + return 1; +} + +static inline int cursor_drop(struct cursor *cur, int size) +{ + return cursor_dropn(cur, size, 1); +} + +static inline unsigned char *cursor_topn(struct cursor *cur, int len, int n) +{ + n += 1; + if (unlikely(cur->p - len*n < cur->start)) { + return NULL; + } + return cur->p - len*n; +} + +static inline unsigned char *cursor_top(struct cursor *cur, int len) +{ + if (unlikely(cur->p - len < cur->start)) { + return NULL; + } + return cur->p - len; +} + +static inline int cursor_top_int(struct cursor *cur, int *i) +{ + u8 *p; + if (unlikely(!(p = cursor_top(cur, sizeof(*i))))) { + return 0; + } + *i = *((int*)p); + return 1; +} + +static inline int cursor_pop(struct cursor *cur, u8 *data, int len) +{ + if (unlikely(cur->p - len < cur->start)) { + return 0; + } + + cur->p -= len; + memcpy(data, cur->p, len); + + return 1; +} + +static inline int cursor_push(struct cursor *cursor, const void *data, int len) +{ + if (unlikely(cursor->p + len >= cursor->end)) { + return 0; + } + + if (cursor->p != data) + memcpy(cursor->p, data, len); + + cursor->p += len; + + return 1; +} + +static inline int cursor_push_int(struct cursor *cursor, int i) +{ + return cursor_push(cursor, (u8*)&i, sizeof(i)); +} + +static inline size_t cursor_count(struct cursor *cursor, size_t elem_size) +{ + return (cursor->p - cursor->start)/elem_size; +} + +/* TODO: push_varint */ +static inline int push_varint(struct cursor *cursor, int n) +{ + int ok, len; + unsigned char b; + len = 0; + + while (1) { + b = (n & 0xFF) | 0x80; + n >>= 7; + if (n == 0) { + b &= 0x7F; + ok = cursor_push_byte(cursor, b); + len++; + if (!ok) return 0; + break; + } + + ok = cursor_push_byte(cursor, b); + len++; + if (!ok) return 0; + } + + return len; +} + +/* TODO: pull_varint */ +static inline int pull_varint(struct cursor *cursor, int *n) +{ + int ok, i; + unsigned char b; + *n = 0; + + for (i = 0;; i++) { + ok = pull_byte(cursor, &b); + if (!ok) return 0; + + *n |= ((int)b & 0x7F) << (i * 7); + + /* is_last */ + if ((b & 0x80) == 0) { + return i+1; + } + + if (i == 4) return 0; + } + + return 0; +} + +static inline int cursor_pull_int(struct cursor *cursor, int *i) +{ + return cursor_pull(cursor, (u8*)i, sizeof(*i)); +} + +static inline void *index_cursor(struct cursor *cursor, unsigned int index, int elem_size) +{ + u8 *p; + p = &cursor->start[elem_size * index]; + + if (unlikely(p >= cursor->end)) + return NULL; + + return (void*)p; +} + + +static inline int push_sized_str(struct cursor *cursor, const char *str, int len) +{ + return cursor_push(cursor, (u8*)str, len); +} + +static inline int cursor_push_str(struct cursor *cursor, const char *str) +{ + return cursor_push(cursor, (u8*)str, strlen(str)); +} + +static inline int cursor_push_c_str(struct cursor *cursor, const char *str) +{ + return cursor_push_str(cursor, str) && cursor_push_byte(cursor, 0); +} + +/* TODO: push varint size */ +static inline int push_prefixed_str(struct cursor *cursor, const char *str) +{ + int ok, len; + len = strlen(str); + ok = push_varint(cursor, len); + if (!ok) return 0; + return push_sized_str(cursor, str, len); +} + +static inline int pull_prefixed_str(struct cursor *cursor, struct cursor *dest_buf, const char **str) +{ + int len, ok; + + ok = pull_varint(cursor, &len); + if (!ok) return 0; + + if (unlikely(dest_buf->p + len > dest_buf->end)) { + return 0; + } + + ok = pull_data_into_cursor(cursor, dest_buf, (unsigned char**)str, len); + if (!ok) return 0; + + ok = cursor_push_byte(dest_buf, 0); + + return 1; +} + +static inline int cursor_remaining_capacity(struct cursor *cursor) +{ + return cursor->end - cursor->p; +} + + +#define max(a,b) ((a) > (b) ? (a) : (b)) +static inline void cursor_print_around(struct cursor *cur, int range) +{ + unsigned char *c; + + printf("[%ld/%ld]\n", cur->p - cur->start, cur->end - cur->start); + + c = max(cur->p - range, cur->start); + for (; c < cur->end && c < (cur->p + range); c++) { + printf("%02x", *c); + } + printf("\n"); + + c = max(cur->p - range, cur->start); + for (; c < cur->end && c < (cur->p + range); c++) { + if (c == cur->p) { + printf("^"); + continue; + } + printf(" "); + } + printf("\n"); +} +#undef max + +#endif diff --git a/node_modules/lnsocket/dist/node/lnsocket.js b/node_modules/lnsocket/dist/node/lnsocket.js new file mode 100644 index 0000000..11e88a4 --- /dev/null +++ b/node_modules/lnsocket/dist/node/lnsocket.js @@ -0,0 +1,391 @@ + +var Module = (() => { + var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; + if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename; + return ( +function(Module) { + Module = Module || {}; + +var Module=typeof Module!="undefined"?Module:{};var readyPromiseResolve,readyPromiseReject;Module["ready"]=new Promise(function(resolve,reject){readyPromiseResolve=resolve;readyPromiseReject=reject});Module.getRandomValue=function(){const window_="object"===typeof window?window:this;const crypto_=typeof window_.crypto!=="undefined"?window_.crypto:window_.msCrypto;let randomBytesNode;if(!crypto_){randomBytesNode=require("crypto").randomBytes;fn=randomValuesNode}else{fn=randomValuesStandard}function randomValuesNode(){return randomBytesNode(1)[0]>>>0}function randomValuesStandard(){var buf=new Uint32Array(1);crypto_.getRandomValues(buf);return buf[0]>>>0}return fn}();var moduleOverrides=Object.assign({},Module);var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var ENVIRONMENT_IS_WEB=typeof window=="object";var ENVIRONMENT_IS_WORKER=typeof importScripts=="function";var ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string";var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;function logExceptionOnExit(e){if(e instanceof ExitStatus)return;let toLog=e;err("exiting due to exception: "+toLog)}var fs;var nodePath;var requireNodeFS;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=require("path").dirname(scriptDirectory)+"/"}else{scriptDirectory=__dirname+"/"}requireNodeFS=(()=>{if(!nodePath){fs=require("fs");nodePath=require("path")}});read_=function shell_read(filename,binary){requireNodeFS();filename=nodePath["normalize"](filename);return fs.readFileSync(filename,binary?undefined:"utf8")};readBinary=(filename=>{var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}return ret});readAsync=((filename,onload,onerror)=>{requireNodeFS();filename=nodePath["normalize"](filename);fs.readFile(filename,function(err,data){if(err)onerror(err);else onload(data.buffer)})});if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/")}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",function(reason){throw reason});quit_=((status,toThrow)=>{if(keepRuntimeAlive()){process["exitCode"]=status;throw toThrow}logExceptionOnExit(toThrow);process["exit"](status)});Module["inspect"]=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(_scriptDir){scriptDirectory=_scriptDir}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,"").lastIndexOf("/")+1)}else{scriptDirectory=""}{read_=(url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText});if(ENVIRONMENT_IS_WORKER){readBinary=(url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)})}readAsync=((url,onload,onerror)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=(()=>{if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()});xhr.onerror=onerror;xhr.send(null)})}setWindowTitle=(title=>document.title=title)}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);Object.assign(Module,moduleOverrides);moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime=Module["noExitRuntime"]||true;if(typeof WebAssembly!="object"){abort("no native wasm support detected")}var wasmMemory;var ABORT=false;var EXITSTATUS;function getCFunc(ident){var func=Module["_"+ident];return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len)}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i=endIdx))++endPtr;if(endPtr-idx>16&&heap.subarray&&UTF8Decoder){return UTF8Decoder.decode(heap.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023)}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf)}var INITIAL_MEMORY=Module["INITIAL_MEMORY"]||16777216;var wasmTable;var __ATPRERUN__=[];var __ATINIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeKeepaliveCounter=0;function keepRuntimeAlive(){return noExitRuntime||runtimeKeepaliveCounter>0}function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnInit(cb){__ATINIT__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){{if(Module["onAbort"]){Module["onAbort"](what)}}what="Aborted("+what+")";err(what);ABORT=true;EXITSTATUS=1;what+=". Build with -s ASSERTIONS=1 for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject(e);throw e}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return filename.startsWith(dataURIPrefix)}function isFileURI(filename){return filename.startsWith("file://")}var wasmBinaryFile;wasmBinaryFile="lnsocket.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}function getBinary(file){try{if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}else{throw"both async and sync fetching of the wasm failed"}}catch(err){abort(err)}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)){if(typeof fetch=="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw"failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary(wasmBinaryFile)})}else{if(readAsync){return new Promise(function(resolve,reject){readAsync(wasmBinaryFile,function(response){resolve(new Uint8Array(response))},reject)})}}}return Promise.resolve().then(function(){return getBinary(wasmBinaryFile)})}function createWasm(){var info={"a":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmMemory=Module["asm"]["i"];updateGlobalBufferAndViews(wasmMemory.buffer);wasmTable=Module["asm"]["m"];addOnInit(Module["asm"]["j"]);removeRunDependency("wasm-instantiate")}addRunDependency("wasm-instantiate");function receiveInstantiationResult(result){receiveInstance(result["instance"])}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(function(instance){return instance}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason)})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming=="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch=="function"){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiationResult,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(receiveInstantiationResult)})})}else{return instantiateArrayBuffer(receiveInstantiationResult)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync().catch(readyPromiseReject);return{}}var ASM_CONSTS={70252:function(){return Module.getRandomValue()},70288:function(){if(Module.getRandomValue===undefined){try{var window_="object"===typeof window?window:self;var crypto_=typeof window_.crypto!=="undefined"?window_.crypto:window_.msCrypto;var randomValuesStandard=function(){var buf=new Uint32Array(1);crypto_.getRandomValues(buf);return buf[0]>>>0};randomValuesStandard();Module.getRandomValue=randomValuesStandard}catch(e){try{var crypto=require("crypto");var randomValueNodeJS=function(){var buf=crypto["randomBytes"](4);return(buf[0]<<24|buf[1]<<16|buf[2]<<8|buf[3])>>>0};randomValueNodeJS();Module.getRandomValue=randomValueNodeJS}catch(e){throw"No secure random number generator found"}}}}};function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func=="number"){if(callback.arg===undefined){getWasmTableEntry(func)()}else{getWasmTableEntry(func)(callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}function getWasmTableEntry(funcPtr){return wasmTable.get(funcPtr)}function ___assert_fail(condition,filename,line,func){abort("Assertion failed: "+UTF8ToString(condition)+", at: "+[filename?UTF8ToString(filename):"unknown filename",line,func?UTF8ToString(func):"unknown function"])}function _abort(){abort("")}var readAsmConstArgsArray=[];function readAsmConstArgs(sigPtr,buf){readAsmConstArgsArray.length=0;var ch;buf>>=2;while(ch=HEAPU8[sigPtr++]){var readAsmConstArgsDouble=ch<105;if(readAsmConstArgsDouble&&buf&1)buf++;readAsmConstArgsArray.push(readAsmConstArgsDouble?HEAPF64[buf++>>1]:HEAP32[buf]);++buf}return readAsmConstArgsArray}function _emscripten_asm_const_int(code,sigPtr,argbuf){var args=readAsmConstArgs(sigPtr,argbuf);return ASM_CONSTS[code].apply(null,args)}function _emscripten_memcpy_big(dest,src,num){HEAPU8.copyWithin(dest,src,src+num)}function abortOnCannotGrowMemory(requestedSize){abort("OOM")}function _emscripten_resize_heap(requestedSize){var oldSize=HEAPU8.length;requestedSize=requestedSize>>>0;abortOnCannotGrowMemory(requestedSize)}var SYSCALLS={buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0}else{buffer.push(curr)}},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},get64:function(low,high){return low}};function _fd_close(fd){return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){}function _fd_write(fd,iov,iovcnt,pnum){var num=0;for(var i=0;i>2];var len=HEAP32[iov+4>>2];iov+=8;for(var j=0;j>2]=num;return 0}var asmLibraryArg={"a":___assert_fail,"b":_abort,"h":_emscripten_asm_const_int,"g":_emscripten_memcpy_big,"c":_emscripten_resize_heap,"f":_fd_close,"d":_fd_seek,"e":_fd_write};var asm=createWasm();var ___wasm_call_ctors=Module["___wasm_call_ctors"]=function(){return(___wasm_call_ctors=Module["___wasm_call_ctors"]=Module["asm"]["j"]).apply(null,arguments)};var _malloc=Module["_malloc"]=function(){return(_malloc=Module["_malloc"]=Module["asm"]["k"]).apply(null,arguments)};var _free=Module["_free"]=function(){return(_free=Module["_free"]=Module["asm"]["l"]).apply(null,arguments)};var _lnsocket_make_default_initmsg=Module["_lnsocket_make_default_initmsg"]=function(){return(_lnsocket_make_default_initmsg=Module["_lnsocket_make_default_initmsg"]=Module["asm"]["n"]).apply(null,arguments)};var _lnsocket_encrypt=Module["_lnsocket_encrypt"]=function(){return(_lnsocket_encrypt=Module["_lnsocket_encrypt"]=Module["asm"]["o"]).apply(null,arguments)};var _lnsocket_decrypt=Module["_lnsocket_decrypt"]=function(){return(_lnsocket_decrypt=Module["_lnsocket_decrypt"]=Module["asm"]["p"]).apply(null,arguments)};var _lnsocket_decrypt_header=Module["_lnsocket_decrypt_header"]=function(){return(_lnsocket_decrypt_header=Module["_lnsocket_decrypt_header"]=Module["asm"]["q"]).apply(null,arguments)};var _lnsocket_make_ping_msg=Module["_lnsocket_make_ping_msg"]=function(){return(_lnsocket_make_ping_msg=Module["_lnsocket_make_ping_msg"]=Module["asm"]["r"]).apply(null,arguments)};var _lnsocket_msgbuf=Module["_lnsocket_msgbuf"]=function(){return(_lnsocket_msgbuf=Module["_lnsocket_msgbuf"]=Module["asm"]["s"]).apply(null,arguments)};var _lnsocket_create=Module["_lnsocket_create"]=function(){return(_lnsocket_create=Module["_lnsocket_create"]=Module["asm"]["t"]).apply(null,arguments)};var _lnsocket_destroy=Module["_lnsocket_destroy"]=function(){return(_lnsocket_destroy=Module["_lnsocket_destroy"]=Module["asm"]["u"]).apply(null,arguments)};var _lnsocket_secp=Module["_lnsocket_secp"]=function(){return(_lnsocket_secp=Module["_lnsocket_secp"]=Module["asm"]["v"]).apply(null,arguments)};var _lnsocket_genkey=Module["_lnsocket_genkey"]=function(){return(_lnsocket_genkey=Module["_lnsocket_genkey"]=Module["asm"]["w"]).apply(null,arguments)};var _lnsocket_print_errors=Module["_lnsocket_print_errors"]=function(){return(_lnsocket_print_errors=Module["_lnsocket_print_errors"]=Module["asm"]["x"]).apply(null,arguments)};var _lnsocket_act_two=Module["_lnsocket_act_two"]=function(){return(_lnsocket_act_two=Module["_lnsocket_act_two"]=Module["asm"]["y"]).apply(null,arguments)};var _commando_make_rpc_msg=Module["_commando_make_rpc_msg"]=function(){return(_commando_make_rpc_msg=Module["_commando_make_rpc_msg"]=Module["asm"]["z"]).apply(null,arguments)};var _lnsocket_act_one=Module["_lnsocket_act_one"]=function(){return(_lnsocket_act_one=Module["_lnsocket_act_one"]=Module["asm"]["A"]).apply(null,arguments)};var stackSave=Module["stackSave"]=function(){return(stackSave=Module["stackSave"]=Module["asm"]["B"]).apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){return(stackRestore=Module["stackRestore"]=Module["asm"]["C"]).apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){return(stackAlloc=Module["stackAlloc"]=Module["asm"]["D"]).apply(null,arguments)};Module["ccall"]=ccall;Module["cwrap"]=cwrap;var calledRun;function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(args){args=args||arguments_;if(runDependencies>0){return}preRun();if(runDependencies>0){return}function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();readyPromiseResolve(Module);if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}Module["run"]=run;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}run(); + + + return Module.ready +} +); +})(); +if (typeof exports === 'object' && typeof module === 'object') + module.exports = Module; +else if (typeof define === 'function' && define['amd']) + define([], function() { return Module; }); +else if (typeof exports === 'object') + exports["Module"] = Module; + +async function lnsocket_init() { + const module = await Module() + + function SocketImpl(host) { + if (!(this instanceof SocketImpl)) + return new SocketImpl(host) + + if (typeof WebSocket !== 'undefined') { + console.log("WebSocket", typeof WebSocket) + const ok = host.startsWith("ws://") || host.startsWith("wss://") + if (!ok) + throw new Error("host must start with ws:// or wss://") + const ws = new WebSocket(host) + ws.ondata = function(fn) { + ws.onmessage = (v) => { + const data = v.data.arrayBuffer() + fn(data) + } + } + return ws + } + + // + // we're in nodejs + // + const net = require('net') + let [hostname,port] = host.split(":") + port = +port || 9735 + const socket = net.createConnection(port, hostname, () => { + socket.emit("open") + }) + socket.addEventListener = socket.on.bind(socket) + + if (socket.onmessage) + throw new Error("socket already has onmessage?") + + socket.ondata = (fn) => { + socket.on('data', fn) + } + + socket.close = () => { + socket.destroy() + } + + if (socket.send) + throw new Error("socket already has send?") + + socket.send = function socket_send(data) { + return new Promise((resolve, reject) => { + socket.write(data, resolve) + }); + } + + return socket + } + + const ACT_ONE_SIZE = 50 + const ACT_TWO_SIZE = 50 + const ACT_THREE_SIZE = 66 + const DEFAULT_TIMEOUT = 15000 + + const COMMANDO_REPLY_CONTINUES = 0x594b + const COMMANDO_REPLY_TERM = 0x594d + + const lnsocket_create = module.cwrap("lnsocket_create", "number") + const lnsocket_destroy = module.cwrap("lnsocket_destroy", "number") + const lnsocket_encrypt = module.cwrap("lnsocket_encrypt", "number", ["int", "array", "int", "int"]) + const lnsocket_decrypt = module.cwrap("lnsocket_decrypt", "number", ["int", "array", "int"]) + const lnsocket_decrypt_header = module.cwrap("lnsocket_decrypt_header", "number", ["number", "array"]) + const lnsocket_msgbuf = module.cwrap("lnsocket_msgbuf", "number", ["int"]) + const lnsocket_act_one = module.cwrap("lnsocket_act_one", "number", ["number", "string"]) + const lnsocket_act_two = module.cwrap("lnsocket_act_two", "number", ["number", "array"]) + const lnsocket_print_errors = module.cwrap("lnsocket_print_errors", "int") + const lnsocket_genkey = module.cwrap("lnsocket_genkey", "int") + const lnsocket_make_default_initmsg = module.cwrap("lnsocket_make_default_initmsg", "int", ["int", "int"]) + const lnsocket_make_ping_msg = module.cwrap("lnsocket_make_ping_msg", "int", ["int", "int", "int", "int"]) + const commando_make_rpc_msg = module.cwrap("commando_make_rpc_msg", "int", ["string", "string", "string", "number", "int", "int"]) + + function concat_u8_arrays(arrays) { + // sum of individual array lengths + let totalLength = arrays.reduce((acc, value) => + acc + (value.length || value.byteLength) + , 0); + + if (!arrays.length) return null; + + let result = new Uint8Array(totalLength); + + let length = 0; + for (let array of arrays) { + if (array instanceof ArrayBuffer) + result.set(new Uint8Array(array), length); + else + result.set(array, length); + + length += (array.length || array.byteLength); + } + + return result; + } + + function parse_msgtype(buf) { + return buf[0] << 8 | buf[1] + } + + function wasm_mem(ptr, size) { + return new Uint8Array(module.HEAPU8.buffer, ptr, size); + } + + function LNSocket(opts) { + if (!(this instanceof LNSocket)) + return new LNSocket(opts) + + this.opts = opts || { + timeout: DEFAULT_TIMEOUT + } + this.queue = [] + this.ln = lnsocket_create() + } + + LNSocket.prototype.queue_recv = function() { + let self = this + return new Promise((resolve, reject) => { + const checker = setInterval(() => { + const val = self.queue.shift() + if (val) { + clearInterval(checker) + resolve(val) + } else if (!self.connected) { + clearInterval(checker) + reject() + } + }, 5); + }) + } + + LNSocket.prototype.print_errors = function _lnsocket_print_errors() { + lnsocket_print_errors(this.ln) + } + + LNSocket.prototype.genkey = function _lnsocket_genkey() { + lnsocket_genkey(this.ln) + } + + LNSocket.prototype.act_one_data = function _lnsocket_act_one(node_id) { + const act_one_ptr = lnsocket_act_one(this.ln, node_id) + if (act_one_ptr === 0) + return null + return wasm_mem(act_one_ptr, ACT_ONE_SIZE) + } + + LNSocket.prototype.act_two = function _lnsocket_act_two(act2) { + const act_three_ptr = lnsocket_act_two(this.ln, new Uint8Array(act2)) + if (act_three_ptr === 0) { + this.print_errors() + return null + } + return wasm_mem(act_three_ptr, ACT_THREE_SIZE) + } + + LNSocket.prototype.connect = async function lnsocket_connect(node_id, host) { + await handle_connect(this, node_id, host) + + const act1 = this.act_one_data(node_id) + this.ws.send(act1) + const act2 = await this.read_all(ACT_TWO_SIZE) + if (act2.length != ACT_TWO_SIZE) { + throw new Error(`expected act2 to be ${ACT_TWO_SIZE} long, got ${act2.length}`) + } + const act3 = this.act_two(act2) + this.ws.send(act3) + } + + LNSocket.prototype.connect_and_init = async function _connect_and_init(node_id, host) { + await this.connect(node_id, host) + await this.perform_init() + } + + LNSocket.prototype.read_all = async function read_all(n) { + let count = 0 + let chunks = [] + if (!this.connected) + throw new Error("read_all: not connected") + while (true) { + let res = await this.queue_recv() + + const remaining = n - count + + if (res.byteLength > remaining) { + chunks.push(res.slice(0, remaining)) + this.queue.unshift(res.slice(remaining)) + break + } else if (res.byteLength === remaining) { + chunks.push(res) + break + } + + chunks.push(res) + count += res.byteLength + } + + return concat_u8_arrays(chunks) + } + + LNSocket.prototype.read_header = async function read_header() { + const header = await this.read_all(18) + if (header.length != 18) + throw new Error("Failed to read header") + return lnsocket_decrypt_header(this.ln, header) + } + + LNSocket.prototype.rpc = async function lnsocket_rpc(opts) { + const msg = this.make_commando_msg(opts) + this.write(msg) + const res = await this.read_all_rpc() + return JSON.parse(res) + } + + LNSocket.prototype.recv = async function lnsocket_recv() { + const msg = await this.read() + const msgtype = parse_msgtype(msg.slice(0,2)) + const res = [msgtype, msg.slice(2)] + return res + } + + LNSocket.prototype.read_all_rpc = async function read_all_rpc() { + let chunks = [] + while (true) { + const [typ, msg] = await this.recv() + switch (typ) { + case COMMANDO_REPLY_TERM: + chunks.push(msg.slice(8)) + return new TextDecoder().decode(concat_u8_arrays(chunks)); + case COMMANDO_REPLY_CONTINUES: + chunks.push(msg.slice(8)) + break + default: + console.log("got unknown type", typ) + continue + } + } + } + + LNSocket.prototype.make_commando_msg = function _lnsocket_make_commando_msg(opts) { + const buflen = 4096 + let len = 0; + const buf = module._malloc(buflen); + module.HEAPU8.set(Uint8Array, buf); + + const params = JSON.stringify(opts.params||{}) + if (!(len = commando_make_rpc_msg(opts.method, params, opts.rune, + 0, buf, buflen))) { + throw new Error("couldn't make commando msg"); + } + + const dat = wasm_mem(buf, len) + module._free(buf); + return dat + } + + LNSocket.prototype.make_ping_msg = function _lnsocket_make_ping_msg(num_pong_bytes=1, ignored_bytes=1) { + const buflen = 32 + let len = 0; + const buf = module._malloc(buflen); + module.HEAPU8.set(Uint8Array, buf); + + if (!(len = lnsocket_make_ping_msg(buf, buflen, num_pong_bytes, ignored_bytes))) + throw new Error("couldn't make ping msg"); + + const dat = wasm_mem(buf, len) + module._free(buf); + return dat + } + + LNSocket.prototype.encrypt = function _lnsocket_encrypt(dat) { + const len = lnsocket_encrypt(this.ln, dat, dat.length) + if (len === 0) { + this.print_errors() + throw new Error("encrypt error") + } + const enc = wasm_mem(lnsocket_msgbuf(this.ln), len) + return enc + } + + LNSocket.prototype.decrypt = function _lnsocket_decrypt(dat) { + const len = lnsocket_decrypt(this.ln, dat, dat.length) + if (len === 0) { + this.print_errors() + throw new Error("decrypt error") + } + return wasm_mem(lnsocket_msgbuf(this.ln), len) + } + + LNSocket.prototype.write = function _lnsocket_write(dat) { + this.ws.send(this.encrypt(dat)) + } + + LNSocket.prototype.read = async function _lnsocket_read() { + const size = await this.read_header() + const enc = await this.read_all(size+16) + return this.decrypt(enc) + } + + LNSocket.prototype.make_default_initmsg = function _lnsocket_make_default_initmsg() { + const buflen = 1024 + let len = 0; + const buf = module._malloc(buflen); + module.HEAPU8.set(Uint8Array, buf); + + if (!(len = lnsocket_make_default_initmsg(buf, buflen))) + throw new Error("couldn't make initmsg"); + + const dat = wasm_mem(buf, len) + module._free(buf); + return dat + } + + LNSocket.prototype.perform_init = async function lnsocket_connect() { + await this.read() + const our_init = this.make_default_initmsg() + this.write(our_init) + } + + LNSocket.prototype.ping_pong = async function lnsocket_ping_pong() { + const pingmsg = this.make_ping_msg() + this.write(pingmsg) + return await this.read() + } + + LNSocket.prototype.disconnect = function lnsocket_disconnect() { + if (this.connected === true && this.ws) { + this.ws.close() + return true + } + return false + } + + LNSocket.prototype.destroy = function _lnsocket_destroy() { + this.disconnect() + lnsocket_destroy(this.ln) + } + + function handle_connect(ln, node_id, host) { + const ws = new SocketImpl(host) + return new Promise((resolve, reject) => { + const timeout = ln.opts.timeout || DEFAULT_TIMEOUT + const timer = setTimeout(reject, timeout); + + ws.ondata((v) => { + ln.queue.push(v) + }); + + ws.addEventListener('open', function(ev) { + ln.ws = ws + ln.connected = true + clearTimeout(timer) + resolve(ws) + }); + + ws.addEventListener('close', function(ev) { + ln.connected = false + }); + }) + } + + return LNSocket +} + +Module.init = Module.lnsocket_init = lnsocket_init diff --git a/node_modules/lnsocket/dist/node/lnsocket.wasm b/node_modules/lnsocket/dist/node/lnsocket.wasm new file mode 100755 index 0000000000000000000000000000000000000000..59c3bb087696582dd46fd2f90dd7cc40a1d23794 GIT binary patch literal 144934 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

Hello World

+ + + + + diff --git a/node_modules/lnsocket/examples/websockets.js b/node_modules/lnsocket/examples/websockets.js new file mode 100644 index 0000000..205f065 --- /dev/null +++ b/node_modules/lnsocket/examples/websockets.js @@ -0,0 +1,16 @@ + +async function go() { + const LNSocket = await lnsocket_init() + const ln = LNSocket() + + ln.genkey() + //const their_init = await ln.connect_and_init("03f3c108ccd536b8526841f0a5c58212bb9e6584a1eb493080e7c1cc34f82dad71", "cln.jb55.com:443") + await ln.connect_and_init("03f3c108ccd536b8526841f0a5c58212bb9e6584a1eb493080e7c1cc34f82dad71", "ws://24.84.152.187:8324") + + const rune = "APaeUhcGPAMQwgV1Kn-hRRs5Bi4-D1nrfsHfCoTLl749MTAmbWV0aG9kPWdldGluZm8=" + const res = await ln.rpc({ method: "getinfo", rune }) + + document.body.innerHTML = `
${JSON.stringify(res.result, undefined, 2)}
` +} + +go() diff --git a/node_modules/lnsocket/export.h b/node_modules/lnsocket/export.h new file mode 100644 index 0000000..22167ed --- /dev/null +++ b/node_modules/lnsocket/export.h @@ -0,0 +1,12 @@ + +#ifndef LNSOCKET_COMMON_H +#define LNSOCKET_COMMON_H + +#ifdef __EMSCRIPTEN__ + #include + #define EXPORT EMSCRIPTEN_KEEPALIVE +#else + #define EXPORT +#endif + +#endif diff --git a/node_modules/lnsocket/go/go.mod b/node_modules/lnsocket/go/go.mod new file mode 100644 index 0000000..69a5269 --- /dev/null +++ b/node_modules/lnsocket/go/go.mod @@ -0,0 +1,37 @@ +module github.com/jb55/lnsocket/go + +require ( + github.com/btcsuite/btcd v0.22.0-beta.0.20211005184431-e3449998be39 + github.com/lightningnetwork/lnd v0.14.1-beta +) + +require ( + github.com/aead/siphash v1.0.1 // indirect + github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect + github.com/btcsuite/btcutil v1.0.3-0.20210527170813-e2ba6805a890 // indirect + github.com/btcsuite/btcutil/psbt v1.0.3-0.20210527170813-e2ba6805a890 // indirect + github.com/btcsuite/btcwallet v0.13.0 // indirect + github.com/btcsuite/btcwallet/wallet/txauthor v1.1.0 // indirect + github.com/btcsuite/btcwallet/wallet/txrules v1.1.0 // indirect + github.com/btcsuite/btcwallet/wallet/txsizes v1.1.0 // indirect + github.com/btcsuite/btcwallet/walletdb v1.3.6-0.20210803004036-eebed51155ec // indirect + github.com/btcsuite/btcwallet/wtxmgr v1.3.1-0.20210822222949-9b5a201c344c // indirect + github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd // indirect + github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/decred/dcrd/lru v1.0.0 // indirect + github.com/go-errors/errors v1.0.1 // indirect + github.com/kkdai/bstream v1.0.0 // indirect + github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf // indirect + github.com/lightninglabs/neutrino v0.13.0 // indirect + github.com/lightningnetwork/lnd/clock v1.1.0 // indirect + github.com/lightningnetwork/lnd/queue v1.1.0 // indirect + github.com/lightningnetwork/lnd/ticker v1.1.0 // indirect + github.com/miekg/dns v1.1.43 // indirect + golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect + golang.org/x/net v0.0.0-20210913180222-943fd674d43e // indirect + golang.org/x/sys v0.0.0-20210915083310-ed5796bab164 // indirect + golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect +) + +go 1.17 diff --git a/node_modules/lnsocket/go/go.sum b/node_modules/lnsocket/go/go.sum new file mode 100644 index 0000000..f95817f --- /dev/null +++ b/node_modules/lnsocket/go/go.sum @@ -0,0 +1,1009 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +git.schwanenlied.me/yawning/bsaes.git v0.0.0-20180720073208-c0276d75487e/go.mod h1:BWqTsj8PgcPriQJGl7el20J/7TuT1d/hSyFDXMEpoEo= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/NebulousLabs/fastrand v0.0.0-20181203155948-6fb6489aac4e/go.mod h1:Bdzq+51GR4/0DIhaICZEOm+OHvXGwwB2trKZ8B4Y6eQ= +github.com/NebulousLabs/go-upnp v0.0.0-20180202185039-29b680b06c82/go.mod h1:GbuBk21JqF+driLX3XtJYNZjGa45YDoa9IqCTzNSfEc= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/Yawning/aez v0.0.0-20180114000226-4dad034d9db2/go.mod h1:9pIqrY6SXNL8vjRQE5Hd/OL5GyK/9MrGUWs87z/eFfk= +github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY= +github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA= +github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= +github.com/andybalholm/brotli v1.0.3 h1:fpcw+r1N1h0Poc1F/pHbW40cUm/lMEQslZtCkBQ0UnM= +github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/btcsuite/btcd v0.0.0-20190629003639-c26ffa870fd8/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= +github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.21.0-beta.0.20201208033208-6bd4c64a54fa/go.mod h1:Sv4JPQ3/M+teHz9Bo5jBpkNcP0x6r7rdihlNL/7tTAs= +github.com/btcsuite/btcd v0.22.0-beta.0.20210803133449-f5a1fb9965e4/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= +github.com/btcsuite/btcd v0.22.0-beta.0.20211005184431-e3449998be39 h1:o6qacOzpKubr16y0RrE2fBauRZN1rDZ1YsE26ixCgQ0= +github.com/btcsuite/btcd v0.22.0-beta.0.20211005184431-e3449998be39/go.mod h1:3PH+KbvLFfzBTCevQenPiDedjGQGt6aa70dVjJDWGTA= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= +github.com/btcsuite/btcutil v1.0.3-0.20210527170813-e2ba6805a890 h1:9aGy5p7oXRUB4MCTmWm0+jzuh79GpjPIfv1leA5POD4= +github.com/btcsuite/btcutil v1.0.3-0.20210527170813-e2ba6805a890/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= +github.com/btcsuite/btcutil/psbt v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:LVveMu4VaNSkIRTZu2+ut0HDBRuYjqGocxDMNS1KuGQ= +github.com/btcsuite/btcutil/psbt v1.0.3-0.20210527170813-e2ba6805a890 h1:0xUNvvwJ7RjzBs4nCF+YrK28S5P/b4uHkpPxY1ovGY4= +github.com/btcsuite/btcutil/psbt v1.0.3-0.20210527170813-e2ba6805a890/go.mod h1:LVveMu4VaNSkIRTZu2+ut0HDBRuYjqGocxDMNS1KuGQ= +github.com/btcsuite/btcwallet v0.13.0 h1:gtLWwueRm27KQiHJpycybv3uMdK1eo87JexfTfzvEhk= +github.com/btcsuite/btcwallet v0.13.0/go.mod h1:iLN1lG1MW0eREm+SikmPO8AZPz5NglBTEK/ErqkjGpo= +github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0/go.mod h1:VufDts7bd/zs3GV13f/lXc/0lXrPnvxD/NvmpG/FEKU= +github.com/btcsuite/btcwallet/wallet/txauthor v1.1.0 h1:8pO0pvPX1rFRfRiol4oV6kX7dY5y4chPwhfVwUfvwtk= +github.com/btcsuite/btcwallet/wallet/txauthor v1.1.0/go.mod h1:ktYuJyumYtwG+QQ832Q+kqvxWJRAei3Nqs5qhSn4nww= +github.com/btcsuite/btcwallet/wallet/txrules v1.0.0/go.mod h1:UwQE78yCerZ313EXZwEiu3jNAtfXj2n2+c8RWiE/WNA= +github.com/btcsuite/btcwallet/wallet/txrules v1.1.0 h1:Vg8G8zhNVjaCdwJg2QOmLoWn4RTP7K0J9xlwY8CJnLY= +github.com/btcsuite/btcwallet/wallet/txrules v1.1.0/go.mod h1:Zn9UTqpiTH+HOd5BLzSBzULzlOPmcoeyQIA0cp0WbQQ= +github.com/btcsuite/btcwallet/wallet/txsizes v1.0.0/go.mod h1:pauEU8UuMFiThe5PB3EO+gO5kx87Me5NvdQDsTuq6cs= +github.com/btcsuite/btcwallet/wallet/txsizes v1.1.0 h1:wZnOolEAeNOHzHTnznw/wQv+j35ftCIokNrnOTOU5o8= +github.com/btcsuite/btcwallet/wallet/txsizes v1.1.0/go.mod h1:pauEU8UuMFiThe5PB3EO+gO5kx87Me5NvdQDsTuq6cs= +github.com/btcsuite/btcwallet/walletdb v1.3.4/go.mod h1:oJDxAEUHVtnmIIBaa22wSBPTVcs6hUp5NKWmI8xDwwU= +github.com/btcsuite/btcwallet/walletdb v1.3.5/go.mod h1:oJDxAEUHVtnmIIBaa22wSBPTVcs6hUp5NKWmI8xDwwU= +github.com/btcsuite/btcwallet/walletdb v1.3.6-0.20210803004036-eebed51155ec h1:zcAU3Ij8SmqaE+ITtS76fua2Niq7DRNp46sJRhi8PiI= +github.com/btcsuite/btcwallet/walletdb v1.3.6-0.20210803004036-eebed51155ec/go.mod h1:oJDxAEUHVtnmIIBaa22wSBPTVcs6hUp5NKWmI8xDwwU= +github.com/btcsuite/btcwallet/wtxmgr v1.3.0/go.mod h1:awQsh1n/0ZrEQ+JZgWvHeo153ubzEisf/FyNtwI0dDk= +github.com/btcsuite/btcwallet/wtxmgr v1.3.1-0.20210822222949-9b5a201c344c h1:owWPexGfK4eSK4/Zy+XK2lET5qsnW7FRAc8OCOdD0Fg= +github.com/btcsuite/btcwallet/wtxmgr v1.3.1-0.20210822222949-9b5a201c344c/go.mod h1:UM38ixX8VwJ9qey4umf//0H3ndn5kSImFZ46V54Nd5Q= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/golangcrypto v0.0.0-20150304025918-53f62d9b43e8/go.mod h1:tYvUd8KLhm/oXvUeSEs2VlLghFjQt9+ZaF9ghH0JNjc= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0 h1:Tvd0BfvqX9o823q1j2UZ/epQo09eJh6dTcRp79ilIN4= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/snappy-go v1.0.0 h1:ZxaA6lo2EpxGddsA8JwWOcxlzRybb444sgmeJQMJGQE= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= +github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= +github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= +github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= +github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+cbHpyrpLDmnN1HqhBfnX7WDiW7eG2c= +github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/lru v1.0.0 h1:Kbsb1SFDsIlaupWPwsPp+dkxiBY1frcS07PCPgotKz8= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q= +github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo= +github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= +github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fergusstrange/embedded-postgres v1.10.0 h1:YnwF6xAQYmKLAXXrrRx4rHDLih47YJwVPvg8jeKfdNg= +github.com/fergusstrange/embedded-postgres v1.10.0/go.mod h1:a008U8/Rws5FtIOTGYDYa7beVWsT3qVKyqExqYYjL+c= +github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c= +github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/frankban/quicktest v1.2.2/go.mod h1:Qh/WofXFeiAFII1aEBu529AtJo6Zg2VHscnEsbBnJ20= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= +github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= +github.com/go-openapi/strfmt v0.19.5/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v0.0.0-20210429001901-424d2337a529/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= +github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.2.1-0.20190312032427-6f77996f0c42/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.5.0/go.mod h1:r1hZAcvfFXuYmcKyCJI9wlyOPIZUJl6FCB8Cpca/NLE= +github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= +github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= +github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= +github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= +github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= +github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= +github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= +github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= +github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= +github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= +github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= +github.com/jackc/pgconn v1.10.0 h1:4EYhlDVEMsJ30nNj0mmgwIUXoq7e9sMJrVC2ED6QlCU= +github.com/jackc/pgconn v1.10.0/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= +github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= +github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= +github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= +github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= +github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A= +github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= +github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= +github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= +github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= +github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= +github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.1.1 h1:7PQ/4gLoqnl87ZxL7xjO0DR5gYuviDCZxQJsUlFW1eI= +github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= +github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= +github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= +github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= +github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= +github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= +github.com/jackc/pgtype v1.8.1 h1:9k0IXtdJXHJbyAWQgbWr1lU+MEhPXZz6RIXxfR5oxXs= +github.com/jackc/pgtype v1.8.1/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= +github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= +github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= +github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= +github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= +github.com/jackc/pgx/v4 v4.13.0 h1:JCjhT5vmhMAf/YwBHLvrBn4OGdIQBiFG6ym8Zmdx570= +github.com/jackc/pgx/v4 v4.13.0/go.mod h1:9P4X524sErlaxj0XSGZk7s+LD0eOyu1ZDUrrpznYDF0= +github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= +github.com/jackpal/go-nat-pmp v0.0.0-20170405195558-28a68d0c24ad/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jedib0t/go-pretty v4.3.0+incompatible/go.mod h1:XemHduiw8R651AF9Pt4FwCTKeG3oo7hrHJAoznj9nag= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= +github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI= +github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/juju/clock v0.0.0-20190205081909-9c5c9712527c/go.mod h1:nD0vlnrUjcjJhqN5WuCWZyzfd5AHZAC9/ajvbSx69xA= +github.com/juju/errors v0.0.0-20190806202954-0232dcc7464d/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q= +github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= +github.com/juju/retry v0.0.0-20180821225755-9058e192b216/go.mod h1:OohPQGsr4pnxwD5YljhQ+TZnuVRYpa5irjugL1Yuif4= +github.com/juju/testing v0.0.0-20190723135506-ce30eb24acd2/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA= +github.com/juju/utils v0.0.0-20180820210520-bf9cc5bdd62d/go.mod h1:6/KLg8Wz/y2KVGWEpkK9vMNGkOnu4k/cqs8Z1fKjTOk= +github.com/juju/version v0.0.0-20180108022336-b64dbd566305/go.mod h1:kE8gK5X0CImdr7qpSKl3xB2PmpySSmfj7zVbkZFs81U= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/kkdai/bstream v0.0.0-20181106074824-b3251f7901ec/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/kkdai/bstream v1.0.0 h1:Se5gHwgp2VT2uHfDrkbbgbgEvV9cimLELwrPJctSjg8= +github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+NVZZA= +github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/pgzip v1.2.4/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= +github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= +github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.3 h1:v9QZf2Sn6AmjXtQeFpdoq/eaNtYP6IN+7lcrygsIAtg= +github.com/lib/pq v1.10.3/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf h1:HZKvJUHlcXI/f/O0Avg7t8sqkPo78HFzjmeYFl6DPnc= +github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf/go.mod h1:vxmQPeIQxPf6Jf9rM8R+B4rKBqLA2AjttNxkFBL2Plk= +github.com/lightninglabs/neutrino v0.12.1/go.mod h1:GlKninWpRBbL7b8G0oQ36/8downfnFwKsr0hbRA6E/E= +github.com/lightninglabs/neutrino v0.13.0 h1:j3PKWEJCwqwMn/qLASz2j0IuCF6AumS9DaM0i0pM/nY= +github.com/lightninglabs/neutrino v0.13.0/go.mod h1:GlKninWpRBbL7b8G0oQ36/8downfnFwKsr0hbRA6E/E= +github.com/lightninglabs/protobuf-hex-display v1.4.3-hex-display/go.mod h1:2oKOBU042GKFHrdbgGiKax4xVrFiZu51lhacUZQ9MnE= +github.com/lightningnetwork/lightning-onion v1.0.2-0.20210520211913-522b799e65b1 h1:h1BsjPzWea790mAXISoiT/qr0JRcixTCDNLmjsDThSw= +github.com/lightningnetwork/lightning-onion v1.0.2-0.20210520211913-522b799e65b1/go.mod h1:rigfi6Af/KqsF7Za0hOgcyq2PNH4AN70AaMRxcJkff4= +github.com/lightningnetwork/lnd v0.14.1-beta h1:v9hOlJ1xYivYQ634Nt71up5QDh8mXVpYh4MXUbbWTRw= +github.com/lightningnetwork/lnd v0.14.1-beta/go.mod h1:o7zDwjZXm/bPP48qjwsqnZvvITyQl+fUv6UVoV4o+J8= +github.com/lightningnetwork/lnd/cert v1.1.0/go.mod h1:3MWXVLLPI0Mg0XETm9fT4N9Vyy/8qQLmaM5589bEggM= +github.com/lightningnetwork/lnd/clock v1.0.1/go.mod h1:KnQudQ6w0IAMZi1SgvecLZQZ43ra2vpDNj7H/aasemg= +github.com/lightningnetwork/lnd/clock v1.1.0 h1:/yfVAwtPmdx45aQBoXQImeY7sOIEr7IXlImRMBOZ7GQ= +github.com/lightningnetwork/lnd/clock v1.1.0/go.mod h1:KnQudQ6w0IAMZi1SgvecLZQZ43ra2vpDNj7H/aasemg= +github.com/lightningnetwork/lnd/healthcheck v1.0.0/go.mod h1:u92p1JGFJNMSkMvztKEwmt1P3TRnLeJBXZ3M85xkU1E= +github.com/lightningnetwork/lnd/healthcheck v1.2.0 h1:00bkNn+hGJM9j3Ht+ulf8YNcSx1HEYSDv5pf4HB1/uQ= +github.com/lightningnetwork/lnd/healthcheck v1.2.0/go.mod h1:WSz3lsUjErJQZ3gb+zW32nM3WIHNiZ3A40GVoaQY5wU= +github.com/lightningnetwork/lnd/kvdb v1.2.1 h1:QevYLPh6bh1SLIvlUaPbrpX/YMKzSPBfmGVvn2i8IlU= +github.com/lightningnetwork/lnd/kvdb v1.2.1/go.mod h1:x+IpsuDynubjokUofavLXroeGfS/WrqUXXTK6vN/gp4= +github.com/lightningnetwork/lnd/queue v1.0.1/go.mod h1:vaQwexir73flPW43Mrm7JOgJHmcEFBWWSl9HlyASoms= +github.com/lightningnetwork/lnd/queue v1.1.0 h1:YpCJjlIvVxN/R7ww2aNiY8ex7U2fucZDLJ67tI3HFx8= +github.com/lightningnetwork/lnd/queue v1.1.0/go.mod h1:YTkTVZCxz8tAYreH27EO3s8572ODumWrNdYW2E/YKxg= +github.com/lightningnetwork/lnd/ticker v1.0.0/go.mod h1:iaLXJiVgI1sPANIF2qYYUJXjoksPNvGNYowB8aRbpX0= +github.com/lightningnetwork/lnd/ticker v1.1.0 h1:ShoBiRP3pIxZHaETndfQ5kEe+S4NdAY1hiX7YbZ4QE4= +github.com/lightningnetwork/lnd/ticker v1.1.0/go.mod h1:ubqbSVCn6RlE0LazXuBr7/Zi6QT0uQo++OgIRBxQUrk= +github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796 h1:sjOGyegMIhvgfq5oaue6Td+hxZuf3tDC8lAPrFldqFw= +github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796/go.mod h1:3p7ZTf9V1sNPI5H8P3NkTFF4LuwMdPl2DodF60qAKqY= +github.com/ltcsuite/ltcutil v0.0.0-20181217130922-17f3b04680b6/go.mod h1:8Vg/LTOO0KYa/vlHWJ6XZAevPQThGH5sufO0Hrou/lA= +github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mholt/archiver/v3 v3.5.0 h1:nE8gZIrw66cu4osS/U7UW7YDuGMHssxKutU8IfWxwWE= +github.com/mholt/archiver/v3 v3.5.0/go.mod h1:qqTTPUK/HZPFgFQ/TJ3BzvTpF/dPtFVJXdQbCmeMxwc= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg= +github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= +github.com/nwaples/rardecode v1.1.2 h1:Cj0yZY6T1Zx1R7AhTbyGSALm44/Mmq+BAPc4B/p/d3M= +github.com/nwaples/rardecode v1.1.2/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pierrec/lz4/v4 v4.0.3/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pierrec/lz4/v4 v4.1.8 h1:ieHkV+i2BRzngO4Wd/3HGowuZStgq6QkPsD1eolNAO4= +github.com/pierrec/lz4/v4 v4.1.8/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= +github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= +github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= +github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= +github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4dN7GR16kFc5fp3d1RIYzJW5onx8Ybykw2YQFA= +github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tv42/zbase32 v0.0.0-20160707012821-501572607d02/go.mod h1:tHlrkM198S068ZqfrO6S8HsoJq2bF3ETfTL+kt4tInY= +github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= +github.com/ulikunitz/xz v0.5.7/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8= +github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.5-0.20200615073812-232d8fc87f50/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= +go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= +go.etcd.io/etcd/api/v3 v3.5.0 h1:GsV3S+OfZEOCNXdtNkBSR7kgLobAa/SO6tCxRa0GAYw= +go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= +go.etcd.io/etcd/client/pkg/v3 v3.5.0 h1:2aQv6F436YnN7I4VbI8PPYrBhu+SmrTaADcf8Mi/6PU= +go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/v2 v2.305.0 h1:ftQ0nOOHMcbMS3KIaDQ0g5Qcd6bhaBrQT6b89DfwLTs= +go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= +go.etcd.io/etcd/client/v3 v3.5.0 h1:62Eh0XOro+rDwkrypAGDfgmNh5Joq+z+W9HZdlXMzek= +go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= +go.etcd.io/etcd/pkg/v3 v3.5.0 h1:ntrg6vvKRW26JRmHTE0iNlDgYK6JX3hg/4cD62X0ixk= +go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= +go.etcd.io/etcd/raft/v3 v3.5.0 h1:kw2TmO3yFTgE+F0mdKkG7xMxkit2duBDa2Hu6D/HMlw= +go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= +go.etcd.io/etcd/server/v3 v3.5.0 h1:jk8D/lwGEDlQU9kZXUFMSANkE22Sg5+mW27ip8xcF9E= +go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= +go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opentelemetry.io/contrib v0.20.0 h1:ubFQUn0VCZ0gPwIoJfBJVpeBlyRMxu8Mm/huKWYd9p0= +go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0 h1:sO4WKdPAudZGKPcpZT4MJn6JaDmpyLrMPDGGyA1SttE= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= +go.opentelemetry.io/otel v0.20.0 h1:eaP0Fqu7SXHwvjiqDq83zImeehOHX8doTvU9AwXON8g= +go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= +go.opentelemetry.io/otel/exporters/otlp v0.20.0 h1:PTNgq9MRmQqqJY0REVbZFvwkYOA85vbdQU/nVfxDyqg= +go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= +go.opentelemetry.io/otel/metric v0.20.0 h1:4kzhXFP+btKm4jwxpjIqjs41A7MakRFUS86bqLHTIw8= +go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= +go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= +go.opentelemetry.io/otel/sdk v0.20.0 h1:JsxtGXd06J8jrnya7fdI/U/MR6yXA5DtbZy+qoHQlr8= +go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= +go.opentelemetry.io/otel/sdk/export/metric v0.20.0 h1:c5VRjxCXdQlx1HjzwGdQHzZaVI82b5EbBgOu2ljD92g= +go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE= +go.opentelemetry.io/otel/sdk/metric v0.20.0 h1:7ao1wpzHRVKf0OQ7GIxiQJA6X7DLX9o14gmVon7mMK8= +go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= +go.opentelemetry.io/otel/trace v0.20.0 h1:1DL6EXUdcg95gukhuRRvLDO/4X5THh/5dIV52lqtnbw= +go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= +go.opentelemetry.io/proto/otlp v0.7.0 h1:rwOQPCuKAKmwGKq2aVNnYIibI6wnV7EvzgfTCzcdGg8= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190206173232-65e2d4e15006/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210913180222-943fd674d43e h1:+b/22bPvDYt4NPDcy4xAGCmON713ONAWFeY3Z7I3tR8= +golang.org/x/net v0.0.0-20210913180222-943fd674d43e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20210615190721-d04028783cf1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210426080607-c94f62235c83/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210915083310-ed5796bab164 h1:7ZDGnxgHAMw7thfC5bEos0RDAccZKxioiWBhfIe+tvw= +golang.org/x/sys v0.0.0-20210915083310-ed5796bab164/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= +golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190201180003-4b09977fb922/go.mod h1:L3J43x8/uS+qIUoksaLKe6OS3nUKxOKuIFz1sl2/jx4= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced h1:c5geK1iMU3cDKtFrCVQIcjR3W+JOZMuhIyICMCTbtus= +google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= +google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v1 v1.0.1/go.mod h1:3NjfXwocQRYAPTq4/fzX+CwUhPRcR/azYRhj8G+LqMo= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= +gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/macaroon-bakery.v2 v2.0.1/go.mod h1:B4/T17l+ZWGwxFSZQmlBwp25x+og7OkhETfr3S9MbIA= +gopkg.in/macaroon.v2 v2.0.0/go.mod h1:+I6LnTMkm/uV5ew/0nsulNjL16SK4+C8yDmRUzHR17I= +gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= +gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= +gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/node_modules/lnsocket/go/lnsocket.go b/node_modules/lnsocket/go/lnsocket.go new file mode 100644 index 0000000..e21695a --- /dev/null +++ b/node_modules/lnsocket/go/lnsocket.go @@ -0,0 +1,190 @@ +package lnsocket + +import ( + "bytes" + "encoding/hex" + "fmt" + "io" + "net" + + "github.com/btcsuite/btcd/btcec" + "github.com/lightningnetwork/lnd/brontide" + "github.com/lightningnetwork/lnd/keychain" + "github.com/lightningnetwork/lnd/lnwire" + "github.com/lightningnetwork/lnd/tor" +) + +const ( + COMMANDO_CMD = 0x4c4f + COMMANDO_REPLY_CONTINUES = 0x594b + COMMANDO_REPLY_TERM = 0x594d +) + +type CommandoMsg struct { + Rune string + Method string + Params string + RequestId uint64 +} + +func NewCommandoMsg(token string, method string, params string) CommandoMsg { + return CommandoMsg{ + Rune: token, + Method: method, + Params: params, + } +} + +// A compile time check to ensure Init implements the lnwire.Message +// interface. + +func (msg *CommandoMsg) MsgType() lnwire.MessageType { + return COMMANDO_CMD +} + +func (msg *CommandoMsg) Decode(reader io.Reader, size uint32) error { + return fmt.Errorf("implememt commando decode?") +} + +func (msg *CommandoMsg) Encode(buf *bytes.Buffer, pver uint32) error { + if err := lnwire.WriteUint64(buf, msg.RequestId); err != nil { + return err + } + + buf.WriteString("{\"method\": \"") + buf.WriteString(msg.Method) + buf.WriteString("\",\"params\":") + buf.WriteString(msg.Params) + buf.WriteString(",\"rune\":\"") + buf.WriteString(msg.Rune) + buf.WriteString("\"}") + + return nil +} + +type LNSocket struct { + Conn net.Conn + PrivKeyECDH *keychain.PrivKeyECDH +} + +func (ln *LNSocket) GenKey() { + remotePriv, _ := btcec.NewPrivateKey(btcec.S256()) + ln.PrivKeyECDH = &keychain.PrivKeyECDH{PrivKey: remotePriv} +} + +func (ln *LNSocket) ConnectWith(netAddr *lnwire.NetAddress) error { + conn, err := brontide.Dial(ln.PrivKeyECDH, netAddr, tor.DefaultConnTimeout, net.DialTimeout) + ln.Conn = conn + return err +} + +func (ln *LNSocket) Connect(hostname string, pubkey string) error { + addr, err := net.ResolveTCPAddr("tcp", hostname) + if err != nil { + return err + } + bytes, err := hex.DecodeString(pubkey) + if err != nil { + return err + } + key, err := btcec.ParsePubKey(bytes, btcec.S256()) + if err != nil { + return err + } + + netAddr := &lnwire.NetAddress{ + IdentityKey: key, + Address: addr, + } + + return ln.ConnectWith(netAddr) +} + +func (ln *LNSocket) PerformInit() error { + no_features := lnwire.NewRawFeatureVector() + init_reply_msg := lnwire.NewInitMessage(no_features, no_features) + + var b bytes.Buffer + _, err := lnwire.WriteMessage(&b, init_reply_msg, 0) + if err != nil { + return err + } + _, err = ln.Conn.Write(b.Bytes()) + + // receive the first init msg + _, _, err = ln.Recv() + if err != nil { + return err + } + + return nil +} + +func (ln *LNSocket) Rpc(token string, method string, params string) (string, error) { + commando_msg := NewCommandoMsg(token, method, params) + + var b bytes.Buffer + _, err := lnwire.WriteMessage(&b, &commando_msg, 0) + if err != nil { + return "", err + } + + bs := b.Bytes() + _, err = ln.Conn.Write(bs) + if err != nil { + return "", err + } + + return ln.rpcReadAll() +} + +func ParseMsgType(bytes []byte) uint16 { + return uint16(bytes[0])<<8 | uint16(bytes[1]) +} + +func (ln *LNSocket) Recv() (uint16, []byte, error) { + res := make([]byte, 65535) + n, err := ln.Conn.Read(res) + if err != nil { + return 0, nil, err + } + if n < 2 { + return 0, nil, fmt.Errorf("read too small") + } + res = res[:n] + msgtype := ParseMsgType(res) + return msgtype, res[2:], nil +} + +func (ln *LNSocket) rpcReadAll() (string, error) { + all := []byte{} + for { + msgtype, res, err := ln.Recv() + if err != nil { + return "", err + } + switch msgtype { + case COMMANDO_REPLY_CONTINUES: + all = append(all, res[8:]...) + continue + case COMMANDO_REPLY_TERM: + all = append(all, res[8:]...) + return string(all), nil + default: + continue + } + } +} + +func (ln *LNSocket) Disconnect() { + ln.Conn.Close() +} + +func (ln *LNSocket) ConnectAndInit(hostname string, pubkey string) error { + err := ln.Connect(hostname, pubkey) + if err != nil { + return err + } + + return ln.PerformInit() +} diff --git a/node_modules/lnsocket/handshake.c b/node_modules/lnsocket/handshake.c new file mode 100644 index 0000000..7cd46fb --- /dev/null +++ b/node_modules/lnsocket/handshake.c @@ -0,0 +1,481 @@ +/* Copyright Rusty Russell (Blockstream) 2015. + William Casarin 2022 + +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. +*/ + +#include "compiler.h" +#include "endian.h" +#include "error.h" +#include "handshake.h" +#include "hkdf.h" +#include "lnsocket_internal.h" +#include "sha256.h" +#include +#include +#include +#include +#include "export.h" + +struct keypair generate_key(secp256k1_context *ctx) +{ + struct keypair k; + + do { + randombytes_buf(k.priv.secret.data, sizeof(k.priv.secret.data)); + } while (!secp256k1_ec_pubkey_create(ctx, &k.pub.pubkey, + k.priv.secret.data)); + return k; +} + + +/* h = SHA-256(h || data) */ +static void sha_mix_in(struct sha256 *h, const void *data, size_t len) +{ + struct sha256_ctx shactx; + + sha256_init(&shactx); + sha256_update(&shactx, h->u.u8, sizeof(*h)); + sha256_update(&shactx, data, len); + sha256_done(&shactx, h); +} + +/* h = SHA-256(h || pub.serializeCompressed()) */ +static void sha_mix_in_key(secp256k1_context *ctx, struct sha256 *h, + const struct pubkey *key) +{ + u8 der[PUBKEY_CMPR_LEN]; + size_t len = sizeof(der); + + secp256k1_ec_pubkey_serialize(ctx, der, &len, &key->pubkey, + SECP256K1_EC_COMPRESSED); + assert(len == sizeof(der)); + sha_mix_in(h, der, sizeof(der)); +} + + +/* BOLT #8: + * * `encryptWithAD(k, n, ad, plaintext)`: outputs `encrypt(k, n, ad, + * plaintext)` + * * Where `encrypt` is an evaluation of `ChaCha20-Poly1305` (IETF + * variant) with the passed arguments, with nonce `n` + */ +static void encrypt_ad(const struct secret *k, u64 nonce, + const void *additional_data, size_t additional_data_len, + const void *plaintext, size_t plaintext_len, + void *output, size_t outputlen) +{ + unsigned char npub[crypto_aead_chacha20poly1305_ietf_NPUBBYTES]; + unsigned long long clen; + int ret; + + assert(outputlen == plaintext_len + crypto_aead_chacha20poly1305_ietf_ABYTES); + le64_nonce(npub, nonce); + BUILD_ASSERT(sizeof(*k) == crypto_aead_chacha20poly1305_ietf_KEYBYTES); + + ret = crypto_aead_chacha20poly1305_ietf_encrypt( + output, &clen, memcheck(plaintext, plaintext_len), + plaintext_len, additional_data, additional_data_len, + NULL, npub, k->data); + + assert(ret == 0); + assert(clen == plaintext_len + crypto_aead_chacha20poly1305_ietf_ABYTES); +} + +static inline void check_act_one(const struct act_one *act1) +{ + /* BOLT #8: + * + * : 1 byte for the handshake version, 33 bytes for the compressed + * ephemeral public key of the initiator, and 16 bytes for the + * `poly1305` tag. + */ + BUILD_ASSERT(sizeof(act1->v) == 1); + BUILD_ASSERT(sizeof(act1->pubkey) == 33); + BUILD_ASSERT(sizeof(act1->tag) == 16); +} + +/* +static void print_hex(u8 *bytes, int len) { + int i; + for (i = 0; i < len; ++i) { + printf("%02x", bytes[i]); + } +} +*/ + +void new_handshake(secp256k1_context *secp, struct handshake *handshake, + const struct pubkey *responder_id) +{ + /* BOLT #8: + * + * Before the start of Act One, both sides initialize their + * per-sessions state as follows: + * + * 1. `h = SHA-256(protocolName)` + * * where `protocolName = "Noise_XK_secp256k1_ChaChaPoly_SHA256"` + * encoded as an ASCII string + */ + sha256(&handshake->h, "Noise_XK_secp256k1_ChaChaPoly_SHA256", + strlen("Noise_XK_secp256k1_ChaChaPoly_SHA256")); + + /* BOLT #8: + * + * 2. `ck = h` + */ + BUILD_ASSERT(sizeof(handshake->h) == sizeof(handshake->ck)); + memcpy(&handshake->ck, &handshake->h, sizeof(handshake->ck)); + + /* BOLT #8: + * + * 3. `h = SHA-256(h || prologue)` + * * where `prologue` is the ASCII string: `lightning` + */ + sha_mix_in(&handshake->h, "lightning", strlen("lightning")); + + /* BOLT #8: + * + * As a concluding step, both sides mix the responder's public key + * into the handshake digest: + * + * * The initiating node mixes in the responding node's static public + * key serialized in Bitcoin's compressed format: + * * `h = SHA-256(h || rs.pub.serializeCompressed())` + * + * * The responding node mixes in their local static public key + * serialized in Bitcoin's compressed format: + * * `h = SHA-256(h || ls.pub.serializeCompressed())` + */ + sha_mix_in_key(secp, &handshake->h, responder_id); +} + +/* +static void print_act_two(struct act_two *two) +{ + printf("ACT2 v %d pubkey ", two->v); + print_hex(two->pubkey, sizeof(two->pubkey)); + printf(" tag "); + print_hex(two->tag, sizeof(two->tag)); + printf("\n"); +} +*/ + +/* BOLT #8: + * * `decryptWithAD(k, n, ad, ciphertext)`: outputs `decrypt(k, n, ad, + * ciphertext)` + * * Where `decrypt` is an evaluation of `ChaCha20-Poly1305` (IETF + * variant) with the passed arguments, with nonce `n` + */ +static int decrypt(const struct secret *k, u64 nonce, + const void *additional_data, size_t additional_data_len, + const void *ciphertext, size_t ciphertext_len, + void *output, size_t outputlen) +{ + unsigned char npub[crypto_aead_chacha20poly1305_ietf_NPUBBYTES]; + unsigned long long mlen; + + assert(outputlen == ciphertext_len - crypto_aead_chacha20poly1305_ietf_ABYTES); + + le64_nonce(npub, nonce); + BUILD_ASSERT(sizeof(*k) == crypto_aead_chacha20poly1305_ietf_KEYBYTES); + if (crypto_aead_chacha20poly1305_ietf_decrypt(output, &mlen, NULL, + memcheck(ciphertext, ciphertext_len), + ciphertext_len, + additional_data, additional_data_len, + npub, k->data) != 0) { + return 0; + } + + assert(mlen == ciphertext_len - crypto_aead_chacha20poly1305_ietf_ABYTES); + return 1; +} + +static int handshake_success(struct lnsocket *ln, struct handshake *h) +{ + struct crypto_state *cs = &ln->crypto_state; + + /* BOLT #8: + * + * 9. `rk, sk = HKDF(ck, zero)` + * * where `zero` is a zero-length plaintext, `rk` is the key to + * be used by the responder to decrypt the messages sent by the + * initiator, and `sk` is the key to be used by the responder + * to encrypt messages to the initiator + * + * * The final encryption keys, to be used for sending and + * receiving messages for the duration of the session, are + * generated. + */ + if (h->side == RESPONDER) + hkdf_two_keys(&cs->rk, &cs->sk, &h->ck, NULL); + else + hkdf_two_keys(&cs->sk, &cs->rk, &h->ck, NULL); + + cs->rn = cs->sn = 0; + cs->r_ck = cs->s_ck = h->ck; + + return 1; +} + +static struct act_three *build_act_three(struct lnsocket *ln) +{ + u8 spub[PUBKEY_CMPR_LEN]; + size_t len = sizeof(spub); + struct handshake *h = &ln->handshake; + + /* BOLT #8: + * 1. `c = encryptWithAD(temp_k2, 1, h, s.pub.serializeCompressed())` + * * where `s` is the static public key of the initiator + */ + secp256k1_ec_pubkey_serialize(ln->secp, spub, &len, + &ln->key.pub.pubkey, + SECP256K1_EC_COMPRESSED); + encrypt_ad(&h->temp_k, 1, &h->h, sizeof(h->h), spub, sizeof(spub), + h->act3.ciphertext, sizeof(h->act3.ciphertext)); + + /* BOLT #8: + * 2. `h = SHA-256(h || c)` + */ + sha_mix_in(&h->h, h->act3.ciphertext, sizeof(h->act3.ciphertext)); + + /* BOLT #8: + * + * 3. `se = ECDH(s.priv, re)` + * * where `re` is the ephemeral public key of the responder + */ + if (!secp256k1_ecdh(ln->secp, h->ss.data, &h->re.pubkey, + ln->key.priv.secret.data, NULL, NULL)) { + note_error(&ln->errs, "act3 ecdh handshake failed"); + return NULL; + } + + /* BOLT #8: + * + * 4. `ck, temp_k3 = HKDF(ck, se)` + * * The final intermediate shared secret is mixed into the running chaining key. + */ + hkdf_two_keys(&h->ck, &h->temp_k, &h->ck, &h->ss); + + /* BOLT #8: + * + * 5. `t = encryptWithAD(temp_k3, 0, h, zero)` + * * where `zero` is a zero-length plaintext + * + */ + encrypt_ad(&h->temp_k, 0, &h->h, sizeof(h->h), NULL, 0, + h->act3.tag, sizeof(h->act3.tag)); + + /* BOLT #8: + * + * 8. Send `m = 0 || c || t` over the network buffer. + * + */ + h->act3.v = 0; + + handshake_success(ln, &ln->handshake); + + return &h->act3; +} + + +// act2: handle the response to the message sent in act1 +struct act_three* EXPORT lnsocket_act_two(struct lnsocket *ln, struct act_two *act2) +{ + struct handshake *h = &ln->handshake; + + //print_act_two(act2); + + /* BOLT #8: + * + * 3. If `v` is an unrecognized handshake version, then the responder + * MUST abort the connection attempt. + */ + if (act2->v != 0) { + note_error(&ln->errs, "unrecognized handshake version"); + return NULL; + } + + //print_hex() + + /* BOLT #8: + * + * * The raw bytes of the remote party's ephemeral public key + * (`re`) are to be deserialized into a point on the curve using + * affine coordinates as encoded by the key's serialized + * composed format. + */ + if (secp256k1_ec_pubkey_parse(ln->secp, &h->re.pubkey, act2->pubkey, + sizeof(act2->pubkey)) != 1) { + note_error(&ln->errs, "failed to parse remote pubkey"); + return NULL; + } + + /* BOLT #8: + * + * 4. `h = SHA-256(h || re.serializeCompressed())` + */ + sha_mix_in_key(ln->secp, &h->h, &h->re); + + /* BOLT #8: + * + * 5. `es = ECDH(s.priv, re)` + */ + if (!secp256k1_ecdh(ln->secp, h->ss.data, &h->re.pubkey, + h->e.priv.secret.data, NULL, NULL)) { + note_error(&ln->errs, "act2 ecdh failed"); + return NULL; + } + + /* BOLT #8: + * + * 6. `ck, temp_k2 = HKDF(ck, ee)` + * * A new temporary encryption key is generated, which is + * used to generate the authenticating MAC. + */ + hkdf_two_keys(&h->ck, &h->temp_k, &h->ck, &h->ss); + + /* BOLT #8: + * + * 7. `p = decryptWithAD(temp_k2, 0, h, c)` + * * If the MAC check in this operation fails, then the initiator + * MUST terminate the connection without any further messages. + */ + if (!decrypt(&h->temp_k, 0, &h->h, sizeof(h->h), + act2->tag, sizeof(act2->tag), NULL, 0)) { + note_error(&ln->errs, "handshake decrypt failed"); + return NULL; + } + + /* BOLT #8: + * + * 8. `h = SHA-256(h || c)` + * * The received ciphertext is mixed into the handshake digest. + * This step serves to ensure the payload wasn't modified by a + * MITM. + */ + sha_mix_in(&h->h, act2->tag, sizeof(act2->tag)); + + return build_act_three(ln); +} + +// Prepare the very first message and send it the connected node +// Wait for a response in act2 +int act_one_initiator_prep(struct lnsocket *ln) +{ + struct handshake *h = &ln->handshake; + + h->e = generate_key(ln->secp); + + /* BOLT #8: + * + * 2. `h = SHA-256(h || e.pub.serializeCompressed())` + * * The newly generated ephemeral key is accumulated into the + * running handshake digest. + */ + sha_mix_in_key(ln->secp, &h->h, &h->e.pub); + + /* BOLT #8: + * + * 3. `es = ECDH(e.priv, rs)` + * * The initiator performs an ECDH between its newly generated ephemeral + * key and the remote node's static public key. + */ + if (!secp256k1_ecdh(ln->secp, h->ss.data, + &h->their_id.pubkey, h->e.priv.secret.data, + NULL, NULL)) { + return note_error(&ln->errs, "handshake failed, secp256k1_ecdh error"); + } + + /* BOLT #8: + * + * 4. `ck, temp_k1 = HKDF(ck, es)` + * * A new temporary encryption key is generated, which is + * used to generate the authenticating MAC. + */ + hkdf_two_keys(&h->ck, &h->temp_k, &h->ck, &h->ss); + + /* BOLT #8: + * 5. `c = encryptWithAD(temp_k1, 0, h, zero)` + * * where `zero` is a zero-length plaintext + */ + encrypt_ad(&h->temp_k, 0, &h->h, sizeof(h->h), NULL, 0, + h->act1.tag, sizeof(h->act1.tag)); + + /* BOLT #8: + * 6. `h = SHA-256(h || c)` + * * Finally, the generated ciphertext is accumulated into the + * authenticating handshake digest. + */ + sha_mix_in(&h->h, h->act1.tag, sizeof(h->act1.tag)); + + /* BOLT #8: + * + * 7. Send `m = 0 || e.pub.serializeCompressed() || c` to the responder over the network buffer. + */ + h->act1.v = 0; + size_t len = sizeof(h->act1.pubkey); + secp256k1_ec_pubkey_serialize(ln->secp, h->act1.pubkey, &len, + &h->e.pub.pubkey, + SECP256K1_EC_COMPRESSED); + + check_act_one(&h->act1); + + return 1; +} + +// act2: read the response to the message sent in act1 +static int act_two_initiator(struct lnsocket *ln, struct handshake *h) +{ + /* BOLT #8: + * + * 1. Read _exactly_ 50 bytes from the network buffer. + * + * 2. Parse the read message (`m`) into `v`, `re`, and `c`: + * * where `v` is the _first_ byte of `m`, `re` is the next 33 + * bytes of `m`, and `c` is the last 16 bytes of `m`. + */ + ssize_t size; + + if ((size = read(ln->socket, &h->act2, ACT_TWO_SIZE)) != ACT_TWO_SIZE) { + printf("read %ld bytes, expected %d\n", size, ACT_TWO_SIZE); + return note_error(&ln->errs, "%s", strerror(errno)); + } + + struct act_three *act3 = lnsocket_act_two(ln, &h->act2); + if (act3 == NULL) + return 0; + + if (write(ln->socket, act3, ACT_THREE_SIZE) != ACT_THREE_SIZE) { + return note_error(&ln->errs, "handshake failed on initial send"); + } + + return 1; +} + +int act_one_initiator(struct lnsocket *ln) +{ + if (!act_one_initiator_prep(ln)) + return 0; + + if (write(ln->socket, &ln->handshake.act1, ACT_ONE_SIZE) != ACT_ONE_SIZE) { + return note_error(&ln->errs, "handshake failed on initial send"); + } + + return act_two_initiator(ln, &ln->handshake); +} diff --git a/node_modules/lnsocket/handshake.h b/node_modules/lnsocket/handshake.h new file mode 100644 index 0000000..9c6a0f5 --- /dev/null +++ b/node_modules/lnsocket/handshake.h @@ -0,0 +1,147 @@ +/* Copyright Rusty Russell (Blockstream) 2015. + +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. +*/ + +#ifndef LNLINK_HANDSHAKE_H +#define LNLINK_HANDSHAKE_H + +#include "typedefs.h" +#include "sha256.h" +#include "crypto.h" + +#include + +#include +#include + +#define ACT_ONE_SIZE 50 +#define ACT_TWO_SIZE 50 +#define ACT_THREE_SIZE 66 + +enum bolt8_side { + INITIATOR, + RESPONDER +}; + +/* BOLT #8: + * + * Act One is sent from initiator to responder. During Act One, the + * initiator attempts to satisfy an implicit challenge by the responder. To + * complete this challenge, the initiator must know the static public key of + * the responder. + */ +struct act_one { + u8 v; + u8 pubkey[PUBKEY_CMPR_LEN]; + u8 tag[crypto_aead_chacha20poly1305_ietf_ABYTES]; +}; + +/* BOLT #8: + * + * Act Two is sent from the responder to the initiator. Act Two will + * _only_ take place if Act One was successful. Act One was successful if + * the responder was able to properly decrypt and check the MAC of the tag + * sent at the end of Act One. + */ +struct act_two { + u8 v; + u8 pubkey[PUBKEY_CMPR_LEN]; + u8 tag[crypto_aead_chacha20poly1305_ietf_ABYTES]; +}; + +/* BOLT #8: + * + * Act Three is the final phase in the authenticated key agreement described + * in this section. This act is sent from the initiator to the responder as a + * concluding step. Act Three is executed _if and only if_ Act Two was + * successful. During Act Three, the initiator transports its static public + * key to the responder encrypted with _strong_ forward secrecy, using the + * accumulated `HKDF` derived secret key at this point of the handshake. + */ +struct act_three { + u8 v; + u8 ciphertext[PUBKEY_CMPR_LEN + crypto_aead_chacha20poly1305_ietf_ABYTES]; + u8 tag[crypto_aead_chacha20poly1305_ietf_ABYTES]; +}; + +/* BOLT #8: + * + * Throughout the handshake process, each side maintains these variables: + * + * * `ck`: the **chaining key**. This value is the accumulated hash of all + * previous ECDH outputs. At the end of the handshake, `ck` is used to derive + * the encryption keys for Lightning messages. + * + * * `h`: the **handshake hash**. This value is the accumulated hash of _all_ + * handshake data that has been sent and received so far during the handshake + * process. + * + * * `temp_k1`, `temp_k2`, `temp_k3`: the **intermediate keys**. These are used to + * encrypt and decrypt the zero-length AEAD payloads at the end of each handshake + * message. + * + * * `e`: a party's **ephemeral keypair**. For each session, a node MUST generate a + * new ephemeral key with strong cryptographic randomness. + * + * * `s`: a party's **static keypair** (`ls` for local, `rs` for remote) + */ +struct handshake { + struct secret ck; + struct secret temp_k; + struct sha256 h; + struct keypair e; + struct secret ss; + + /* Used between the Acts */ + struct pubkey re; + struct act_one act1; + struct act_two act2; + struct act_three act3; + + /* Where is connection from/to */ + struct addrinfo addr; + + /* Who they are: set already if we're initiator. */ + struct pubkey their_id; + + /* Are we initiator or responder. */ + enum bolt8_side side; + + /* Function to call once handshake complete. */ + /* + struct io_plan *(*cb)(struct io_conn *conn, + const struct pubkey *their_id, + const struct wireaddr_internal *wireaddr, + struct crypto_state *cs, + void *cbarg); + void *cbarg; + */ +}; + +void new_handshake(secp256k1_context *secp, struct handshake *handshake, + const struct pubkey *responder_id); + +struct lnsocket; + +int act_one_initiator_prep(struct lnsocket *ln); +int act_one_initiator(struct lnsocket *ln); +struct keypair generate_key(secp256k1_context *ctx); + +#endif /* LNLINK_HANDSHAKE_H */ diff --git a/node_modules/lnsocket/hkdf.c b/node_modules/lnsocket/hkdf.c new file mode 100644 index 0000000..b044fd8 --- /dev/null +++ b/node_modules/lnsocket/hkdf.c @@ -0,0 +1,98 @@ +/* MIT (BSD) license */ + +#include "hmac.h" +#include "sha256.h" +#include +#include + +void hkdf_sha256(void *okm, size_t okm_size, + const void *s, size_t ssize, + const void *k, size_t ksize, + const void *info, size_t isize) +{ + struct hmac_sha256 prk, t; + struct hmac_sha256_ctx ctx; + unsigned char c; + + assert(okm_size < 255 * sizeof(t)); + + /* RFC 5869: + * + * 2.2. Step 1: Extract + * + * HKDF-Extract(salt, IKM) -> PRK + * + * Options: + * Hash a hash function; HashLen denotes the length of the + * hash function output in octets + * + * Inputs: + * salt optional salt value (a non-secret random value); + * if not provided, it is set to a string of HashLen zeros. + * IKM input keying material + * + * Output: + * PRK a pseudorandom key (of HashLen octets) + * + * The output PRK is calculated as follows: + * + * PRK = HMAC-Hash(salt, IKM) + */ + hmac_sha256(&prk, s, ssize, k, ksize); + + /* + * 2.3. Step 2: Expand + * + * HKDF-Expand(PRK, info, L) -> OKM + * + * Options: + * Hash a hash function; HashLen denotes the length of the + * hash function output in octets + * + * Inputs: + * PRK a pseudorandom key of at least HashLen octets + * (usually, the output from the extract step) + * info optional context and application specific information + * (can be a zero-length string) + * L length of output keying material in octets + * (<= 255*HashLen) + * + * Output: + * OKM output keying material (of L octets) + * + * The output OKM is calculated as follows: + * + * N = ceil(L/HashLen) + * T = T(1) | T(2) | T(3) | ... | T(N) + * OKM = first L octets of T + * + * where: + * T(0) = empty string (zero length) + * T(1) = HMAC-Hash(PRK, T(0) | info | 0x01) + * T(2) = HMAC-Hash(PRK, T(1) | info | 0x02) + * T(3) = HMAC-Hash(PRK, T(2) | info | 0x03) + * ... + * + * (where the constant concatenated to the end of each T(n) is a + * single octet.) + */ + c = 1; + hmac_sha256_init(&ctx, &prk, sizeof(prk)); + hmac_sha256_update(&ctx, info, isize); + hmac_sha256_update(&ctx, &c, 1); + hmac_sha256_done(&ctx, &t); + + while (okm_size > sizeof(t)) { + memcpy(okm, &t, sizeof(t)); + okm = (char *)okm + sizeof(t); + okm_size -= sizeof(t); + + c++; + hmac_sha256_init(&ctx, &prk, sizeof(prk)); + hmac_sha256_update(&ctx, &t, sizeof(t)); + hmac_sha256_update(&ctx, info, isize); + hmac_sha256_update(&ctx, &c, 1); + hmac_sha256_done(&ctx, &t); + } + memcpy(okm, &t, okm_size); +} diff --git a/node_modules/lnsocket/hkdf.h b/node_modules/lnsocket/hkdf.h new file mode 100644 index 0000000..b6da5fa --- /dev/null +++ b/node_modules/lnsocket/hkdf.h @@ -0,0 +1,22 @@ + +#ifndef CCAN_CRYPTO_HKDF_SHA256_H +#define CCAN_CRYPTO_HKDF_SHA256_H +/* BSD-MIT - see LICENSE file for details */ +#include + +/** + * hkdf_sha256 - generate a derived key + * @okm: where to output the key + * @okm_size: the number of bytes pointed to by @okm (must be less than 255*32) + * @s: salt + * @ssize: the number of bytes pointed to by @s + * @k: pointer to input key + * @ksize: the number of bytes pointed to by @k + * @info: pointer to info + * @isize: the number of bytes pointed to by @info + */ +void hkdf_sha256(void *okm, size_t okm_size, + const void *s, size_t ssize, + const void *k, size_t ksize, + const void *info, size_t isize); +#endif /* CCAN_CRYPTO_HKDF_SHA256_H */ diff --git a/node_modules/lnsocket/hmac.c b/node_modules/lnsocket/hmac.c new file mode 100644 index 0000000..d0b2683 --- /dev/null +++ b/node_modules/lnsocket/hmac.c @@ -0,0 +1,278 @@ +/* Copyright Rusty Russell (Blockstream) 2015. + +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. +*/ + +#include +#include "hmac.h" + +#define IPAD 0x3636363636363636ULL +#define OPAD 0x5C5C5C5C5C5C5C5CULL + +#define BLOCK_256_U64S (HMAC_SHA256_BLOCKSIZE / sizeof(uint64_t)) +#define BLOCK_512_U64S (HMAC_SHA512_BLOCKSIZE / sizeof(uint64_t)) + +static inline void xor_block_256(uint64_t block[BLOCK_256_U64S], uint64_t pad) +{ + size_t i; + + for (i = 0; i < BLOCK_256_U64S; i++) + block[i] ^= pad; +} + + +static inline void xor_block_512(uint64_t block[BLOCK_512_U64S], uint64_t pad) +{ + size_t i; + + for (i = 0; i < BLOCK_512_U64S; i++) + block[i] ^= pad; +} + +void hmac_sha256_init(struct hmac_sha256_ctx *ctx, + const void *k, size_t ksize) +{ + struct sha256 hashed_key; + /* We use k_opad as k_ipad temporarily. */ + uint64_t *k_ipad = ctx->k_opad; + + /* (keys longer than B bytes are first hashed using H) */ + if (ksize > HMAC_SHA256_BLOCKSIZE) { + sha256(&hashed_key, k, ksize); + k = &hashed_key; + ksize = sizeof(hashed_key); + } + + /* From RFC2104: + * + * (1) append zeros to the end of K to create a B byte string + * (e.g., if K is of length 20 bytes and B=64, then K will be + * appended with 44 zero bytes 0x00) + */ + memcpy(k_ipad, k, ksize); + memset((char *)k_ipad + ksize, 0, HMAC_SHA256_BLOCKSIZE - ksize); + + /* + * (2) XOR (bitwise exclusive-OR) the B byte string computed + * in step (1) with ipad + */ + xor_block_256(k_ipad, IPAD); + + /* + * We start (4) here, appending text later: + * + * (3) append the stream of data 'text' to the B byte string resulting + * from step (2) + * (4) apply H to the stream generated in step (3) + */ + sha256_init(&ctx->sha); + sha256_update(&ctx->sha, k_ipad, HMAC_SHA256_BLOCKSIZE); + + /* + * (5) XOR (bitwise exclusive-OR) the B byte string computed in + * step (1) with opad + */ + xor_block_256(ctx->k_opad, IPAD^OPAD); +} + + +void hmac_sha512_init(struct hmac_sha512_ctx *ctx, + const void *k, size_t ksize) +{ + struct sha512 hashed_key; + /* We use k_opad as k_ipad temporarily. */ + uint64_t *k_ipad = ctx->k_opad; + + /* (keys longer than B bytes are first hashed using H) */ + if (ksize > HMAC_SHA512_BLOCKSIZE) { + sha512(&hashed_key, k, ksize); + k = &hashed_key; + ksize = sizeof(hashed_key); + } + + /* From RFC2104: + * + * (1) append zeros to the end of K to create a B byte string + * (e.g., if K is of length 20 bytes and B=64, then K will be + * appended with 44 zero bytes 0x00) + */ + memcpy(k_ipad, k, ksize); + memset((char *)k_ipad + ksize, 0, HMAC_SHA512_BLOCKSIZE - ksize); + + /* + * (2) XOR (bitwise exclusive-OR) the B byte string computed + * in step (1) with ipad + */ + xor_block_512(k_ipad, IPAD); + + /* + * We start (4) here, appending text later: + * + * (3) append the stream of data 'text' to the B byte string resulting + * from step (2) + * (4) apply H to the stream generated in step (3) + */ + sha512_init(&ctx->sha); + sha512_update(&ctx->sha, k_ipad, HMAC_SHA512_BLOCKSIZE); + + /* + * (5) XOR (bitwise exclusive-OR) the B byte string computed in + * step (1) with opad + */ + xor_block_512(ctx->k_opad, IPAD^OPAD); +} + + +void hmac_sha256_update(struct hmac_sha256_ctx *ctx, const void *p, size_t size) +{ + /* This is the appending-text part of this: + * + * (3) append the stream of data 'text' to the B byte string resulting + * from step (2) + * (4) apply H to the stream generated in step (3) + */ + sha256_update(&ctx->sha, p, size); +} + + +void hmac_sha512_update(struct hmac_sha512_ctx *ctx, const void *p, size_t size) +{ + sha512_update(&ctx->sha, p, size); +} + + +void hmac_sha256_done(struct hmac_sha256_ctx *ctx, + struct hmac_sha256 *hmac) +{ + /* (4) apply H to the stream generated in step (3) */ + sha256_done(&ctx->sha, &hmac->sha); + + /* + * (6) append the H result from step (4) to the B byte string + * resulting from step (5) + * (7) apply H to the stream generated in step (6) and output + * the result + */ + sha256_init(&ctx->sha); + sha256_update(&ctx->sha, ctx->k_opad, sizeof(ctx->k_opad)); + sha256_update(&ctx->sha, &hmac->sha, sizeof(hmac->sha)); + sha256_done(&ctx->sha, &hmac->sha); +} + + +void hmac_sha512_done(struct hmac_sha512_ctx *ctx, + struct hmac_sha512 *hmac) +{ + /* (4) apply H to the stream generated in step (3) */ + sha512_done(&ctx->sha, &hmac->sha); + + /* + * (6) append the H result from step (4) to the B byte string + * resulting from step (5) + * (7) apply H to the stream generated in step (6) and output + * the result + */ + sha512_init(&ctx->sha); + sha512_update(&ctx->sha, ctx->k_opad, sizeof(ctx->k_opad)); + sha512_update(&ctx->sha, &hmac->sha, sizeof(hmac->sha)); + sha512_done(&ctx->sha, &hmac->sha); +} + +#if 1 +void hmac_sha256(struct hmac_sha256 *hmac, + const void *k, size_t ksize, + const void *d, size_t dsize) +{ + struct hmac_sha256_ctx ctx; + + hmac_sha256_init(&ctx, k, ksize); + hmac_sha256_update(&ctx, d, dsize); + hmac_sha256_done(&ctx, hmac); +} + + +void hmac_sha512(struct hmac_sha512 *hmac, + const void *k, size_t ksize, + const void *d, size_t dsize) +{ + struct hmac_sha512_ctx ctx; + + hmac_sha512_init(&ctx, k, ksize); + hmac_sha512_update(&ctx, d, dsize); + hmac_sha512_done(&ctx, hmac); +} + + +#else +/* Direct mapping from MD5 example in RFC2104 */ +void hmac_sha256(struct hmac_sha256 *hmac, + const void *key, size_t key_len, + const void *text, size_t text_len) +{ + struct sha256_ctx context; + unsigned char k_ipad[65]; /* inner padding - + * key XORd with ipad + */ + unsigned char k_opad[65]; /* outer padding - + * key XORd with opad + *//* start out by storing key in pads */ + unsigned char tk[32]; + int i; + + /* if key is longer than 64 bytes reset it to key=MD5(key) */ + if (key_len > 64) { + + struct sha256_ctx tctx; + + sha256_init(&tctx); + sha256_update(&tctx, key, key_len); + sha256_done(&tctx, tk); + + key = tk; + key_len = 32; + } + bzero( k_ipad, sizeof k_ipad); + bzero( k_opad, sizeof k_opad); + bcopy( key, k_ipad, key_len); + bcopy( key, k_opad, key_len); + + /* XOR key with ipad and opad values */ + for (i=0; i<64; i++) { + k_ipad[i] ^= 0x36; + k_opad[i] ^= 0x5c; + } + /* + * perform inner MD5 + */ + sha256_init(&context); /* init context for 1st + * pass */ + sha256_update(&context, k_ipad, 64); /* start with inner pad */ + sha256_update(&context, text, text_len); /* then text of datagram */ + sha256_done(&context, &hmac->sha); /* finish up 1st pass */ + /* + * perform outer MD5 + */ + sha256_init(&context); /* init context for 2nd + * pass */ + sha256_update(&context, k_opad, 64); /* start with outer pad */ + sha256_update(&context, &hmac->sha, 32); /* then results of 1st + * hash */ + sha256_done(&context, &hmac->sha); /* finish up 2nd pass */ +} +#endif diff --git a/node_modules/lnsocket/hmac.h b/node_modules/lnsocket/hmac.h new file mode 100644 index 0000000..87952fd --- /dev/null +++ b/node_modules/lnsocket/hmac.h @@ -0,0 +1,116 @@ + +#ifndef CCAN_CRYPTO_HMAC_SHA256_H +#define CCAN_CRYPTO_HMAC_SHA256_H +/* BSD-MIT */ +#include +#include +#include "sha256.h" +#include "sha512.h" + +/* Number of bytes per block. */ +#define HMAC_SHA256_BLOCKSIZE 64 +#define HMAC_SHA512_BLOCKSIZE 128 + +/** + * struct hmac_sha256 - structure representing a completed HMAC. + */ +struct hmac_sha256 { + struct sha256 sha; +}; + + +struct hmac_sha512 { + struct sha512 sha; +}; + +/** + * hmac_sha256 - return hmac of an object with a key. + * @hmac: the hmac to fill in + * @k: pointer to the key, + * @ksize: the number of bytes pointed to by @k + * @d: pointer to memory, + * @dsize: the number of bytes pointed to by @d + */ +void hmac_sha256(struct hmac_sha256 *hmac, + const void *k, size_t ksize, + const void *d, size_t dsize); + +void hmac_sha512(struct hmac_sha512 *hmac, + const void *k, size_t ksize, + const void *d, size_t dsize); + +/** + * struct hmac_sha256_ctx - structure to store running context for hmac_sha256 + */ +struct hmac_sha256_ctx { + struct sha256_ctx sha; + uint64_t k_opad[HMAC_SHA256_BLOCKSIZE / sizeof(uint64_t)]; +}; + + +struct hmac_sha512_ctx { + struct sha512_ctx sha; + uint64_t k_opad[HMAC_SHA512_BLOCKSIZE / sizeof(uint64_t)]; +}; + +/** + * hmac_sha256_init - initialize an HMAC_SHA256 context. + * @ctx: the hmac_sha256_ctx to initialize + * @k: pointer to the key, + * @ksize: the number of bytes pointed to by @k + * + * This must be called before hmac_sha256_update or hmac_sha256_done. + * + * If it was already initialized, this forgets anything which was + * hashed before. + * + * Example: + * static void hmac_all(const char *key, + * const char **arr, struct hmac_sha256 *hash) + * { + * size_t i; + * struct hmac_sha256_ctx ctx; + * + * hmac_sha256_init(&ctx, key, strlen(key)); + * for (i = 0; arr[i]; i++) + * hmac_sha256_update(&ctx, arr[i], strlen(arr[i])); + * hmac_sha256_done(&ctx, hash); + * } + */ +void hmac_sha256_init(struct hmac_sha256_ctx *ctx, + const void *k, size_t ksize); + +void hmac_sha512_init(struct hmac_sha512_ctx *ctx, + const void *k, size_t ksize); + + +/** + * hmac_sha256_update - include some memory in the hash. + * @ctx: the hmac_sha256_ctx to use + * @p: pointer to memory, + * @size: the number of bytes pointed to by @p + * + * You can call this multiple times to hash more data, before calling + * hmac_sha256_done(). + */ +void hmac_sha256_update(struct hmac_sha256_ctx *ctx, + const void *p, size_t size); + +void hmac_sha512_update(struct hmac_sha512_ctx *ctx, + const void *p, size_t size); + +/** + * hmac_sha256_done - finish HMAC_SHA256 and return the hash + * @ctx: the hmac_sha256_ctx to complete + * @res: the hash to return. + * + * Note that @ctx is *destroyed* by this, and must be reinitialized. + * To avoid that, pass a copy instead. + */ +void hmac_sha256_done(struct hmac_sha256_ctx *hmac_sha256, + struct hmac_sha256 *res); + +void hmac_sha512_done(struct hmac_sha512_ctx *hmac_sha256, + struct hmac_sha512 *res); + +#endif /* CCAN_CRYPTO_HMAC_SHA256_H */ diff --git a/node_modules/lnsocket/index.js b/node_modules/lnsocket/index.js new file mode 100644 index 0000000..093f749 --- /dev/null +++ b/node_modules/lnsocket/index.js @@ -0,0 +1,11 @@ + +const Module = require("./dist/node/lnsocket.js") +const LNSocketReady = Module.lnsocket_init() + +async function load_lnsocket(opts) +{ + const LNSocket = await LNSocketReady + return new LNSocket(opts) +} + +module.exports = load_lnsocket diff --git a/node_modules/lnsocket/lnrpc.c b/node_modules/lnsocket/lnrpc.c new file mode 100644 index 0000000..d7e3cb1 --- /dev/null +++ b/node_modules/lnsocket/lnrpc.c @@ -0,0 +1,114 @@ + +#include + +#include "lnsocket.h" +#include "endian.h" +#include "typedefs.h" +#include "commando.h" + +#include +#include + +#include + +int usage() +{ + printf("lnrpc [params (json string)]\n\n"); + printf("currently supports commando for clightning, but potentially more rpc types in the future!\n"); + return 0; +} + +int main(int argc, const char *argv[]) +{ + static u8 msgbuf[4096]; + u8 *buf; + struct lnsocket *ln; + fd_set set; + struct timeval timeout = {0}; + + char *timeout_str; + u16 len, msgtype; + int ok = 1; + int socket, rv; + int verbose = getenv("VERBOSE") != 0; + //int verbose = 1; + + timeout_str = getenv("LNRPC_TIMEOUT"); + int timeout_ms = timeout_str ? atoi(timeout_str) : 5000; + + timeout.tv_sec = timeout_ms / 1000; + timeout.tv_usec = (timeout_ms % 1000) * 1000; + + FD_ZERO(&set); /* clear the set */ + + if (argc < 5) + return usage(); + + ln = lnsocket_create(); + assert(ln); + + lnsocket_genkey(ln); + + const char *nodeid = argv[1]; + const char *host = argv[2]; + const char *rune = argv[3]; + const char *method = argv[4]; + const char *params = argc < 7 ? argv[5] : NULL; + + if (!(ok = lnsocket_connect(ln, nodeid, host))) + goto done; + + if (!(ok = lnsocket_fd(ln, &socket))) + goto done; + + FD_SET(socket, &set); /* add our file descriptor to the set */ + + if (!(ok = lnsocket_perform_init(ln))) + goto done; + + if (verbose) + fprintf(stderr, "init success\n"); + + if (!(ok = len = commando_make_rpc_msg(method, params, rune, 1, msgbuf, sizeof(msgbuf)))) + goto done; + + if (!(ok = lnsocket_write(ln, msgbuf, len))) + goto done; + + if (verbose) + fprintf(stderr, "waiting for response...\n"); + + while (1) { + rv = select(socket + 1, &set, NULL, NULL, &timeout); + + if (rv == -1) { + perror("select"); + ok = 0; + goto done; + } else if (rv == 0) { + fprintf(stderr, "error: rpc request timeout\n"); + ok = 0; + goto done; + } + + if (!(ok = lnsocket_recv(ln, &msgtype, &buf, &len))) + goto done; + + switch (msgtype) { + case COMMANDO_REPLY_TERM: + printf("%.*s\n", len - 8, buf + 8); + goto done; + case COMMANDO_REPLY_CONTINUES: + printf("%.*s", len - 8, buf + 8); + continue; + default: + // ignore extra interleaved messages which can happen + continue; + } + } + +done: + lnsocket_print_errors(ln); + lnsocket_destroy(ln); + return !ok; +} diff --git a/node_modules/lnsocket/lnsocket.c b/node_modules/lnsocket/lnsocket.c new file mode 100644 index 0000000..471bde4 --- /dev/null +++ b/node_modules/lnsocket/lnsocket.c @@ -0,0 +1,632 @@ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "handshake.h" +#include "error.h" +#include "crypto.h" +#include "endian.h" +#include "bigsize.h" +#include "compiler.h" +#include "lnsocket_internal.h" +#include "lnsocket.h" + +#define array_len(x) (sizeof(x)/sizeof(x[0])) + +#define MSGBUF_MEM (65536*2) +#define ERROR_MEM 4096 +#define DEFAULT_TIMEOUT 3000 + +int push_error(struct lnsocket *lnsocket, const char *err); + +static int char_to_hex(unsigned char *val, char c) +{ + if (c >= '0' && c <= '9') { + *val = c - '0'; + return 1; + } + if (c >= 'a' && c <= 'f') { + *val = c - 'a' + 10; + return 1; + } + if (c >= 'A' && c <= 'F') { + *val = c - 'A' + 10; + return 1; + } + return 0; +} + + +static int hex_decode(const char *str, size_t slen, void *buf, size_t bufsize) +{ + unsigned char v1, v2; + unsigned char *p = buf; + + while (slen > 1) { + if (!char_to_hex(&v1, str[0]) || !char_to_hex(&v2, str[1])) + return 0; + if (!bufsize) + return 0; + *(p++) = (v1 << 4) | v2; + str += 2; + slen -= 2; + bufsize--; + } + return slen == 0 && bufsize == 0; +} + + +int parse_node_id(const char *str, struct node_id *dest) +{ + return hex_decode(str, strlen(str), dest->k, sizeof(*dest)); +} + +int pubkey_from_node_id(secp256k1_context *secp, struct pubkey *key, + const struct node_id *id) +{ + return secp256k1_ec_pubkey_parse(secp, &key->pubkey, + memcheck(id->k, sizeof(id->k)), + sizeof(id->k)); +} + + +static int read_all(int fd, void *data, size_t size) +{ + while (size) { + ssize_t done; + + done = read(fd, data, size); + if (done < 0 && errno == EINTR) + continue; + if (done <= 0) + return 0; + data = (char *)data + done; + size -= done; + } + + return 1; +} + +int EXPORT lnsocket_make_default_initmsg(unsigned char *msgbuf, int buflen) +{ + u8 global_features[2] = {0}; + u8 features[5] = {0}; + u16 len; + + /* + struct tlv network_tlv; + u8 tlvbuf[1024]; + const u8 genesis_block[] = { + 0x6f, 0xe2, 0x8c, 0x0a, 0xb6, 0xf1, 0xb3, 0x72, 0xc1, 0xa6, 0xa2, 0x46, + 0xae, 0x63, 0xf7, 0x4f, 0x93, 0x1e, 0x83, 0x65, 0xe1, 0x5a, 0x08, 0x9c, + 0x68, 0xd6, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + const u8 *blockids[] = { genesis_block }; + + if (!lnsocket_make_network_tlv(tlvbuf, sizeof(tlvbuf), blockids, 1, + &network_tlv)) + return 0; + + + const struct tlv *init_tlvs[] = { &network_tlv } ; + */ + + const struct tlv *init_tlvs[] = { } ; + + if (!lnsocket_make_init_msg(msgbuf, buflen, + global_features, sizeof(global_features), + features, sizeof(features), + init_tlvs, 0, + &len)) + return 0; + + return (int)len; +} + +/* +static void print_hex(u8 *bytes, int len) { + int i; + for (i = 0; i < len; ++i) { + printf("%02x", bytes[i]); + } +} +*/ + +int lnsocket_perform_init(struct lnsocket *ln) +{ + u8 msgbuf[1024]; + u16 len; + u8 *buf; + + // read the init message from the other side and ignore it + if (!lnsocket_read(ln, &buf, &len)) + return 0; + + if (!(len = lnsocket_make_default_initmsg(msgbuf, sizeof(msgbuf)))) + return 0; + + if (!lnsocket_write(ln, msgbuf, len)) + return 0; + + return 1; +} + +// simple helper that pushes a message type and payload +int lnsocket_send(struct lnsocket *ln, unsigned short msg_type, const unsigned char *payload, unsigned short payload_len) +{ + reset_cursor(&ln->msgbuf); + + if (!cursor_push_u16(&ln->msgbuf, msg_type)) + return note_error(&ln->errs, "could not write type to msgbuf?"); + + if (!cursor_push(&ln->msgbuf, payload, payload_len)) + return note_error(&ln->errs, "payload too big"); + + return lnsocket_write(ln, ln->msgbuf.start, ln->msgbuf.p - ln->msgbuf.start); +} + +// simple helper that receives a message type and payload +int lnsocket_recv(struct lnsocket *ln, u16 *msg_type, unsigned char **payload, u16 *payload_len) +{ + struct cursor cur; + u8 *msg; + u16 msglen; + + if (!lnsocket_read(ln, &msg, &msglen)) + return 0; + + make_cursor(msg, msg + msglen, &cur); + + if (!cursor_pull_u16(&cur, msg_type)) + return note_error(&ln->errs, "could not read msgtype"); + + *payload_len = msglen - 2; + *payload = cur.p; + + if (*payload + *payload_len > cur.end) + return note_error(&ln->errs, "recv buffer overflow?"); + + return 1; +} + +int EXPORT lnsocket_decrypt(struct lnsocket *ln, unsigned char *packet, int size) +{ + struct cursor enc, dec; + + make_cursor(packet, packet + size, &enc); + reset_cursor(&ln->msgbuf); + if (!cursor_slice(&ln->msgbuf, &dec, size - 16)) + return note_error(&ln->errs, "out of memory: %d + %d = %d > %d", + ln->msgbuf.end - ln->msgbuf.p, size, + ln->msgbuf.end - ln->msgbuf.p + size, + MSGBUF_MEM + ); + + if (!cryptomsg_decrypt_body(&ln->crypto_state, + enc.start, enc.end - enc.start, + dec.start, dec.end - dec.start)) + return note_error(&ln->errs, "error decrypting body"); + + return dec.end - dec.start; +} + +// this is used in js +int EXPORT lnsocket_decrypt_header(struct lnsocket *ln, unsigned char *hdr) +{ + u16 size = 0; + if (!cryptomsg_decrypt_header(&ln->crypto_state, hdr, &size)) + return note_error(&ln->errs, + "Failed hdr decrypt with rn=%"PRIu64, + ln->crypto_state.rn-1); + return size; +} + +int lnsocket_read(struct lnsocket *ln, unsigned char **buf, unsigned short *len) +{ + struct cursor enc, dec; + u8 hdr[18]; + u16 size; + + reset_cursor(&ln->errs.cur); + reset_cursor(&ln->msgbuf); + + if (!read_all(ln->socket, hdr, sizeof(hdr))) + return note_error(&ln->errs,"Failed reading header: %s", + strerror(errno)); + + if (!cryptomsg_decrypt_header(&ln->crypto_state, hdr, &size)) + return note_error(&ln->errs, + "Failed hdr decrypt with rn=%"PRIu64, + ln->crypto_state.rn-1); + + if (!cursor_slice(&ln->msgbuf, &enc, size + 16)) + return note_error(&ln->errs, "out of memory"); + + if (!cursor_slice(&ln->msgbuf, &dec, size)) + return note_error(&ln->errs, "out of memory: %d + %d = %d > %d", + ln->msgbuf.end - ln->msgbuf.p, size, + ln->msgbuf.end - ln->msgbuf.p + size, + MSGBUF_MEM + ); + + if (!read_all(ln->socket, enc.p, enc.end - enc.start)) + return note_error(&ln->errs, "Failed reading body: %s", + strerror(errno)); + + if (!cryptomsg_decrypt_body(&ln->crypto_state, + enc.start, enc.end - enc.start, + dec.start, dec.end - dec.start)) + return note_error(&ln->errs, "error decrypting body"); + + *buf = dec.start; + *len = dec.end - dec.start; + + return 1; +} + +static int highest_byte(unsigned char *buf, int buflen) +{ + int i, highest; + for (i = 0, highest = 0; i < buflen; i++) { + if (buf[i] != 0) + highest = i; + } + return highest; +} + +#define max(a,b) ((a) > (b) ? (a) : (b)) +int lnsocket_set_feature_bit(unsigned char *buf, int buflen, int *newlen, unsigned int bit) +{ + if (newlen == NULL) + return 0; + + if (bit / 8 >= buflen) + return 0; + + *newlen = max(highest_byte(buf, buflen), (bit / 8) + 1); + buf[*newlen - 1 - bit / 8] |= (1 << (bit % 8)); + + return 1; +} +#undef max + +int cursor_push_tlv(struct cursor *cur, const struct tlv *tlv) +{ + /* BOLT #1: + * + * The sending node: + ... + * - MUST minimally encode `type` and `length`. + */ + return cursor_push_bigsize(cur, tlv->type) && + cursor_push_bigsize(cur, tlv->length) && + cursor_push(cur, tlv->value, tlv->length); +} + +int cursor_push_tlvs(struct cursor *cur, const struct tlv **tlvs, int n_tlvs) +{ + int i; + for (i = 0; i < n_tlvs; i++) { + if (!cursor_push_tlv(cur, tlvs[i])) + return 0; + } + + return 1; +} + +int lnsocket_make_network_tlv(unsigned char *buf, int buflen, + const unsigned char **blockids, int num_blockids, + struct tlv *tlv_out) +{ + struct cursor cur; + + if (!tlv_out) + return 0; + + tlv_out->type = 1; + tlv_out->value = buf; + + make_cursor(buf, buf + buflen, &cur); + + for (size_t i = 0; i < num_blockids; i++) { + if (!cursor_push(&cur, memcheck(blockids[i], 32), 32)) + return 0; + } + + tlv_out->length = cur.p - cur.start; + return 1; +} + +int lnsocket_make_ping_msg(unsigned char *buf, int buflen, u16 num_pong_bytes, u16 ignored_bytes) +{ + struct cursor msg; + int i; + + make_cursor(buf, buf + buflen, &msg); + + if (!cursor_push_u16(&msg, WIRE_PING)) + return 0; + if (!cursor_push_u16(&msg, num_pong_bytes)) + return 0; + if (!cursor_push_u16(&msg, ignored_bytes)) + return 0; + for (i = 0; i < ignored_bytes; i++) { + if (!cursor_push_byte(&msg, 0)) + return 0; + } + + return msg.p - msg.start; +} + +int lnsocket_make_init_msg(unsigned char *buf, int buflen, + const unsigned char *globalfeatures, u16 gflen, + const unsigned char *features, u16 flen, + const struct tlv **tlvs, + unsigned short num_tlvs, + unsigned short *outlen) +{ + struct cursor msg; + + make_cursor(buf, buf + buflen, &msg); + + if (!cursor_push_u16(&msg, WIRE_INIT)) + return 0; + + if (!cursor_push_u16(&msg, gflen)) + return 0; + + if (!cursor_push(&msg, globalfeatures, gflen)) + return 0; + + if (!cursor_push_u16(&msg, flen)) + return 0; + + if (!cursor_push(&msg, features, flen)) + return 0; + + if (!cursor_push_tlvs(&msg, tlvs, num_tlvs)) + return 0; + + *outlen = msg.p - msg.start; + + return 1; +} + +unsigned char* EXPORT lnsocket_msgbuf(struct lnsocket *ln) +{ + return ln->msgbuf.start; +} + +int EXPORT lnsocket_encrypt(struct lnsocket *ln, const u8 *msg, unsigned short msglen) +{ + ssize_t outcap; + size_t outlen; + + // this is just temporary so we don't need to move the memory cursor + reset_cursor(&ln->msgbuf); + + u8 *out = ln->msgbuf.start; + outcap = ln->msgbuf.end - ln->msgbuf.start; + +#ifndef __EMSCRIPTEN__ + if (!ln->socket) + return note_error(&ln->errs, "not connected"); +#endif + + if (outcap <= 0) + return note_error(&ln->errs, "out of memory"); + + if (!cryptomsg_encrypt_msg(&ln->crypto_state, msg, msglen, out, &outlen, (size_t)outcap)) + return note_error(&ln->errs, "encrypt message failed, out of memory"); + + return outlen; +} + +int lnsocket_write(struct lnsocket *ln, const u8 *msg, unsigned short msglen) +{ + ssize_t writelen, outlen; + u8 *out = ln->msgbuf.start; + + if (!(outlen = lnsocket_encrypt(ln, msg, msglen))) + return 0; + + if ((writelen = write(ln->socket, out, outlen)) != outlen) + return note_error(&ln->errs, + "write failed. wrote %ld bytes, expected %ld %s", + writelen, outlen, + writelen < 0 ? strerror(errno) : ""); + + return 1; +} + +struct lnsocket *lnsocket_create() +{ + struct cursor mem; + int memory = MSGBUF_MEM + ERROR_MEM + sizeof(struct lnsocket); + + void *arena = malloc(memory); + + if (!arena) + return NULL; + + make_cursor(arena, arena + memory, &mem); + struct lnsocket *lnsocket = cursor_alloc(&mem, sizeof(*lnsocket)); + + if (!lnsocket) + return NULL; + + lnsocket->secp = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | + SECP256K1_CONTEXT_SIGN); + + if (!cursor_slice(&mem, &lnsocket->msgbuf, MSGBUF_MEM)) + return NULL; + + if (!cursor_slice(&mem, &lnsocket->errs.cur, ERROR_MEM)) + return NULL; + + lnsocket->errs.enabled = 1; + + lnsocket->mem = mem; + return lnsocket; +} + +void lnsocket_destroy(struct lnsocket *lnsocket) +{ + if (!lnsocket) + return; + + secp256k1_context_destroy(lnsocket->secp); + free(lnsocket->mem.start); +} + +int is_zero(void *vp, int size) +{ + u8 *p = (u8*)vp; + const u8 *start = p; + + for (; p < start+size; p++) { + if (*p != 0) + return 0; + } + return 1; +} + +static int io_fd_block(int fd, int block) +{ + int flags = fcntl(fd, F_GETFL); + + if (flags == -1) + return 0; + + if (block) + flags &= ~O_NONBLOCK; + else + flags |= O_NONBLOCK; + + return fcntl(fd, F_SETFL, flags) != -1; +} + +const char *parse_port(char *host) +{ + int i, len; + + len = strlen(host); + + for (i = 0; i < len; i++) { + if (host[i] == ':') { + host[i] = 0; + return &host[i+1]; + } + } + + + return NULL; +} + +int lnsocket_connect_with(struct lnsocket *ln, const char *node_id, const char *host, int timeout_ms) +{ + int ret; + struct addrinfo *addrs = NULL; + struct pubkey their_id; + struct node_id their_node_id; + struct timeval timeout = {0}; + char onlyhost[strlen(host)+1]; + strncpy(onlyhost, host, sizeof(onlyhost)); + fd_set set; + + timeout.tv_sec = timeout_ms / 1000; + timeout.tv_usec = (timeout_ms % 1000) * 1000; + + FD_ZERO(&set); /* clear the set */ + + if (is_zero(&ln->key, sizeof(ln->key))) + return note_error(&ln->errs, "key not initialized, use lnsocket_set_key() or lnsocket_genkey()"); + + // convert node_id string to bytes + if (!parse_node_id(node_id, &their_node_id)) + return note_error(&ln->errs, "failed to parse node id"); + + // encode node_id bytes to secp pubkey + if (!pubkey_from_node_id(ln->secp, &their_id, &their_node_id)) + return note_error(&ln->errs, "failed to convert node_id to pubkey"); + + // parse ip into addrinfo + const char *port = parse_port(onlyhost); + if ((ret = getaddrinfo(onlyhost, port ? port : "9735", NULL, &addrs)) || !addrs) + return note_error(&ln->errs, "%s", gai_strerror(ret)); + + // create our network socket for comms + if (!(ln->socket = socket(AF_INET, SOCK_STREAM, 0))) + return note_error(&ln->errs, "creating socket failed"); + + FD_SET(ln->socket, &set); /* add our file descriptor to the set */ + + if (!io_fd_block(ln->socket, 0)) + return note_error(&ln->errs, "failed setting socket to non-blocking"); + + // connect to the node! + connect(ln->socket, addrs->ai_addr, addrs->ai_addrlen); + + if (!io_fd_block(ln->socket, 1)) + return note_error(&ln->errs, "failed setting socket to blocking"); + + ret = select(ln->socket + 1, NULL, &set, NULL, &timeout); + if (ret == -1) { + return note_error(&ln->errs, "select error"); + } else if (ret == 0) { + return note_error(&ln->errs, "connection timeout"); + } + + // prepare some data for ACT1 + new_handshake(ln->secp, &ln->handshake, &their_id); + + ln->handshake.side = INITIATOR; + ln->handshake.their_id = their_id; + + // let's do this! + return act_one_initiator(ln); +} + +int lnsocket_connect(struct lnsocket *ln, const char *node_id, const char *host) +{ + return lnsocket_connect_with(ln, node_id, host, DEFAULT_TIMEOUT); +} + +int lnsocket_fd(struct lnsocket *ln, int *fd) +{ + *fd = ln->socket; + return 1; +} + +void * lnsocket_secp(struct lnsocket *ln) +{ + return ln->secp; +} + +void lnsocket_genkey(struct lnsocket *ln) +{ + ln->key = generate_key(ln->secp); +} + +void lnsocket_print_errors(struct lnsocket *ln) +{ + print_error_backtrace(&ln->errs); +} + + diff --git a/node_modules/lnsocket/lnsocket.h b/node_modules/lnsocket/lnsocket.h new file mode 100644 index 0000000..10a326b --- /dev/null +++ b/node_modules/lnsocket/lnsocket.h @@ -0,0 +1,95 @@ +#ifndef LNSOCKET_H +#define LNSOCKET_H + +#include +#include + +struct lnsocket; + +#ifdef __EMSCRIPTEN__ + #include + #define EXPORT EMSCRIPTEN_KEEPALIVE +#else + #define EXPORT +#endif + +enum peer_wire { + WIRE_INIT = 16, + WIRE_ERROR = 17, + WIRE_WARNING = 1, + WIRE_PING = 18, + WIRE_PONG = 19, + WIRE_TX_ADD_INPUT = 66, + WIRE_TX_ADD_OUTPUT = 67, + WIRE_TX_REMOVE_INPUT = 68, + WIRE_TX_REMOVE_OUTPUT = 69, + WIRE_TX_COMPLETE = 70, + WIRE_TX_SIGNATURES = 71, + WIRE_OPEN_CHANNEL = 32, + WIRE_ACCEPT_CHANNEL = 33, + WIRE_FUNDING_CREATED = 34, + WIRE_FUNDING_SIGNED = 35, + WIRE_FUNDING_LOCKED = 36, + WIRE_OPEN_CHANNEL2 = 64, + WIRE_ACCEPT_CHANNEL2 = 65, + WIRE_INIT_RBF = 72, + WIRE_ACK_RBF = 73, + WIRE_SHUTDOWN = 38, + WIRE_CLOSING_SIGNED = 39, + WIRE_UPDATE_ADD_HTLC = 128, + WIRE_UPDATE_FULFILL_HTLC = 130, + WIRE_UPDATE_FAIL_HTLC = 131, + WIRE_UPDATE_FAIL_MALFORMED_HTLC = 135, + WIRE_COMMITMENT_SIGNED = 132, + WIRE_REVOKE_AND_ACK = 133, + WIRE_UPDATE_FEE = 134, + WIRE_UPDATE_BLOCKHEIGHT = 137, + WIRE_CHANNEL_REESTABLISH = 136, + WIRE_ANNOUNCEMENT_SIGNATURES = 259, + WIRE_CHANNEL_ANNOUNCEMENT = 256, + WIRE_NODE_ANNOUNCEMENT = 257, + WIRE_CHANNEL_UPDATE = 258, + WIRE_QUERY_SHORT_CHANNEL_IDS = 261, + WIRE_REPLY_SHORT_CHANNEL_IDS_END = 262, + WIRE_QUERY_CHANNEL_RANGE = 263, + WIRE_REPLY_CHANNEL_RANGE = 264, + WIRE_GOSSIP_TIMESTAMP_FILTER = 265, + WIRE_OBS2_ONION_MESSAGE = 387, + WIRE_ONION_MESSAGE = 513, +}; + +/* A single TLV field, consisting of the data and its associated metadata. */ +struct tlv { + uint64_t type; + size_t length; + unsigned char *value; +}; + +struct lnsocket EXPORT *lnsocket_create(); + +/* messages */ + +int lnsocket_make_network_tlv(unsigned char *buf, int buflen, const unsigned char **blockids, int num_blockids, struct tlv *tlv_out); +int EXPORT lnsocket_make_ping_msg(unsigned char *buf, int buflen, unsigned short num_pong_bytes, unsigned short ignored_bytes); +int lnsocket_make_init_msg(unsigned char *buf, int buflen, const unsigned char *globalfeatures, unsigned short gflen, const unsigned char *features, unsigned short flen, const struct tlv **tlvs, unsigned short num_tlvs, unsigned short *outlen); + +int lnsocket_perform_init(struct lnsocket *ln); + +int lnsocket_connect(struct lnsocket *, const char *node_id, const char *host); + +int lnsocket_fd(struct lnsocket *, int *fd); +int lnsocket_write(struct lnsocket *, const unsigned char *msg, unsigned short msg_len); +int lnsocket_read(struct lnsocket *, unsigned char **buf, unsigned short *len); + +int lnsocket_send(struct lnsocket *, unsigned short msg_type, const unsigned char *payload, unsigned short payload_len); +int lnsocket_recv(struct lnsocket *, unsigned short *msg_type, unsigned char **payload, unsigned short *payload_len); + +void* EXPORT lnsocket_secp(struct lnsocket *); +void EXPORT lnsocket_genkey(struct lnsocket *); +void EXPORT lnsocket_destroy(struct lnsocket *); +void EXPORT lnsocket_print_errors(struct lnsocket *); +int EXPORT lnsocket_make_default_initmsg(unsigned char *msgbuf, int buflen); +int EXPORT lnsocket_encrypt(struct lnsocket *ln, const unsigned char *msg, unsigned short msglen); +int EXPORT lnsocket_decrypt_header(struct lnsocket *ln, unsigned char *hdr); + +#endif /* LNSOCKET_H */ diff --git a/node_modules/lnsocket/lnsocket_internal.h b/node_modules/lnsocket/lnsocket_internal.h new file mode 100644 index 0000000..89298dd --- /dev/null +++ b/node_modules/lnsocket/lnsocket_internal.h @@ -0,0 +1,26 @@ +#ifndef LNSOCKET_INTERNAL_H +#define LNSOCKET_INTERNAL_H + +#include "crypto.h" +#include "error.h" +#include "handshake.h" + +struct lnsocket { + const char *errors[8]; + struct cursor mem; + struct cursor msgbuf; + struct errors errs; + int num_errors; + int socket; + struct keypair key; + struct pubkey responder_id; + struct handshake handshake; + struct crypto_state crypto_state; + secp256k1_context *secp; +}; + +int parse_node_id(const char *str, struct node_id *dest); +int pubkey_from_node_id(secp256k1_context *secp, struct pubkey *key, const struct node_id *id); +int is_zero(void *vp, int size); + +#endif /* LNSOCKET_INTERNAL_H */ diff --git a/node_modules/lnsocket/lnsocket_lib.js b/node_modules/lnsocket/lnsocket_lib.js new file mode 100644 index 0000000..6e8413f --- /dev/null +++ b/node_modules/lnsocket/lnsocket_lib.js @@ -0,0 +1,370 @@ + +async function lnsocket_init() { + const module = await Module() + + function SocketImpl(host) { + if (!(this instanceof SocketImpl)) + return new SocketImpl(host) + + if (typeof WebSocket !== 'undefined') { + console.log("WebSocket", typeof WebSocket) + const ok = host.startsWith("ws://") || host.startsWith("wss://") + if (!ok) + throw new Error("host must start with ws:// or wss://") + const ws = new WebSocket(host) + ws.ondata = function(fn) { + ws.onmessage = (v) => { + const data = v.data.arrayBuffer() + fn(data) + } + } + return ws + } + + // + // we're in nodejs + // + const net = require('net') + let [hostname,port] = host.split(":") + port = +port || 9735 + const socket = net.createConnection(port, hostname, () => { + socket.emit("open") + }) + socket.addEventListener = socket.on.bind(socket) + + if (socket.onmessage) + throw new Error("socket already has onmessage?") + + socket.ondata = (fn) => { + socket.on('data', fn) + } + + socket.close = () => { + socket.destroy() + } + + if (socket.send) + throw new Error("socket already has send?") + + socket.send = function socket_send(data) { + return new Promise((resolve, reject) => { + socket.write(data, resolve) + }); + } + + return socket + } + + const ACT_ONE_SIZE = 50 + const ACT_TWO_SIZE = 50 + const ACT_THREE_SIZE = 66 + const DEFAULT_TIMEOUT = 15000 + + const COMMANDO_REPLY_CONTINUES = 0x594b + const COMMANDO_REPLY_TERM = 0x594d + + const lnsocket_create = module.cwrap("lnsocket_create", "number") + const lnsocket_destroy = module.cwrap("lnsocket_destroy", "number") + const lnsocket_encrypt = module.cwrap("lnsocket_encrypt", "number", ["int", "array", "int", "int"]) + const lnsocket_decrypt = module.cwrap("lnsocket_decrypt", "number", ["int", "array", "int"]) + const lnsocket_decrypt_header = module.cwrap("lnsocket_decrypt_header", "number", ["number", "array"]) + const lnsocket_msgbuf = module.cwrap("lnsocket_msgbuf", "number", ["int"]) + const lnsocket_act_one = module.cwrap("lnsocket_act_one", "number", ["number", "string"]) + const lnsocket_act_two = module.cwrap("lnsocket_act_two", "number", ["number", "array"]) + const lnsocket_print_errors = module.cwrap("lnsocket_print_errors", "int") + const lnsocket_genkey = module.cwrap("lnsocket_genkey", "int") + const lnsocket_make_default_initmsg = module.cwrap("lnsocket_make_default_initmsg", "int", ["int", "int"]) + const lnsocket_make_ping_msg = module.cwrap("lnsocket_make_ping_msg", "int", ["int", "int", "int", "int"]) + const commando_make_rpc_msg = module.cwrap("commando_make_rpc_msg", "int", ["string", "string", "string", "number", "int", "int"]) + + function concat_u8_arrays(arrays) { + // sum of individual array lengths + let totalLength = arrays.reduce((acc, value) => + acc + (value.length || value.byteLength) + , 0); + + if (!arrays.length) return null; + + let result = new Uint8Array(totalLength); + + let length = 0; + for (let array of arrays) { + if (array instanceof ArrayBuffer) + result.set(new Uint8Array(array), length); + else + result.set(array, length); + + length += (array.length || array.byteLength); + } + + return result; + } + + function parse_msgtype(buf) { + return buf[0] << 8 | buf[1] + } + + function wasm_mem(ptr, size) { + return new Uint8Array(module.HEAPU8.buffer, ptr, size); + } + + function LNSocket(opts) { + if (!(this instanceof LNSocket)) + return new LNSocket(opts) + + this.opts = opts || { + timeout: DEFAULT_TIMEOUT + } + this.queue = [] + this.ln = lnsocket_create() + } + + LNSocket.prototype.queue_recv = function() { + let self = this + return new Promise((resolve, reject) => { + const checker = setInterval(() => { + const val = self.queue.shift() + if (val) { + clearInterval(checker) + resolve(val) + } else if (!self.connected) { + clearInterval(checker) + reject() + } + }, 5); + }) + } + + LNSocket.prototype.print_errors = function _lnsocket_print_errors() { + lnsocket_print_errors(this.ln) + } + + LNSocket.prototype.genkey = function _lnsocket_genkey() { + lnsocket_genkey(this.ln) + } + + LNSocket.prototype.act_one_data = function _lnsocket_act_one(node_id) { + const act_one_ptr = lnsocket_act_one(this.ln, node_id) + if (act_one_ptr === 0) + return null + return wasm_mem(act_one_ptr, ACT_ONE_SIZE) + } + + LNSocket.prototype.act_two = function _lnsocket_act_two(act2) { + const act_three_ptr = lnsocket_act_two(this.ln, new Uint8Array(act2)) + if (act_three_ptr === 0) { + this.print_errors() + return null + } + return wasm_mem(act_three_ptr, ACT_THREE_SIZE) + } + + LNSocket.prototype.connect = async function lnsocket_connect(node_id, host) { + await handle_connect(this, node_id, host) + + const act1 = this.act_one_data(node_id) + this.ws.send(act1) + const act2 = await this.read_all(ACT_TWO_SIZE) + if (act2.length != ACT_TWO_SIZE) { + throw new Error(`expected act2 to be ${ACT_TWO_SIZE} long, got ${act2.length}`) + } + const act3 = this.act_two(act2) + this.ws.send(act3) + } + + LNSocket.prototype.connect_and_init = async function _connect_and_init(node_id, host) { + await this.connect(node_id, host) + await this.perform_init() + } + + LNSocket.prototype.read_all = async function read_all(n) { + let count = 0 + let chunks = [] + if (!this.connected) + throw new Error("read_all: not connected") + while (true) { + let res = await this.queue_recv() + + const remaining = n - count + + if (res.byteLength > remaining) { + chunks.push(res.slice(0, remaining)) + this.queue.unshift(res.slice(remaining)) + break + } else if (res.byteLength === remaining) { + chunks.push(res) + break + } + + chunks.push(res) + count += res.byteLength + } + + return concat_u8_arrays(chunks) + } + + LNSocket.prototype.read_header = async function read_header() { + const header = await this.read_all(18) + if (header.length != 18) + throw new Error("Failed to read header") + return lnsocket_decrypt_header(this.ln, header) + } + + LNSocket.prototype.rpc = async function lnsocket_rpc(opts) { + const msg = this.make_commando_msg(opts) + this.write(msg) + const res = await this.read_all_rpc() + return JSON.parse(res) + } + + LNSocket.prototype.recv = async function lnsocket_recv() { + const msg = await this.read() + const msgtype = parse_msgtype(msg.slice(0,2)) + const res = [msgtype, msg.slice(2)] + return res + } + + LNSocket.prototype.read_all_rpc = async function read_all_rpc() { + let chunks = [] + while (true) { + const [typ, msg] = await this.recv() + switch (typ) { + case COMMANDO_REPLY_TERM: + chunks.push(msg.slice(8)) + return new TextDecoder().decode(concat_u8_arrays(chunks)); + case COMMANDO_REPLY_CONTINUES: + chunks.push(msg.slice(8)) + break + default: + console.log("got unknown type", typ) + continue + } + } + } + + LNSocket.prototype.make_commando_msg = function _lnsocket_make_commando_msg(opts) { + const buflen = 4096 + let len = 0; + const buf = module._malloc(buflen); + module.HEAPU8.set(Uint8Array, buf); + + const params = JSON.stringify(opts.params||{}) + if (!(len = commando_make_rpc_msg(opts.method, params, opts.rune, + 0, buf, buflen))) { + throw new Error("couldn't make commando msg"); + } + + const dat = wasm_mem(buf, len) + module._free(buf); + return dat + } + + LNSocket.prototype.make_ping_msg = function _lnsocket_make_ping_msg(num_pong_bytes=1, ignored_bytes=1) { + const buflen = 32 + let len = 0; + const buf = module._malloc(buflen); + module.HEAPU8.set(Uint8Array, buf); + + if (!(len = lnsocket_make_ping_msg(buf, buflen, num_pong_bytes, ignored_bytes))) + throw new Error("couldn't make ping msg"); + + const dat = wasm_mem(buf, len) + module._free(buf); + return dat + } + + LNSocket.prototype.encrypt = function _lnsocket_encrypt(dat) { + const len = lnsocket_encrypt(this.ln, dat, dat.length) + if (len === 0) { + this.print_errors() + throw new Error("encrypt error") + } + const enc = wasm_mem(lnsocket_msgbuf(this.ln), len) + return enc + } + + LNSocket.prototype.decrypt = function _lnsocket_decrypt(dat) { + const len = lnsocket_decrypt(this.ln, dat, dat.length) + if (len === 0) { + this.print_errors() + throw new Error("decrypt error") + } + return wasm_mem(lnsocket_msgbuf(this.ln), len) + } + + LNSocket.prototype.write = function _lnsocket_write(dat) { + this.ws.send(this.encrypt(dat)) + } + + LNSocket.prototype.read = async function _lnsocket_read() { + const size = await this.read_header() + const enc = await this.read_all(size+16) + return this.decrypt(enc) + } + + LNSocket.prototype.make_default_initmsg = function _lnsocket_make_default_initmsg() { + const buflen = 1024 + let len = 0; + const buf = module._malloc(buflen); + module.HEAPU8.set(Uint8Array, buf); + + if (!(len = lnsocket_make_default_initmsg(buf, buflen))) + throw new Error("couldn't make initmsg"); + + const dat = wasm_mem(buf, len) + module._free(buf); + return dat + } + + LNSocket.prototype.perform_init = async function lnsocket_connect() { + await this.read() + const our_init = this.make_default_initmsg() + this.write(our_init) + } + + LNSocket.prototype.ping_pong = async function lnsocket_ping_pong() { + const pingmsg = this.make_ping_msg() + this.write(pingmsg) + return await this.read() + } + + LNSocket.prototype.disconnect = function lnsocket_disconnect() { + if (this.connected === true && this.ws) { + this.ws.close() + return true + } + return false + } + + LNSocket.prototype.destroy = function _lnsocket_destroy() { + this.disconnect() + lnsocket_destroy(this.ln) + } + + function handle_connect(ln, node_id, host) { + const ws = new SocketImpl(host) + return new Promise((resolve, reject) => { + const timeout = ln.opts.timeout || DEFAULT_TIMEOUT + const timer = setTimeout(reject, timeout); + + ws.ondata((v) => { + ln.queue.push(v) + }); + + ws.addEventListener('open', function(ev) { + ln.ws = ws + ln.connected = true + clearTimeout(timer) + resolve(ws) + }); + + ws.addEventListener('close', function(ev) { + ln.connected = false + }); + }) + } + + return LNSocket +} + +Module.init = Module.lnsocket_init = lnsocket_init diff --git a/node_modules/lnsocket/lnsocket_pre.js b/node_modules/lnsocket/lnsocket_pre.js new file mode 100644 index 0000000..35fe441 --- /dev/null +++ b/node_modules/lnsocket/lnsocket_pre.js @@ -0,0 +1,24 @@ +Module.getRandomValue = (function() { + const window_ = "object" === typeof window ? window : this + const crypto_ = typeof window_.crypto !== "undefined" ? window_.crypto : window_.msCrypto; + + let randomBytesNode + if (!crypto_) { + randomBytesNode = require('crypto').randomBytes + fn = randomValuesNode + } else { + fn = randomValuesStandard + } + + function randomValuesNode() { + return randomBytesNode(1)[0] >>> 0 + } + + function randomValuesStandard() { + var buf = new Uint32Array(1); + crypto_.getRandomValues(buf); + return buf[0] >>> 0; + }; + + return fn +})() diff --git a/node_modules/lnsocket/lnsocket_wasm.c b/node_modules/lnsocket/lnsocket_wasm.c new file mode 100644 index 0000000..28160c9 --- /dev/null +++ b/node_modules/lnsocket/lnsocket_wasm.c @@ -0,0 +1,39 @@ + +#include "handshake.h" +#include "lnsocket_internal.h" +#include + +struct act_three* lnsocket_act_two(struct lnsocket *ln, struct act_two *act2); + +void* EMSCRIPTEN_KEEPALIVE lnsocket_act_one(struct lnsocket *ln, const char *node_id) +{ + struct pubkey their_id; + struct node_id their_node_id; + + if (is_zero(&ln->key, sizeof(ln->key))) { + note_error(&ln->errs, "key not initialized, use lnsocket_set_key() or lnsocket_genkey()"); + return NULL; + } + + if (!parse_node_id(node_id, &their_node_id)) { + note_error(&ln->errs, "failed to parse node id"); + return NULL; + } + + if (!pubkey_from_node_id(ln->secp, &their_id, &their_node_id)) { + note_error(&ln->errs, "failed to convert node_id to pubkey"); + return NULL; + } + + new_handshake(ln->secp, &ln->handshake, &their_id); + + ln->handshake.side = INITIATOR; + ln->handshake.their_id = their_id; + + if (!act_one_initiator_prep(ln)) { + note_error(&ln->errs, "failed to build initial handshake data (act1)"); + return NULL; + } + + return &ln->handshake.act1; +} diff --git a/node_modules/lnsocket/package.json b/node_modules/lnsocket/package.json new file mode 100644 index 0000000..3caabf3 --- /dev/null +++ b/node_modules/lnsocket/package.json @@ -0,0 +1,13 @@ +{ + "name": "lnsocket", + "description": "Connect to the lightning network", + "version": "0.2.5", + "repository": { + "url": "https://github.com/jb55/lnsocket" + }, + "main": "index.js", + "dependencies": {}, + "devDependencies": { + "tap": "~0.2.5" + } +} diff --git a/node_modules/lnsocket/sha256.c b/node_modules/lnsocket/sha256.c new file mode 100644 index 0000000..e8ddbb7 --- /dev/null +++ b/node_modules/lnsocket/sha256.c @@ -0,0 +1,302 @@ +/* MIT (BSD) license - see LICENSE file for details */ +/* SHA256 core code translated from the Bitcoin project's C++: + * + * src/crypto/sha256.cpp commit 417532c8acb93c36c2b6fd052b7c11b6a2906aa2 + * Copyright (c) 2014 The Bitcoin Core developers + * Distributed under the MIT software license, see the accompanying + * file COPYING or http://www.opensource.org/licenses/mit-license.php. + */ +#include "sha256.h" +#include "endian.h" +#include "compiler.h" +#include +#include +#include + +static void invalidate_sha256(struct sha256_ctx *ctx) +{ +#ifdef CCAN_CRYPTO_SHA256_USE_OPENSSL + ctx->c.md_len = 0; +#else + ctx->bytes = (size_t)-1; +#endif +} + +static void check_sha256(struct sha256_ctx *ctx) +{ +#ifdef CCAN_CRYPTO_SHA256_USE_OPENSSL + assert(ctx->c.md_len != 0); +#else + assert(ctx->bytes != (size_t)-1); +#endif +} + +#ifdef CCAN_CRYPTO_SHA256_USE_OPENSSL +void sha256_init(struct sha256_ctx *ctx) +{ + SHA256_Init(&ctx->c); +} + +void sha256_update(struct sha256_ctx *ctx, const void *p, size_t size) +{ + check_sha256(ctx); + SHA256_Update(&ctx->c, p, size); +} + +void sha256_done(struct sha256_ctx *ctx, struct sha256 *res) +{ + SHA256_Final(res->u.u8, &ctx->c); + invalidate_sha256(ctx); +} +#else +static uint32_t Ch(uint32_t x, uint32_t y, uint32_t z) +{ + return z ^ (x & (y ^ z)); +} +static uint32_t Maj(uint32_t x, uint32_t y, uint32_t z) +{ + return (x & y) | (z & (x | y)); +} +static uint32_t Sigma0(uint32_t x) +{ + return (x >> 2 | x << 30) ^ (x >> 13 | x << 19) ^ (x >> 22 | x << 10); +} +static uint32_t Sigma1(uint32_t x) +{ + return (x >> 6 | x << 26) ^ (x >> 11 | x << 21) ^ (x >> 25 | x << 7); +} +static uint32_t sigma0(uint32_t x) +{ + return (x >> 7 | x << 25) ^ (x >> 18 | x << 14) ^ (x >> 3); +} +static uint32_t sigma1(uint32_t x) +{ + return (x >> 17 | x << 15) ^ (x >> 19 | x << 13) ^ (x >> 10); +} + +/** One round of SHA-256. */ +static void Round(uint32_t a, uint32_t b, uint32_t c, uint32_t *d, uint32_t e, uint32_t f, uint32_t g, uint32_t *h, uint32_t k, uint32_t w) +{ + uint32_t t1 = *h + Sigma1(e) + Ch(e, f, g) + k + w; + uint32_t t2 = Sigma0(a) + Maj(a, b, c); + *d += t1; + *h = t1 + t2; +} + +/** Perform one SHA-256 transformation, processing a 64-byte chunk. */ +static void Transform(uint32_t *s, const uint32_t *chunk) +{ + uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7]; + uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; + + Round(a, b, c, &d, e, f, g, &h, 0x428a2f98, w0 = be32_to_cpu(chunk[0])); + Round(h, a, b, &c, d, e, f, &g, 0x71374491, w1 = be32_to_cpu(chunk[1])); + Round(g, h, a, &b, c, d, e, &f, 0xb5c0fbcf, w2 = be32_to_cpu(chunk[2])); + Round(f, g, h, &a, b, c, d, &e, 0xe9b5dba5, w3 = be32_to_cpu(chunk[3])); + Round(e, f, g, &h, a, b, c, &d, 0x3956c25b, w4 = be32_to_cpu(chunk[4])); + Round(d, e, f, &g, h, a, b, &c, 0x59f111f1, w5 = be32_to_cpu(chunk[5])); + Round(c, d, e, &f, g, h, a, &b, 0x923f82a4, w6 = be32_to_cpu(chunk[6])); + Round(b, c, d, &e, f, g, h, &a, 0xab1c5ed5, w7 = be32_to_cpu(chunk[7])); + Round(a, b, c, &d, e, f, g, &h, 0xd807aa98, w8 = be32_to_cpu(chunk[8])); + Round(h, a, b, &c, d, e, f, &g, 0x12835b01, w9 = be32_to_cpu(chunk[9])); + Round(g, h, a, &b, c, d, e, &f, 0x243185be, w10 = be32_to_cpu(chunk[10])); + Round(f, g, h, &a, b, c, d, &e, 0x550c7dc3, w11 = be32_to_cpu(chunk[11])); + Round(e, f, g, &h, a, b, c, &d, 0x72be5d74, w12 = be32_to_cpu(chunk[12])); + Round(d, e, f, &g, h, a, b, &c, 0x80deb1fe, w13 = be32_to_cpu(chunk[13])); + Round(c, d, e, &f, g, h, a, &b, 0x9bdc06a7, w14 = be32_to_cpu(chunk[14])); + Round(b, c, d, &e, f, g, h, &a, 0xc19bf174, w15 = be32_to_cpu(chunk[15])); + + Round(a, b, c, &d, e, f, g, &h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, &c, d, e, f, &g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, &b, c, d, e, &f, 0x0fc19dc6, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, &a, b, c, d, &e, 0x240ca1cc, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, &h, a, b, c, &d, 0x2de92c6f, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, &g, h, a, b, &c, 0x4a7484aa, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, &f, g, h, a, &b, 0x5cb0a9dc, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, &e, f, g, h, &a, 0x76f988da, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, &d, e, f, g, &h, 0x983e5152, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, &c, d, e, f, &g, 0xa831c66d, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, &b, c, d, e, &f, 0xb00327c8, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, &a, b, c, d, &e, 0xbf597fc7, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, &h, a, b, c, &d, 0xc6e00bf3, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, &g, h, a, b, &c, 0xd5a79147, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, &f, g, h, a, &b, 0x06ca6351, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, &e, f, g, h, &a, 0x14292967, w15 += sigma1(w13) + w8 + sigma0(w0)); + + Round(a, b, c, &d, e, f, g, &h, 0x27b70a85, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, &c, d, e, f, &g, 0x2e1b2138, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, &b, c, d, e, &f, 0x4d2c6dfc, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, &a, b, c, d, &e, 0x53380d13, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, &h, a, b, c, &d, 0x650a7354, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, &g, h, a, b, &c, 0x766a0abb, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, &f, g, h, a, &b, 0x81c2c92e, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, &e, f, g, h, &a, 0x92722c85, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, &d, e, f, g, &h, 0xa2bfe8a1, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, &c, d, e, f, &g, 0xa81a664b, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, &b, c, d, e, &f, 0xc24b8b70, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, &a, b, c, d, &e, 0xc76c51a3, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, &h, a, b, c, &d, 0xd192e819, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, &g, h, a, b, &c, 0xd6990624, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, &f, g, h, a, &b, 0xf40e3585, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, &e, f, g, h, &a, 0x106aa070, w15 += sigma1(w13) + w8 + sigma0(w0)); + + Round(a, b, c, &d, e, f, g, &h, 0x19a4c116, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, &c, d, e, f, &g, 0x1e376c08, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, &b, c, d, e, &f, 0x2748774c, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, &a, b, c, d, &e, 0x34b0bcb5, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, &h, a, b, c, &d, 0x391c0cb3, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, &g, h, a, b, &c, 0x4ed8aa4a, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, &f, g, h, a, &b, 0x5b9cca4f, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, &e, f, g, h, &a, 0x682e6ff3, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, &d, e, f, g, &h, 0x748f82ee, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, &c, d, e, f, &g, 0x78a5636f, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, &b, c, d, e, &f, 0x84c87814, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, &a, b, c, d, &e, 0x8cc70208, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, &h, a, b, c, &d, 0x90befffa, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, &g, h, a, b, &c, 0xa4506ceb, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, &f, g, h, a, &b, 0xbef9a3f7, w14 + sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, &e, f, g, h, &a, 0xc67178f2, w15 + sigma1(w13) + w8 + sigma0(w0)); + + s[0] += a; + s[1] += b; + s[2] += c; + s[3] += d; + s[4] += e; + s[5] += f; + s[6] += g; + s[7] += h; +} + + +static void add(struct sha256_ctx *ctx, const void *p, size_t len) +{ + const unsigned char *data = p; + size_t bufsize = ctx->bytes % 64; + + if (bufsize + len >= 64) { + /* Fill the buffer, and process it. */ + memcpy(ctx->buf.u8 + bufsize, data, 64 - bufsize); + ctx->bytes += 64 - bufsize; + data += 64 - bufsize; + len -= 64 - bufsize; + Transform(ctx->s, ctx->buf.u32); + bufsize = 0; + } + + while (len >= 64) { + /* Process full chunks directly from the source. */ + if (alignment_ok(data, sizeof(uint32_t))) + Transform(ctx->s, (const uint32_t *)data); + else { + memcpy(ctx->buf.u8, data, sizeof(ctx->buf)); + Transform(ctx->s, ctx->buf.u32); + } + ctx->bytes += 64; + data += 64; + len -= 64; + } + + if (len) { + /* Fill the buffer with what remains. */ + memcpy(ctx->buf.u8 + bufsize, data, len); + ctx->bytes += len; + } +} + +void sha256_init(struct sha256_ctx *ctx) +{ + struct sha256_ctx init = SHA256_INIT; + *ctx = init; +} + +void sha256_update(struct sha256_ctx *ctx, const void *p, size_t size) +{ + check_sha256(ctx); + add(ctx, p, size); +} + +void sha256_done(struct sha256_ctx *ctx, struct sha256 *res) +{ + static const unsigned char pad[64] = {0x80}; + uint64_t sizedesc; + size_t i; + + sizedesc = cpu_to_be64((uint64_t)ctx->bytes << 3); + /* Add '1' bit to terminate, then all 0 bits, up to next block - 8. */ + add(ctx, pad, 1 + ((128 - 8 - (ctx->bytes % 64) - 1) % 64)); + /* Add number of bits of data (big endian) */ + add(ctx, &sizedesc, 8); + for (i = 0; i < sizeof(ctx->s) / sizeof(ctx->s[0]); i++) + res->u.u32[i] = cpu_to_be32(ctx->s[i]); + invalidate_sha256(ctx); +} +#endif + +void sha256(struct sha256 *sha, const void *p, size_t size) +{ + struct sha256_ctx ctx; + + sha256_init(&ctx); + sha256_update(&ctx, p, size); + sha256_done(&ctx, sha); +} + +void sha256_u8(struct sha256_ctx *ctx, uint8_t v) +{ + sha256_update(ctx, &v, sizeof(v)); +} + +void sha256_u16(struct sha256_ctx *ctx, uint16_t v) +{ + sha256_update(ctx, &v, sizeof(v)); +} + +void sha256_u32(struct sha256_ctx *ctx, uint32_t v) +{ + sha256_update(ctx, &v, sizeof(v)); +} + +void sha256_u64(struct sha256_ctx *ctx, uint64_t v) +{ + sha256_update(ctx, &v, sizeof(v)); +} + +/* Add as little-endian */ +void sha256_le16(struct sha256_ctx *ctx, uint16_t v) +{ + leint16_t lev = cpu_to_le16(v); + sha256_update(ctx, &lev, sizeof(lev)); +} + +void sha256_le32(struct sha256_ctx *ctx, uint32_t v) +{ + leint32_t lev = cpu_to_le32(v); + sha256_update(ctx, &lev, sizeof(lev)); +} + +void sha256_le64(struct sha256_ctx *ctx, uint64_t v) +{ + leint64_t lev = cpu_to_le64(v); + sha256_update(ctx, &lev, sizeof(lev)); +} + +/* Add as big-endian */ +void sha256_be16(struct sha256_ctx *ctx, uint16_t v) +{ + beint16_t bev = cpu_to_be16(v); + sha256_update(ctx, &bev, sizeof(bev)); +} + +void sha256_be32(struct sha256_ctx *ctx, uint32_t v) +{ + beint32_t bev = cpu_to_be32(v); + sha256_update(ctx, &bev, sizeof(bev)); +} + +void sha256_be64(struct sha256_ctx *ctx, uint64_t v) +{ + beint64_t bev = cpu_to_be64(v); + sha256_update(ctx, &bev, sizeof(bev)); +} + + diff --git a/node_modules/lnsocket/sha256.h b/node_modules/lnsocket/sha256.h new file mode 100644 index 0000000..2a92831 --- /dev/null +++ b/node_modules/lnsocket/sha256.h @@ -0,0 +1,155 @@ + +#ifndef CCAN_CRYPTO_SHA256_H +#define CCAN_CRYPTO_SHA256_H + + +/** Output length for `wally_sha256` */ +#define SHA256_LEN 32 + + +/* BSD-MIT - see LICENSE file for details */ +/* #include "config.h" */ +#include +#include + +/* Uncomment this to use openssl's SHA256 routines (and link with -lcrypto) */ +/*#define CCAN_CRYPTO_SHA256_USE_OPENSSL 1*/ + +#ifdef CCAN_CRYPTO_SHA256_USE_OPENSSL +#include +#endif + +/** + * struct sha256 - structure representing a completed SHA256. + * @u.u8: an unsigned char array. + * @u.u32: a 32-bit integer array. + * + * Other fields may be added to the union in future. + */ +struct sha256 { + union { + uint32_t u32[8]; + unsigned char u8[32]; + } u; +}; + +/** + * sha256 - return sha256 of an object. + * @sha256: the sha256 to fill in + * @p: pointer to memory, + * @size: the number of bytes pointed to by @p + * + * The bytes pointed to by @p is SHA256 hashed into @sha256. This is + * equivalent to sha256_init(), sha256_update() then sha256_done(). + */ +void sha256(struct sha256 *sha, const void *p, size_t size); + +/** + * struct sha256_ctx - structure to store running context for sha256 + */ +struct sha256_ctx { +#ifdef CCAN_CRYPTO_SHA256_USE_OPENSSL + SHA256_CTX c; +#else + uint32_t s[8]; + union { + uint32_t u32[16]; + unsigned char u8[64]; + } buf; + size_t bytes; +#endif +}; + +/** + * sha256_init - initialize an SHA256 context. + * @ctx: the sha256_ctx to initialize + * + * This must be called before sha256_update or sha256_done, or + * alternately you can assign SHA256_INIT. + * + * If it was already initialized, this forgets anything which was + * hashed before. + * + * Example: + * static void hash_all(const char **arr, struct sha256 *hash) + * { + * size_t i; + * struct sha256_ctx ctx; + * + * sha256_init(&ctx); + * for (i = 0; arr[i]; i++) + * sha256_update(&ctx, arr[i], strlen(arr[i])); + * sha256_done(&ctx, hash); + * } + */ +void sha256_init(struct sha256_ctx *ctx); + +/** + * SHA256_INIT - initializer for an SHA256 context. + * + * This can be used to statically initialize an SHA256 context (instead + * of sha256_init()). + * + * Example: + * static void hash_all(const char **arr, struct sha256 *hash) + * { + * size_t i; + * struct sha256_ctx ctx = SHA256_INIT; + * + * for (i = 0; arr[i]; i++) + * sha256_update(&ctx, arr[i], strlen(arr[i])); + * sha256_done(&ctx, hash); + * } + */ +#ifdef CCAN_CRYPTO_SHA256_USE_OPENSSL +#define SHA256_INIT \ + { { { 0x6a09e667ul, 0xbb67ae85ul, 0x3c6ef372ul, 0xa54ff53aul, \ + 0x510e527ful, 0x9b05688cul, 0x1f83d9abul, 0x5be0cd19ul }, \ + 0x0, 0x0, \ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, \ + 0x0, 0x20 } } +#else +#define SHA256_INIT \ + { { 0x6a09e667ul, 0xbb67ae85ul, 0x3c6ef372ul, 0xa54ff53aul, \ + 0x510e527ful, 0x9b05688cul, 0x1f83d9abul, 0x5be0cd19ul }, \ + { { 0 } }, 0 } +#endif + +/** + * sha256_update - include some memory in the hash. + * @ctx: the sha256_ctx to use + * @p: pointer to memory, + * @size: the number of bytes pointed to by @p + * + * You can call this multiple times to hash more data, before calling + * sha256_done(). + */ +void sha256_update(struct sha256_ctx *ctx, const void *p, size_t size); + +/** + * sha256_done - finish SHA256 and return the hash + * @ctx: the sha256_ctx to complete + * @res: the hash to return. + * + * Note that @ctx is *destroyed* by this, and must be reinitialized. + * To avoid that, pass a copy instead. + */ +void sha256_done(struct sha256_ctx *sha256, struct sha256 *res); + +/* Add various types to an SHA256 hash */ +void sha256_u8(struct sha256_ctx *ctx, uint8_t v); +void sha256_u16(struct sha256_ctx *ctx, uint16_t v); +void sha256_u32(struct sha256_ctx *ctx, uint32_t v); +void sha256_u64(struct sha256_ctx *ctx, uint64_t v); + +/* Add as little-endian */ +void sha256_le16(struct sha256_ctx *ctx, uint16_t v); +void sha256_le32(struct sha256_ctx *ctx, uint32_t v); +void sha256_le64(struct sha256_ctx *ctx, uint64_t v); + +/* Add as big-endian */ +void sha256_be16(struct sha256_ctx *ctx, uint16_t v); +void sha256_be32(struct sha256_ctx *ctx, uint32_t v); +void sha256_be64(struct sha256_ctx *ctx, uint64_t v); + +#endif /* CCAN_CRYPTO_SHA256_H */ diff --git a/node_modules/lnsocket/sha512.c b/node_modules/lnsocket/sha512.c new file mode 100644 index 0000000..1f866bb --- /dev/null +++ b/node_modules/lnsocket/sha512.c @@ -0,0 +1,261 @@ + +/* MIT (BSD) license - see LICENSE file for details */ +/* SHA512 core code translated from the Bitcoin project's C++: + * + * src/crypto/sha512.cpp commit f914f1a746d7f91951c1da262a4a749dd3ebfa71 + * Copyright (c) 2014 The Bitcoin Core developers + * Distributed under the MIT software license, see the accompanying + * file COPYING or http://www.opensource.org/licenses/mit-license.php. + */ +#include "sha512.h" +#include "endian.h" +#include "compiler.h" +#include +#include +#include + +static void invalidate_sha512(struct sha512_ctx *ctx) +{ +#ifdef CCAN_CRYPTO_SHA512_USE_OPENSSL + ctx->c.md_len = 0; +#else + ctx->bytes = (size_t)-1; +#endif +} + +static void check_sha512(struct sha512_ctx *ctx) +{ +#ifdef CCAN_CRYPTO_SHA512_USE_OPENSSL + assert(ctx->c.md_len != 0); +#else + assert(ctx->bytes != (size_t)-1); +#endif +} + +#ifdef CCAN_CRYPTO_SHA512_USE_OPENSSL +void sha512_init(struct sha512_ctx *ctx) +{ + SHA512_Init(&ctx->c); +} + +void sha512_update(struct sha512_ctx *ctx, const void *p, size_t size) +{ + check_sha512(ctx); + SHA512_Update(&ctx->c, p, size); +} + +void sha512_done(struct sha512_ctx *ctx, struct sha512 *res) +{ + SHA512_Final(res->u.u8, &ctx->c); + invalidate_sha512(ctx); +} +#else +static uint64_t Ch(uint64_t x, uint64_t y, uint64_t z) +{ + return z ^ (x & (y ^ z)); +} +static uint64_t Maj(uint64_t x, uint64_t y, uint64_t z) +{ + return (x & y) | (z & (x | y)); +} +static uint64_t Sigma0(uint64_t x) +{ + return (x >> 28 | x << 36) ^ (x >> 34 | x << 30) ^ (x >> 39 | x << 25); +} +static uint64_t Sigma1(uint64_t x) +{ + return (x >> 14 | x << 50) ^ (x >> 18 | x << 46) ^ (x >> 41 | x << 23); +} +static uint64_t sigma0(uint64_t x) +{ + return (x >> 1 | x << 63) ^ (x >> 8 | x << 56) ^ (x >> 7); +} +static uint64_t sigma1(uint64_t x) +{ + return (x >> 19 | x << 45) ^ (x >> 61 | x << 3) ^ (x >> 6); +} + +/** One round of SHA-512. */ +static void Round(uint64_t a, uint64_t b, uint64_t c, uint64_t *d, uint64_t e, uint64_t f, uint64_t g, uint64_t *h, uint64_t k, uint64_t w) +{ + uint64_t t1 = *h + Sigma1(e) + Ch(e, f, g) + k + w; + uint64_t t2 = Sigma0(a) + Maj(a, b, c); + *d += t1; + *h = t1 + t2; +} + +/** Perform one SHA-512 transformation, processing a 128-byte chunk. */ +static void Transform(uint64_t *s, const uint64_t *chunk) +{ + uint64_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7]; + uint64_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; + + Round(a, b, c, &d, e, f, g, &h, 0x428a2f98d728ae22ull, w0 = be64_to_cpu(chunk[0])); + Round(h, a, b, &c, d, e, f, &g, 0x7137449123ef65cdull, w1 = be64_to_cpu(chunk[1])); + Round(g, h, a, &b, c, d, e, &f, 0xb5c0fbcfec4d3b2full, w2 = be64_to_cpu(chunk[2])); + Round(f, g, h, &a, b, c, d, &e, 0xe9b5dba58189dbbcull, w3 = be64_to_cpu(chunk[3])); + Round(e, f, g, &h, a, b, c, &d, 0x3956c25bf348b538ull, w4 = be64_to_cpu(chunk[4])); + Round(d, e, f, &g, h, a, b, &c, 0x59f111f1b605d019ull, w5 = be64_to_cpu(chunk[5])); + Round(c, d, e, &f, g, h, a, &b, 0x923f82a4af194f9bull, w6 = be64_to_cpu(chunk[6])); + Round(b, c, d, &e, f, g, h, &a, 0xab1c5ed5da6d8118ull, w7 = be64_to_cpu(chunk[7])); + Round(a, b, c, &d, e, f, g, &h, 0xd807aa98a3030242ull, w8 = be64_to_cpu(chunk[8])); + Round(h, a, b, &c, d, e, f, &g, 0x12835b0145706fbeull, w9 = be64_to_cpu(chunk[9])); + Round(g, h, a, &b, c, d, e, &f, 0x243185be4ee4b28cull, w10 = be64_to_cpu(chunk[10])); + Round(f, g, h, &a, b, c, d, &e, 0x550c7dc3d5ffb4e2ull, w11 = be64_to_cpu(chunk[11])); + Round(e, f, g, &h, a, b, c, &d, 0x72be5d74f27b896full, w12 = be64_to_cpu(chunk[12])); + Round(d, e, f, &g, h, a, b, &c, 0x80deb1fe3b1696b1ull, w13 = be64_to_cpu(chunk[13])); + Round(c, d, e, &f, g, h, a, &b, 0x9bdc06a725c71235ull, w14 = be64_to_cpu(chunk[14])); + Round(b, c, d, &e, f, g, h, &a, 0xc19bf174cf692694ull, w15 = be64_to_cpu(chunk[15])); + + Round(a, b, c, &d, e, f, g, &h, 0xe49b69c19ef14ad2ull, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, &c, d, e, f, &g, 0xefbe4786384f25e3ull, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, &b, c, d, e, &f, 0x0fc19dc68b8cd5b5ull, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, &a, b, c, d, &e, 0x240ca1cc77ac9c65ull, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, &h, a, b, c, &d, 0x2de92c6f592b0275ull, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, &g, h, a, b, &c, 0x4a7484aa6ea6e483ull, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, &f, g, h, a, &b, 0x5cb0a9dcbd41fbd4ull, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, &e, f, g, h, &a, 0x76f988da831153b5ull, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, &d, e, f, g, &h, 0x983e5152ee66dfabull, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, &c, d, e, f, &g, 0xa831c66d2db43210ull, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, &b, c, d, e, &f, 0xb00327c898fb213full, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, &a, b, c, d, &e, 0xbf597fc7beef0ee4ull, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, &h, a, b, c, &d, 0xc6e00bf33da88fc2ull, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, &g, h, a, b, &c, 0xd5a79147930aa725ull, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, &f, g, h, a, &b, 0x06ca6351e003826full, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, &e, f, g, h, &a, 0x142929670a0e6e70ull, w15 += sigma1(w13) + w8 + sigma0(w0)); + + Round(a, b, c, &d, e, f, g, &h, 0x27b70a8546d22ffcull, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, &c, d, e, f, &g, 0x2e1b21385c26c926ull, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, &b, c, d, e, &f, 0x4d2c6dfc5ac42aedull, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, &a, b, c, d, &e, 0x53380d139d95b3dfull, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, &h, a, b, c, &d, 0x650a73548baf63deull, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, &g, h, a, b, &c, 0x766a0abb3c77b2a8ull, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, &f, g, h, a, &b, 0x81c2c92e47edaee6ull, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, &e, f, g, h, &a, 0x92722c851482353bull, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, &d, e, f, g, &h, 0xa2bfe8a14cf10364ull, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, &c, d, e, f, &g, 0xa81a664bbc423001ull, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, &b, c, d, e, &f, 0xc24b8b70d0f89791ull, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, &a, b, c, d, &e, 0xc76c51a30654be30ull, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, &h, a, b, c, &d, 0xd192e819d6ef5218ull, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, &g, h, a, b, &c, 0xd69906245565a910ull, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, &f, g, h, a, &b, 0xf40e35855771202aull, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, &e, f, g, h, &a, 0x106aa07032bbd1b8ull, w15 += sigma1(w13) + w8 + sigma0(w0)); + + Round(a, b, c, &d, e, f, g, &h, 0x19a4c116b8d2d0c8ull, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, &c, d, e, f, &g, 0x1e376c085141ab53ull, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, &b, c, d, e, &f, 0x2748774cdf8eeb99ull, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, &a, b, c, d, &e, 0x34b0bcb5e19b48a8ull, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, &h, a, b, c, &d, 0x391c0cb3c5c95a63ull, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, &g, h, a, b, &c, 0x4ed8aa4ae3418acbull, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, &f, g, h, a, &b, 0x5b9cca4f7763e373ull, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, &e, f, g, h, &a, 0x682e6ff3d6b2b8a3ull, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, &d, e, f, g, &h, 0x748f82ee5defb2fcull, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, &c, d, e, f, &g, 0x78a5636f43172f60ull, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, &b, c, d, e, &f, 0x84c87814a1f0ab72ull, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, &a, b, c, d, &e, 0x8cc702081a6439ecull, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, &h, a, b, c, &d, 0x90befffa23631e28ull, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, &g, h, a, b, &c, 0xa4506cebde82bde9ull, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, &f, g, h, a, &b, 0xbef9a3f7b2c67915ull, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, &e, f, g, h, &a, 0xc67178f2e372532bull, w15 += sigma1(w13) + w8 + sigma0(w0)); + + Round(a, b, c, &d, e, f, g, &h, 0xca273eceea26619cull, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, &c, d, e, f, &g, 0xd186b8c721c0c207ull, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, &b, c, d, e, &f, 0xeada7dd6cde0eb1eull, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, &a, b, c, d, &e, 0xf57d4f7fee6ed178ull, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, &h, a, b, c, &d, 0x06f067aa72176fbaull, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, &g, h, a, b, &c, 0x0a637dc5a2c898a6ull, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, &f, g, h, a, &b, 0x113f9804bef90daeull, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, &e, f, g, h, &a, 0x1b710b35131c471bull, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, &d, e, f, g, &h, 0x28db77f523047d84ull, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, &c, d, e, f, &g, 0x32caab7b40c72493ull, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, &b, c, d, e, &f, 0x3c9ebe0a15c9bebcull, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, &a, b, c, d, &e, 0x431d67c49c100d4cull, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, &h, a, b, c, &d, 0x4cc5d4becb3e42b6ull, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, &g, h, a, b, &c, 0x597f299cfc657e2aull, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, &f, g, h, a, &b, 0x5fcb6fab3ad6faecull, w14 + sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, &e, f, g, h, &a, 0x6c44198c4a475817ull, w15 + sigma1(w13) + w8 + sigma0(w0)); + + s[0] += a; + s[1] += b; + s[2] += c; + s[3] += d; + s[4] += e; + s[5] += f; + s[6] += g; + s[7] += h; +} + +static void add(struct sha512_ctx *ctx, const void *p, size_t len) +{ + const unsigned char *data = p; + size_t bufsize = ctx->bytes % 128; + + if (bufsize + len >= 128) { + /* Fill the buffer, and process it. */ + memcpy(ctx->buf.u8 + bufsize, data, 128 - bufsize); + ctx->bytes += 128 - bufsize; + data += 128 - bufsize; + len -= 128 - bufsize; + Transform(ctx->s, ctx->buf.u64); + bufsize = 0; + } + + while (len >= 128) { + /* Process full chunks directly from the source. */ + if (alignment_ok(data, sizeof(uint64_t))) + Transform(ctx->s, (const uint64_t *)data); + else { + memcpy(ctx->buf.u8, data, sizeof(ctx->buf)); + Transform(ctx->s, ctx->buf.u64); + } + ctx->bytes += 128; + data += 128; + len -= 128; + } + + if (len) { + /* Fill the buffer with what remains. */ + memcpy(ctx->buf.u8 + bufsize, data, len); + ctx->bytes += len; + } +} + +void sha512_init(struct sha512_ctx *ctx) +{ + struct sha512_ctx init = SHA512_INIT; + *ctx = init; +} + +void sha512_update(struct sha512_ctx *ctx, const void *p, size_t size) +{ + check_sha512(ctx); + add(ctx, p, size); +} + +void sha512_done(struct sha512_ctx *ctx, struct sha512 *res) +{ + static const unsigned char pad[128] = { 0x80 }; + uint64_t sizedesc[2] = { 0, 0 }; + size_t i; + + sizedesc[1] = cpu_to_be64((uint64_t)ctx->bytes << 3); + + /* Add '1' bit to terminate, then all 0 bits, up to next block - 16. */ + add(ctx, pad, 1 + ((256 - 16 - (ctx->bytes % 128) - 1) % 128)); + /* Add number of bits of data (big endian) */ + add(ctx, sizedesc, sizeof(sizedesc)); + for (i = 0; i < sizeof(ctx->s) / sizeof(ctx->s[0]); i++) + res->u.u64[i] = cpu_to_be64(ctx->s[i]); + invalidate_sha512(ctx); +} +#endif /* CCAN_CRYPTO_SHA512_USE_OPENSSL */ + +void sha512(struct sha512 *sha, const void *p, size_t size) +{ + struct sha512_ctx ctx; + + sha512_init(&ctx); + sha512_update(&ctx, p, size); + sha512_done(&ctx, sha); + memset(&ctx, 0, sizeof(ctx)); +} diff --git a/node_modules/lnsocket/sha512.h b/node_modules/lnsocket/sha512.h new file mode 100644 index 0000000..48cc47b --- /dev/null +++ b/node_modules/lnsocket/sha512.h @@ -0,0 +1,138 @@ + +#ifndef CCAN_CRYPTO_SHA512_H +#define CCAN_CRYPTO_SHA512_H +/* BSD-MIT - see LICENSE file for details */ +#include +#include + +/** Output length for `wally_sha512` */ +#define SHA512_LEN 64 + +/* Uncomment this to use openssl's SHA512 routines (and link with -lcrypto) */ +/*#define CCAN_CRYPTO_SHA512_USE_OPENSSL 1*/ + +#ifdef CCAN_CRYPTO_SHA512_USE_OPENSSL +#include +#endif + +/** + * struct sha512 - structure representing a completed SHA512. + * @u.u8: an unsigned char array. + * @u.u64: a 64-bit integer array. + * + * Other fields may be added to the union in future. + */ +struct sha512 { + union { + uint64_t u64[8]; + unsigned char u8[64]; + } u; +}; + +/** + * sha512 - return sha512 of an object. + * @sha512: the sha512 to fill in + * @p: pointer to memory, + * @size: the number of bytes pointed to by @p + * + * The bytes pointed to by @p is SHA512 hashed into @sha512. This is + * equivalent to sha512_init(), sha512_update() then sha512_done(). + */ +void sha512(struct sha512 *sha, const void *p, size_t size); + +/** + * struct sha512_ctx - structure to store running context for sha512 + */ +struct sha512_ctx { +#ifdef CCAN_CRYPTO_SHA512_USE_OPENSSL + SHA512_CTX c; +#else + uint64_t s[8]; + union { + uint64_t u64[16]; + unsigned char u8[128]; + } buf; + size_t bytes; +#endif +}; + +/** + * sha512_init - initialize an SHA512 context. + * @ctx: the sha512_ctx to initialize + * + * This must be called before sha512_update or sha512_done, or + * alternately you can assign SHA512_INIT. + * + * If it was already initialized, this forgets anything which was + * hashed before. + * + * Example: + * static void hash_all(const char **arr, struct sha512 *hash) + * { + * size_t i; + * struct sha512_ctx ctx; + * + * sha512_init(&ctx); + * for (i = 0; arr[i]; i++) + * sha512_update(&ctx, arr[i], strlen(arr[i])); + * sha512_done(&ctx, hash); + * } + */ +void sha512_init(struct sha512_ctx *ctx); + +/** + * SHA512_INIT - initializer for an SHA512 context. + * + * This can be used to statically initialize an SHA512 context (instead + * of sha512_init()). + * + * Example: + * static void hash_all(const char **arr, struct sha512 *hash) + * { + * size_t i; + * struct sha512_ctx ctx = SHA512_INIT; + * + * for (i = 0; arr[i]; i++) + * sha512_update(&ctx, arr[i], strlen(arr[i])); + * sha512_done(&ctx, hash); + * } + */ +#ifdef CCAN_CRYPTO_SHA512_USE_OPENSSL + { { { 0x6a09e667f3bcc908ull, 0xbb67ae8584caa73bull, \ + 0x3c6ef372fe94f82bull, 0xa54ff53a5f1d36f1ull, \ + 0x510e527fade682d1ull, 0x9b05688c2b3e6c1full, \ + 0x1f83d9abfb41bd6bull, 0x5be0cd19137e2179ull }, \ + 0, 0, \ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, \ + 0, 0x40 } } +#else +#define SHA512_INIT \ + { { 0x6a09e667f3bcc908ull, 0xbb67ae8584caa73bull, \ + 0x3c6ef372fe94f82bull, 0xa54ff53a5f1d36f1ull, \ + 0x510e527fade682d1ull, 0x9b05688c2b3e6c1full, \ + 0x1f83d9abfb41bd6bull, 0x5be0cd19137e2179ull }, \ + { { 0 } }, 0 } +#endif + +/** + * sha512_update - include some memory in the hash. + * @ctx: the sha512_ctx to use + * @p: pointer to memory, + * @size: the number of bytes pointed to by @p + * + * You can call this multiple times to hash more data, before calling + * sha512_done(). + */ +void sha512_update(struct sha512_ctx *ctx, const void *p, size_t size); + +/** + * sha512_done - finish SHA512 and return the hash + * @ctx: the sha512_ctx to complete + * @res: the hash to return. + * + * Note that @ctx is *destroyed* by this, and must be reinitialized. + * To avoid that, pass a copy instead. + */ +void sha512_done(struct sha512_ctx *sha512, struct sha512 *res); + +#endif /* CCAN_CRYPTO_SHA512_H */ diff --git a/node_modules/lnsocket/shell.nix b/node_modules/lnsocket/shell.nix new file mode 100644 index 0000000..694fd2d --- /dev/null +++ b/node_modules/lnsocket/shell.nix @@ -0,0 +1,5 @@ +{ pkgs ? import {} }: +pkgs.mkShell { + buildInputs = [ ]; + nativeBuildInputs = with pkgs; [ gdb autoreconfHook emscripten wabt go ]; +} diff --git a/node_modules/lnsocket/test.c b/node_modules/lnsocket/test.c new file mode 100644 index 0000000..4e8c161 --- /dev/null +++ b/node_modules/lnsocket/test.c @@ -0,0 +1,59 @@ + +#include "lnsocket.h" +#include "endian.h" +#include "typedefs.h" +#include +#include + +static void print_data(unsigned char *buf, int len) +{ + int i; + + for (i = 0; i < len; i++) { + printf("%02x", buf[i]); + } + printf("\n"); +} + +int main(int argc, const char *argv[]) +{ + static u8 msgbuf[4096]; + u8 *buf; + struct lnsocket *ln; + + u16 len; + int ok = 1; + + ln = lnsocket_create(); + assert(ln); + + lnsocket_genkey(ln); + + const char *nodeid = "03f3c108ccd536b8526841f0a5c58212bb9e6584a1eb493080e7c1cc34f82dad71"; + if (!(ok = lnsocket_connect(ln, nodeid, "24.84.152.187"))) + goto done; + + if (!(ok = lnsocket_perform_init(ln))) + goto done; + + printf("init ok!\n"); + + if (!(ok = len = lnsocket_make_ping_msg(msgbuf, sizeof(msgbuf), 1, 1))) + goto done; + + if (!(ok = lnsocket_write(ln, msgbuf, len))) + goto done; + + printf("sent ping "); + print_data(msgbuf, len); + + if (!(ok = lnsocket_read(ln, &buf, &len))) + goto done; + + printf("got "); + print_data(buf, len); +done: + lnsocket_print_errors(ln); + lnsocket_destroy(ln); + return !ok; +} diff --git a/node_modules/lnsocket/tools/0001-configure-customizable-AR-and-RANLIB.patch b/node_modules/lnsocket/tools/0001-configure-customizable-AR-and-RANLIB.patch new file mode 100644 index 0000000..c606d89 --- /dev/null +++ b/node_modules/lnsocket/tools/0001-configure-customizable-AR-and-RANLIB.patch @@ -0,0 +1,67 @@ +From 0d253d52e804a5affb0f1c851ec250071e7345d9 Mon Sep 17 00:00:00 2001 +From: Tim Ruffing +Date: Sun, 13 Mar 2022 10:39:55 +0100 +Subject: [PATCH] configure: Use modern way to set AR + +This uses AM_PROG_AR to discover ar, which is the recommended way to do +so. Among other advantages, it honors the AR environment variable (as +set from the outside). The macro has been around since automake 1.11.2 +(Dec 2011). + +This commit also removes code that discovers ranlib and strip. ranlib +has been obsolete for decades (ar does its task now automatically), and +anyway LT_INIT takes care of discovering it. The code we used to set +STRIP was last mentioned in the automake 1.5 manual. Since automake 1.6 +(Mar 2002), strip is discovered automatically when necessary (look for +the *private* macro AM_PROG_INSTALL_STRIP in the automake manual). +--- + .gitignore | 1 + + configure.ac | 11 +++++------ + 2 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/.gitignore b/.gitignore +index 53941f23a..d88627d72 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -46,6 +46,7 @@ coverage.*.html + + src/libsecp256k1-config.h + src/libsecp256k1-config.h.in ++build-aux/ar-lib + build-aux/config.guess + build-aux/config.sub + build-aux/depcomp +diff --git a/configure.ac b/configure.ac +index cc766b20a..16a492071 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -25,24 +25,23 @@ AC_CANONICAL_HOST + AH_TOP([#ifndef LIBSECP256K1_CONFIG_H]) + AH_TOP([#define LIBSECP256K1_CONFIG_H]) + AH_BOTTOM([#endif /*LIBSECP256K1_CONFIG_H*/]) +-AM_INIT_AUTOMAKE([foreign subdir-objects]) + +-LT_INIT([win32-dll]) ++# Require Automake 1.11.2 for AM_PROG_AR ++AM_INIT_AUTOMAKE([1.11.2 foreign subdir-objects]) + + # Make the compilation flags quiet unless V=1 is used. + m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + + PKG_PROG_PKG_CONFIG + +-AC_PATH_TOOL(AR, ar) +-AC_PATH_TOOL(RANLIB, ranlib) +-AC_PATH_TOOL(STRIP, strip) +- + AC_PROG_CC + if test x"$ac_cv_prog_cc_c89" = x"no"; then + AC_MSG_ERROR([c89 compiler support required]) + fi + AM_PROG_AS ++AM_PROG_AR ++ ++LT_INIT([win32-dll]) + + build_windows=no + diff --git a/node_modules/lnsocket/tools/refresh-submodules.sh b/node_modules/lnsocket/tools/refresh-submodules.sh new file mode 100755 index 0000000..bedb8f3 --- /dev/null +++ b/node_modules/lnsocket/tools/refresh-submodules.sh @@ -0,0 +1,42 @@ +#! /bin/sh + +if [ $# = 0 ]; then + echo "Usage: $0 ..." >&2 + exit 1 +fi + +# If no git dir (or, if we're a submodule, git file), forget it. +[ -e .git ] || exit 0 + +# git submodule can't run in parallel. Really. +# Wait for it to finish if in parallel. +if ! mkdir .refresh-submodules 2>/dev/null ; then + # If we don't make progress in ~60 seconds, force delete and retry. + LIMIT=$((50 + $$ % 20)) + i=0 + while [ $i -lt $LIMIT ]; do + [ -d .refresh-submodules ] || exit 0 + sleep 1 + i=$((i + 1)) + done + rmdir .refresh-submodules + exec "$0" "$@" || exit 1 +fi + +trap "rmdir .refresh-submodules" EXIT + +# Be a little careful here, since we do rm -rf! +for m in "$@"; do + if ! grep -q "path = $m\$" .gitmodules; then + echo "$m is not a submodule!" >&2 + exit 1 + fi +done + +# git submodule can segfault. Really. +if [ "$(git submodule status "$@" | grep -c '^ ')" != $# ]; then + echo Reinitializing submodules "$@" ... + git submodule sync "$@" + rm -rf "$@" + git submodule update --init --recursive "$@" +fi diff --git a/node_modules/lnsocket/tools/secp-ios.sh b/node_modules/lnsocket/tools/secp-ios.sh new file mode 100755 index 0000000..3fa58a5 --- /dev/null +++ b/node_modules/lnsocket/tools/secp-ios.sh @@ -0,0 +1,74 @@ +#! /usr/bin/env bash +# +# Step 1. +# Configure for base system so simulator is covered +# +# Step 2. +# Make for iOS and iOS simulator +# +# Step 3. +# Merge libs into final version for xcode import + +cd deps/secp256k1 + +export PREFIX="$(pwd)/libsecp256k1-ios" +export IOS64_PREFIX="$PREFIX/tmp/ios64" +export SIMULATOR64_PREFIX="$PREFIX/tmp/simulator64" +export XCODEDIR=$(xcode-select -p) +export IOS_SIMULATOR_VERSION_MIN=${IOS_SIMULATOR_VERSION_MIN-"6.0.0"} +export IOS_VERSION_MIN=${IOS_VERSION_MIN-"6.0.0"} + +mkdir -p $SIMULATOR64_PREFIX $IOS64_PREFIX || exit 1 + +# Build for the simulator +export BASEDIR="${XCODEDIR}/Platforms/iPhoneSimulator.platform/Developer" +export PATH="${BASEDIR}/usr/bin:$BASEDIR/usr/sbin:$PATH" +export SDK="${BASEDIR}/SDKs/iPhoneSimulator.sdk" + +## x86_64 simulator +export CFLAGS="-O2 -arch x86_64 -isysroot ${SDK} -mios-simulator-version-min=${IOS_SIMULATOR_VERSION_MIN} -flto" +export LDFLAGS="-arch x86_64 -isysroot ${SDK} -mios-simulator-version-min=${IOS_SIMULATOR_VERSION_MIN} -flto" + +make distclean > /dev/null + +./configure --host=x86_64-apple-darwin10 \ + --disable-shared \ + --enable-module-ecdh \ + --prefix="$SIMULATOR64_PREFIX" + +make -j3 install || exit 1 + +# Build for iOS +export BASEDIR="${XCODEDIR}/Platforms/iPhoneOS.platform/Developer" +export PATH="${BASEDIR}/usr/bin:$BASEDIR/usr/sbin:$PATH" +export SDK="${BASEDIR}/SDKs/iPhoneOS.sdk" + +## 64-bit iOS +export CFLAGS="-O2 -arch arm64 -isysroot ${SDK} -mios-version-min=${IOS_VERSION_MIN} -flto -fembed-bitcode" +export LDFLAGS="-arch arm64 -isysroot ${SDK} -mios-version-min=${IOS_VERSION_MIN} -flto -fembed-bitcode" + +make distclean > /dev/null + +./configure --host=arm-apple-darwin10 \ + --disable-shared \ + --enable-module-ecdh \ + --prefix="$IOS64_PREFIX" || exit 1 + +make -j3 install || exit 1 + +# Create universal binary and include folder +rm -fr -- "$PREFIX/include" "$PREFIX/libsecp256k1.a" 2> /dev/null +mkdir -p -- "$PREFIX/lib" +lipo -create \ + "$SIMULATOR64_PREFIX/lib/libsecp256k1.a" \ + "$IOS64_PREFIX/lib/libsecp256k1.a" \ + -output "$PREFIX/lib/libsecp256k1.a" + +echo +echo "libsecp256k1 has been installed into $PREFIX" +echo +file -- "$PREFIX/lib/libsecp256k1.a" + +# Cleanup +rm -rf -- "$PREFIX/tmp" +make distclean > /dev/null diff --git a/node_modules/lnsocket/tools/secp-wasm.sh b/node_modules/lnsocket/tools/secp-wasm.sh new file mode 100755 index 0000000..59a7322 --- /dev/null +++ b/node_modules/lnsocket/tools/secp-wasm.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +cd deps/secp256k1 + +export CC=emcc +export AR=emar +export RANLIB=emranlib + +export PREFIX="$(pwd)/libsecp256k1-wasm" + +mkdir -p $PREFIX || exit 1 + +make distclean > /dev/null + +patch -N -p1 < ../../tools/0001-configure-customizable-AR-and-RANLIB.patch + +./configure --disable-shared \ + --disable-tests \ + --disable-exhaustive-tests \ + --disable-benchmark \ + --enable-module-ecdh \ + --prefix="$PREFIX" + +make -j3 install || exit 1 + +rm -rf -- "$PREFIX/tmp" +make distclean > /dev/null diff --git a/node_modules/lnsocket/typedefs.h b/node_modules/lnsocket/typedefs.h new file mode 100644 index 0000000..7996b87 --- /dev/null +++ b/node_modules/lnsocket/typedefs.h @@ -0,0 +1,13 @@ + +#ifndef LNSOCKET_TYPES_H +#define LNSOCKET_TYPES_H +#include + +typedef unsigned char u8; +typedef unsigned int u32; +typedef unsigned short u16; +typedef uint64_t u64; +typedef int64_t s64; + + +#endif /* LNSOCKET_TYPES_H */ diff --git a/node_modules/lnsocket/varint.c b/node_modules/lnsocket/varint.c new file mode 100644 index 0000000..aca37ce --- /dev/null +++ b/node_modules/lnsocket/varint.c @@ -0,0 +1,75 @@ + +#include "varint.h" + +size_t varint_size(uint64_t v) +{ + if (v < 0xfd) + return 1; + if (v <= 0xffff) + return 3; + if (v <= 0xffffffff) + return 5; + return 9; +} + +size_t varint_put(unsigned char buf[VARINT_MAX_LEN], uint64_t v) +{ + unsigned char *p = buf; + + if (v < 0xfd) { + *(p++) = v; + } else if (v <= 0xffff) { + (*p++) = 0xfd; + (*p++) = v; + (*p++) = v >> 8; + } else if (v <= 0xffffffff) { + (*p++) = 0xfe; + (*p++) = v; + (*p++) = v >> 8; + (*p++) = v >> 16; + (*p++) = v >> 24; + } else { + (*p++) = 0xff; + (*p++) = v; + (*p++) = v >> 8; + (*p++) = v >> 16; + (*p++) = v >> 24; + (*p++) = v >> 32; + (*p++) = v >> 40; + (*p++) = v >> 48; + (*p++) = v >> 56; + } + return p - buf; +} + +size_t varint_get(const unsigned char *p, size_t max, int64_t *val) +{ + if (max < 1) + return 0; + + switch (*p) { + case 0xfd: + if (max < 3) + return 0; + *val = ((uint64_t)p[2] << 8) + p[1]; + return 3; + case 0xfe: + if (max < 5) + return 0; + *val = ((uint64_t)p[4] << 24) + ((uint64_t)p[3] << 16) + + ((uint64_t)p[2] << 8) + p[1]; + return 5; + case 0xff: + if (max < 9) + return 0; + *val = ((uint64_t)p[8] << 56) + ((uint64_t)p[7] << 48) + + ((uint64_t)p[6] << 40) + ((uint64_t)p[5] << 32) + + ((uint64_t)p[4] << 24) + ((uint64_t)p[3] << 16) + + ((uint64_t)p[2] << 8) + p[1]; + return 9; + default: + *val = *p; + return 1; + } +} + diff --git a/node_modules/lnsocket/varint.h b/node_modules/lnsocket/varint.h new file mode 100644 index 0000000..1f093f7 --- /dev/null +++ b/node_modules/lnsocket/varint.h @@ -0,0 +1,14 @@ + +#ifndef LNSOCKET_VARINT_H +#define LNSOCKET_VARINT_H + +#define VARINT_MAX_LEN 9 + +#include +#include + +size_t varint_put(unsigned char buf[VARINT_MAX_LEN], uint64_t v); +size_t varint_size(uint64_t v); +size_t varint_get(const unsigned char *p, size_t max, int64_t *val); + +#endif /* LNSOCKET_VARINT_H */ diff --git a/node_modules/mkdirp/.npmignore b/node_modules/mkdirp/.npmignore new file mode 100644 index 0000000..9303c34 --- /dev/null +++ b/node_modules/mkdirp/.npmignore @@ -0,0 +1,2 @@ +node_modules/ +npm-debug.log \ No newline at end of file diff --git a/node_modules/mkdirp/.travis.yml b/node_modules/mkdirp/.travis.yml new file mode 100644 index 0000000..84fd7ca --- /dev/null +++ b/node_modules/mkdirp/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - 0.6 + - 0.8 + - 0.9 diff --git a/node_modules/mkdirp/LICENSE b/node_modules/mkdirp/LICENSE new file mode 100644 index 0000000..432d1ae --- /dev/null +++ b/node_modules/mkdirp/LICENSE @@ -0,0 +1,21 @@ +Copyright 2010 James Halliday (mail@substack.net) + +This project is free software released under the MIT/X11 license: + +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/mkdirp/examples/pow.js b/node_modules/mkdirp/examples/pow.js new file mode 100644 index 0000000..e692421 --- /dev/null +++ b/node_modules/mkdirp/examples/pow.js @@ -0,0 +1,6 @@ +var mkdirp = require('mkdirp'); + +mkdirp('/tmp/foo/bar/baz', function (err) { + if (err) console.error(err) + else console.log('pow!') +}); diff --git a/node_modules/mkdirp/index.js b/node_modules/mkdirp/index.js new file mode 100644 index 0000000..fda6de8 --- /dev/null +++ b/node_modules/mkdirp/index.js @@ -0,0 +1,82 @@ +var path = require('path'); +var fs = require('fs'); + +module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP; + +function mkdirP (p, mode, f, made) { + if (typeof mode === 'function' || mode === undefined) { + f = mode; + mode = 0777 & (~process.umask()); + } + if (!made) made = null; + + var cb = f || function () {}; + if (typeof mode === 'string') mode = parseInt(mode, 8); + p = path.resolve(p); + + fs.mkdir(p, mode, function (er) { + if (!er) { + made = made || p; + return cb(null, made); + } + switch (er.code) { + case 'ENOENT': + mkdirP(path.dirname(p), mode, function (er, made) { + if (er) cb(er, made); + else mkdirP(p, mode, cb, made); + }); + break; + + // In the case of any other error, just see if there's a dir + // there already. If so, then hooray! If not, then something + // is borked. + default: + fs.stat(p, function (er2, stat) { + // if the stat fails, then that's super weird. + // let the original error be the failure reason. + if (er2 || !stat.isDirectory()) cb(er, made) + else cb(null, made); + }); + break; + } + }); +} + +mkdirP.sync = function sync (p, mode, made) { + if (mode === undefined) { + mode = 0777 & (~process.umask()); + } + if (!made) made = null; + + if (typeof mode === 'string') mode = parseInt(mode, 8); + p = path.resolve(p); + + try { + fs.mkdirSync(p, mode); + made = made || p; + } + catch (err0) { + switch (err0.code) { + case 'ENOENT' : + made = sync(path.dirname(p), mode, made); + sync(p, mode, made); + break; + + // In the case of any other error, just see if there's a dir + // there already. If so, then hooray! If not, then something + // is borked. + default: + var stat; + try { + stat = fs.statSync(p); + } + catch (err1) { + throw err0; + } + if (!stat.isDirectory()) throw err0; + break; + } + } + + return made; +}; diff --git a/node_modules/mkdirp/package.json b/node_modules/mkdirp/package.json new file mode 100644 index 0000000..8aa64fe --- /dev/null +++ b/node_modules/mkdirp/package.json @@ -0,0 +1,22 @@ +{ + "name" : "mkdirp", + "description" : "Recursively mkdir, like `mkdir -p`", + "version" : "0.3.5", + "author" : "James Halliday (http://substack.net)", + "main" : "./index", + "keywords" : [ + "mkdir", + "directory" + ], + "repository" : { + "type" : "git", + "url" : "http://github.com/substack/node-mkdirp.git" + }, + "scripts" : { + "test" : "tap test/*.js" + }, + "devDependencies" : { + "tap" : "~0.4.0" + }, + "license" : "MIT" +} diff --git a/node_modules/mkdirp/readme.markdown b/node_modules/mkdirp/readme.markdown new file mode 100644 index 0000000..83b0216 --- /dev/null +++ b/node_modules/mkdirp/readme.markdown @@ -0,0 +1,63 @@ +# mkdirp + +Like `mkdir -p`, but in node.js! + +[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp) + +# example + +## pow.js + +```js +var mkdirp = require('mkdirp'); + +mkdirp('/tmp/foo/bar/baz', function (err) { + if (err) console.error(err) + else console.log('pow!') +}); +``` + +Output + +``` +pow! +``` + +And now /tmp/foo/bar/baz exists, huzzah! + +# methods + +```js +var mkdirp = require('mkdirp'); +``` + +## mkdirp(dir, mode, cb) + +Create a new directory and any necessary subdirectories at `dir` with octal +permission string `mode`. + +If `mode` isn't specified, it defaults to `0777 & (~process.umask())`. + +`cb(err, made)` fires with the error or the first directory `made` +that had to be created, if any. + +## mkdirp.sync(dir, mode) + +Synchronously create a new directory and any necessary subdirectories at `dir` +with octal permission string `mode`. + +If `mode` isn't specified, it defaults to `0777 & (~process.umask())`. + +Returns the first directory that had to be created, if any. + +# install + +With [npm](http://npmjs.org) do: + +``` +npm install mkdirp +``` + +# license + +MIT diff --git a/node_modules/mkdirp/test/chmod.js b/node_modules/mkdirp/test/chmod.js new file mode 100644 index 0000000..520dcb8 --- /dev/null +++ b/node_modules/mkdirp/test/chmod.js @@ -0,0 +1,38 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +var ps = [ '', 'tmp' ]; + +for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); +} + +var file = ps.join('/'); + +test('chmod-pre', function (t) { + var mode = 0744 + mkdirp(file, mode, function (er) { + t.ifError(er, 'should not error'); + fs.stat(file, function (er, stat) { + t.ifError(er, 'should exist'); + t.ok(stat && stat.isDirectory(), 'should be directory'); + t.equal(stat && stat.mode & 0777, mode, 'should be 0744'); + t.end(); + }); + }); +}); + +test('chmod', function (t) { + var mode = 0755 + mkdirp(file, mode, function (er) { + t.ifError(er, 'should not error'); + fs.stat(file, function (er, stat) { + t.ifError(er, 'should exist'); + t.ok(stat && stat.isDirectory(), 'should be directory'); + t.end(); + }); + }); +}); diff --git a/node_modules/mkdirp/test/clobber.js b/node_modules/mkdirp/test/clobber.js new file mode 100644 index 0000000..0eb7099 --- /dev/null +++ b/node_modules/mkdirp/test/clobber.js @@ -0,0 +1,37 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +var ps = [ '', 'tmp' ]; + +for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); +} + +var file = ps.join('/'); + +// a file in the way +var itw = ps.slice(0, 3).join('/'); + + +test('clobber-pre', function (t) { + console.error("about to write to "+itw) + fs.writeFileSync(itw, 'I AM IN THE WAY, THE TRUTH, AND THE LIGHT.'); + + fs.stat(itw, function (er, stat) { + t.ifError(er) + t.ok(stat && stat.isFile(), 'should be file') + t.end() + }) +}) + +test('clobber', function (t) { + t.plan(2); + mkdirp(file, 0755, function (err) { + t.ok(err); + t.equal(err.code, 'ENOTDIR'); + t.end(); + }); +}); diff --git a/node_modules/mkdirp/test/mkdirp.js b/node_modules/mkdirp/test/mkdirp.js new file mode 100644 index 0000000..b07cd70 --- /dev/null +++ b/node_modules/mkdirp/test/mkdirp.js @@ -0,0 +1,28 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('woo', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); diff --git a/node_modules/mkdirp/test/perm.js b/node_modules/mkdirp/test/perm.js new file mode 100644 index 0000000..23a7abb --- /dev/null +++ b/node_modules/mkdirp/test/perm.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('async perm', function (t) { + t.plan(2); + var file = '/tmp/' + (Math.random() * (1<<30)).toString(16); + + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); + +test('async root perm', function (t) { + mkdirp('/tmp', 0755, function (err) { + if (err) t.fail(err); + t.end(); + }); + t.end(); +}); diff --git a/node_modules/mkdirp/test/perm_sync.js b/node_modules/mkdirp/test/perm_sync.js new file mode 100644 index 0000000..f685f60 --- /dev/null +++ b/node_modules/mkdirp/test/perm_sync.js @@ -0,0 +1,39 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('sync perm', function (t) { + t.plan(2); + var file = '/tmp/' + (Math.random() * (1<<30)).toString(16) + '.json'; + + mkdirp.sync(file, 0755); + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }); +}); + +test('sync root perm', function (t) { + t.plan(1); + + var file = '/tmp'; + mkdirp.sync(file, 0755); + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }); +}); diff --git a/node_modules/mkdirp/test/race.js b/node_modules/mkdirp/test/race.js new file mode 100644 index 0000000..96a0447 --- /dev/null +++ b/node_modules/mkdirp/test/race.js @@ -0,0 +1,41 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('race', function (t) { + t.plan(4); + var ps = [ '', 'tmp' ]; + + for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); + } + var file = ps.join('/'); + + var res = 2; + mk(file, function () { + if (--res === 0) t.end(); + }); + + mk(file, function () { + if (--res === 0) t.end(); + }); + + function mk (file, cb) { + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + if (cb) cb(); + } + }) + }) + }); + } +}); diff --git a/node_modules/mkdirp/test/rel.js b/node_modules/mkdirp/test/rel.js new file mode 100644 index 0000000..7985824 --- /dev/null +++ b/node_modules/mkdirp/test/rel.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('rel', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var cwd = process.cwd(); + process.chdir('/tmp'); + + var file = [x,y,z].join('/'); + + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + process.chdir(cwd); + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); diff --git a/node_modules/mkdirp/test/return.js b/node_modules/mkdirp/test/return.js new file mode 100644 index 0000000..bce68e5 --- /dev/null +++ b/node_modules/mkdirp/test/return.js @@ -0,0 +1,25 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('return value', function (t) { + t.plan(4); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + // should return the first dir created. + // By this point, it would be profoundly surprising if /tmp didn't + // already exist, since every other test makes things in there. + mkdirp(file, function (err, made) { + t.ifError(err); + t.equal(made, '/tmp/' + x); + mkdirp(file, function (err, made) { + t.ifError(err); + t.equal(made, null); + }); + }); +}); diff --git a/node_modules/mkdirp/test/return_sync.js b/node_modules/mkdirp/test/return_sync.js new file mode 100644 index 0000000..7c222d3 --- /dev/null +++ b/node_modules/mkdirp/test/return_sync.js @@ -0,0 +1,24 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('return value', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + // should return the first dir created. + // By this point, it would be profoundly surprising if /tmp didn't + // already exist, since every other test makes things in there. + // Note that this will throw on failure, which will fail the test. + var made = mkdirp.sync(file); + t.equal(made, '/tmp/' + x); + + // making the same file again should have no effect. + made = mkdirp.sync(file); + t.equal(made, null); +}); diff --git a/node_modules/mkdirp/test/root.js b/node_modules/mkdirp/test/root.js new file mode 100644 index 0000000..97ad7a2 --- /dev/null +++ b/node_modules/mkdirp/test/root.js @@ -0,0 +1,18 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('root', function (t) { + // '/' on unix, 'c:/' on windows. + var file = path.resolve('/'); + + mkdirp(file, 0755, function (err) { + if (err) throw err + fs.stat(file, function (er, stat) { + if (er) throw er + t.ok(stat.isDirectory(), 'target is a directory'); + t.end(); + }) + }); +}); diff --git a/node_modules/mkdirp/test/sync.js b/node_modules/mkdirp/test/sync.js new file mode 100644 index 0000000..7530cad --- /dev/null +++ b/node_modules/mkdirp/test/sync.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('sync', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + try { + mkdirp.sync(file, 0755); + } catch (err) { + t.fail(err); + return t.end(); + } + + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }); + }); +}); diff --git a/node_modules/mkdirp/test/umask.js b/node_modules/mkdirp/test/umask.js new file mode 100644 index 0000000..64ccafe --- /dev/null +++ b/node_modules/mkdirp/test/umask.js @@ -0,0 +1,28 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('implicit mode from umask', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + mkdirp(file, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0777 & (~process.umask())); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); diff --git a/node_modules/mkdirp/test/umask_sync.js b/node_modules/mkdirp/test/umask_sync.js new file mode 100644 index 0000000..35bd5cb --- /dev/null +++ b/node_modules/mkdirp/test/umask_sync.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('umask sync modes', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + try { + mkdirp.sync(file); + } catch (err) { + t.fail(err); + return t.end(); + } + + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, (0777 & (~process.umask()))); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }); + }); +}); diff --git a/node_modules/nopt/.npmignore b/node_modules/nopt/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/node_modules/nopt/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/nopt/LICENSE b/node_modules/nopt/LICENSE new file mode 100644 index 0000000..05a4010 --- /dev/null +++ b/node_modules/nopt/LICENSE @@ -0,0 +1,23 @@ +Copyright 2009, 2010, 2011 Isaac Z. Schlueter. +All rights reserved. + +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/nopt/README.md b/node_modules/nopt/README.md new file mode 100644 index 0000000..96798a1 --- /dev/null +++ b/node_modules/nopt/README.md @@ -0,0 +1,210 @@ +If you want to write an option parser, and have it be good, there are +two ways to do it. The Right Way, and the Wrong Way. + +The Wrong Way is to sit down and write an option parser. We've all done +that. + +The Right Way is to write some complex configurable program with so many +options that you go half-insane just trying to manage them all, and put +it off with duct-tape solutions until you see exactly to the core of the +problem, and finally snap and write an awesome option parser. + +If you want to write an option parser, don't write an option parser. +Write a package manager, or a source control system, or a service +restarter, or an operating system. You probably won't end up with a +good one of those, but if you don't give up, and you are relentless and +diligent enough in your procrastination, you may just end up with a very +nice option parser. + +## USAGE + + // my-program.js + var nopt = require("nopt") + , Stream = require("stream").Stream + , path = require("path") + , knownOpts = { "foo" : [String, null] + , "bar" : [Stream, Number] + , "baz" : path + , "bloo" : [ "big", "medium", "small" ] + , "flag" : Boolean + , "pick" : Boolean + , "many" : [String, Array] + } + , shortHands = { "foofoo" : ["--foo", "Mr. Foo"] + , "b7" : ["--bar", "7"] + , "m" : ["--bloo", "medium"] + , "p" : ["--pick"] + , "f" : ["--flag"] + } + // everything is optional. + // knownOpts and shorthands default to {} + // arg list defaults to process.argv + // slice defaults to 2 + , parsed = nopt(knownOpts, shortHands, process.argv, 2) + console.log(parsed) + +This would give you support for any of the following: + +```bash +$ node my-program.js --foo "blerp" --no-flag +{ "foo" : "blerp", "flag" : false } + +$ node my-program.js ---bar 7 --foo "Mr. Hand" --flag +{ bar: 7, foo: "Mr. Hand", flag: true } + +$ node my-program.js --foo "blerp" -f -----p +{ foo: "blerp", flag: true, pick: true } + +$ node my-program.js -fp --foofoo +{ foo: "Mr. Foo", flag: true, pick: true } + +$ node my-program.js --foofoo -- -fp # -- stops the flag parsing. +{ foo: "Mr. Foo", argv: { remain: ["-fp"] } } + +$ node my-program.js --blatzk -fp # unknown opts are ok. +{ blatzk: true, flag: true, pick: true } + +$ node my-program.js --blatzk=1000 -fp # but you need to use = if they have a value +{ blatzk: 1000, flag: true, pick: true } + +$ node my-program.js --no-blatzk -fp # unless they start with "no-" +{ blatzk: false, flag: true, pick: true } + +$ node my-program.js --baz b/a/z # known paths are resolved. +{ baz: "/Users/isaacs/b/a/z" } + +# if Array is one of the types, then it can take many +# values, and will always be an array. The other types provided +# specify what types are allowed in the list. + +$ node my-program.js --many 1 --many null --many foo +{ many: ["1", "null", "foo"] } + +$ node my-program.js --many foo +{ many: ["foo"] } +``` + +Read the tests at the bottom of `lib/nopt.js` for more examples of +what this puppy can do. + +## Types + +The following types are supported, and defined on `nopt.typeDefs` + +* String: A normal string. No parsing is done. +* path: A file system path. Gets resolved against cwd if not absolute. +* url: A url. If it doesn't parse, it isn't accepted. +* Number: Must be numeric. +* Date: Must parse as a date. If it does, and `Date` is one of the options, + then it will return a Date object, not a string. +* Boolean: Must be either `true` or `false`. If an option is a boolean, + then it does not need a value, and its presence will imply `true` as + the value. To negate boolean flags, do `--no-whatever` or `--whatever + false` +* NaN: Means that the option is strictly not allowed. Any value will + fail. +* Stream: An object matching the "Stream" class in node. Valuable + for use when validating programmatically. (npm uses this to let you + supply any WriteStream on the `outfd` and `logfd` config options.) +* Array: If `Array` is specified as one of the types, then the value + will be parsed as a list of options. This means that multiple values + can be specified, and that the value will always be an array. + +If a type is an array of values not on this list, then those are +considered valid values. For instance, in the example above, the +`--bloo` option can only be one of `"big"`, `"medium"`, or `"small"`, +and any other value will be rejected. + +When parsing unknown fields, `"true"`, `"false"`, and `"null"` will be +interpreted as their JavaScript equivalents, and numeric values will be +interpreted as a number. + +You can also mix types and values, or multiple types, in a list. For +instance `{ blah: [Number, null] }` would allow a value to be set to +either a Number or null. When types are ordered, this implies a +preference, and the first type that can be used to properly interpret +the value will be used. + +To define a new type, add it to `nopt.typeDefs`. Each item in that +hash is an object with a `type` member and a `validate` method. The +`type` member is an object that matches what goes in the type list. The +`validate` method is a function that gets called with `validate(data, +key, val)`. Validate methods should assign `data[key]` to the valid +value of `val` if it can be handled properly, or return boolean +`false` if it cannot. + +You can also call `nopt.clean(data, types, typeDefs)` to clean up a +config object and remove its invalid properties. + +## Error Handling + +By default, nopt outputs a warning to standard error when invalid +options are found. You can change this behavior by assigning a method +to `nopt.invalidHandler`. This method will be called with +the offending `nopt.invalidHandler(key, val, types)`. + +If no `nopt.invalidHandler` is assigned, then it will console.error +its whining. If it is assigned to boolean `false` then the warning is +suppressed. + +## Abbreviations + +Yes, they are supported. If you define options like this: + +```javascript +{ "foolhardyelephants" : Boolean +, "pileofmonkeys" : Boolean } +``` + +Then this will work: + +```bash +node program.js --foolhar --pil +node program.js --no-f --pileofmon +# etc. +``` + +## Shorthands + +Shorthands are a hash of shorter option names to a snippet of args that +they expand to. + +If multiple one-character shorthands are all combined, and the +combination does not unambiguously match any other option or shorthand, +then they will be broken up into their constituent parts. For example: + +```json +{ "s" : ["--loglevel", "silent"] +, "g" : "--global" +, "f" : "--force" +, "p" : "--parseable" +, "l" : "--long" +} +``` + +```bash +npm ls -sgflp +# just like doing this: +npm ls --loglevel silent --global --force --long --parseable +``` + +## The Rest of the args + +The config object returned by nopt is given a special member called +`argv`, which is an object with the following fields: + +* `remain`: The remaining args after all the parsing has occurred. +* `original`: The args as they originally appeared. +* `cooked`: The args after flags and shorthands are expanded. + +## Slicing + +Node programs are called with more or less the exact argv as it appears +in C land, after the v8 and node-specific options have been plucked off. +As such, `argv[0]` is always `node` and `argv[1]` is always the +JavaScript program being run. + +That's usually not very useful to you. So they're sliced off by +default. If you want them, then you can pass in `0` as the last +argument, or any other number that you'd like to slice off the start of +the list. diff --git a/node_modules/nopt/bin/nopt.js b/node_modules/nopt/bin/nopt.js new file mode 100755 index 0000000..30e9fdb --- /dev/null +++ b/node_modules/nopt/bin/nopt.js @@ -0,0 +1,51 @@ +#!/usr/bin/env node +var nopt = require("../lib/nopt") + , types = { num: Number + , bool: Boolean + , help: Boolean + , list: Array + , "num-list": [Number, Array] + , "str-list": [String, Array] + , "bool-list": [Boolean, Array] + , str: String + , clear: Boolean + , config: Boolean + , length: Number + } + , shorthands = { s: [ "--str", "astring" ] + , b: [ "--bool" ] + , nb: [ "--no-bool" ] + , tft: [ "--bool-list", "--no-bool-list", "--bool-list", "true" ] + , "?": ["--help"] + , h: ["--help"] + , H: ["--help"] + , n: [ "--num", "125" ] + , c: ["--config"] + , l: ["--length"] + } + , parsed = nopt( types + , shorthands + , process.argv + , 2 ) + +console.log("parsed", parsed) + +if (parsed.help) { + console.log("") + console.log("nopt cli tester") + console.log("") + console.log("types") + console.log(Object.keys(types).map(function M (t) { + var type = types[t] + if (Array.isArray(type)) { + return [t, type.map(function (type) { return type.name })] + } + return [t, type && type.name] + }).reduce(function (s, i) { + s[i[0]] = i[1] + return s + }, {})) + console.log("") + console.log("shorthands") + console.log(shorthands) +} diff --git a/node_modules/nopt/examples/my-program.js b/node_modules/nopt/examples/my-program.js new file mode 100755 index 0000000..142447e --- /dev/null +++ b/node_modules/nopt/examples/my-program.js @@ -0,0 +1,30 @@ +#!/usr/bin/env node + +//process.env.DEBUG_NOPT = 1 + +// my-program.js +var nopt = require("../lib/nopt") + , Stream = require("stream").Stream + , path = require("path") + , knownOpts = { "foo" : [String, null] + , "bar" : [Stream, Number] + , "baz" : path + , "bloo" : [ "big", "medium", "small" ] + , "flag" : Boolean + , "pick" : Boolean + } + , shortHands = { "foofoo" : ["--foo", "Mr. Foo"] + , "b7" : ["--bar", "7"] + , "m" : ["--bloo", "medium"] + , "p" : ["--pick"] + , "f" : ["--flag", "true"] + , "g" : ["--flag"] + , "s" : "--flag" + } + // everything is optional. + // knownOpts and shorthands default to {} + // arg list defaults to process.argv + // slice defaults to 2 + , parsed = nopt(knownOpts, shortHands, process.argv, 2) + +console.log("parsed =\n"+ require("util").inspect(parsed)) diff --git a/node_modules/nopt/lib/nopt.js b/node_modules/nopt/lib/nopt.js new file mode 100644 index 0000000..9efab7a --- /dev/null +++ b/node_modules/nopt/lib/nopt.js @@ -0,0 +1,412 @@ +// info about each config option. + +var debug = process.env.DEBUG_NOPT || process.env.NOPT_DEBUG + ? function () { console.error.apply(console, arguments) } + : function () {} + +var url = require("url") + , path = require("path") + , Stream = require("stream").Stream + , abbrev = require("abbrev") + +module.exports = exports = nopt +exports.clean = clean + +exports.typeDefs = + { String : { type: String, validate: validateString } + , Boolean : { type: Boolean, validate: validateBoolean } + , url : { type: url, validate: validateUrl } + , Number : { type: Number, validate: validateNumber } + , path : { type: path, validate: validatePath } + , Stream : { type: Stream, validate: validateStream } + , Date : { type: Date, validate: validateDate } + } + +function nopt (types, shorthands, args, slice) { + args = args || process.argv + types = types || {} + shorthands = shorthands || {} + if (typeof slice !== "number") slice = 2 + + debug(types, shorthands, args, slice) + + args = args.slice(slice) + var data = {} + , key + , remain = [] + , cooked = args + , original = args.slice(0) + + parse(args, data, remain, types, shorthands) + // now data is full + clean(data, types, exports.typeDefs) + data.argv = {remain:remain,cooked:cooked,original:original} + Object.defineProperty(data.argv, 'toString', { value: function () { + return this.original.map(JSON.stringify).join(" ") + }, enumerable: false }) + return data +} + +function clean (data, types, typeDefs) { + typeDefs = typeDefs || exports.typeDefs + var remove = {} + , typeDefault = [false, true, null, String, Number, Array] + + Object.keys(data).forEach(function (k) { + if (k === "argv") return + var val = data[k] + , isArray = Array.isArray(val) + , type = types[k] + if (!isArray) val = [val] + if (!type) type = typeDefault + if (type === Array) type = typeDefault.concat(Array) + if (!Array.isArray(type)) type = [type] + + debug("val=%j", val) + debug("types=", type) + val = val.map(function (val) { + // if it's an unknown value, then parse false/true/null/numbers/dates + if (typeof val === "string") { + debug("string %j", val) + val = val.trim() + if ((val === "null" && ~type.indexOf(null)) + || (val === "true" && + (~type.indexOf(true) || ~type.indexOf(Boolean))) + || (val === "false" && + (~type.indexOf(false) || ~type.indexOf(Boolean)))) { + val = JSON.parse(val) + debug("jsonable %j", val) + } else if (~type.indexOf(Number) && !isNaN(val)) { + debug("convert to number", val) + val = +val + } else if (~type.indexOf(Date) && !isNaN(Date.parse(val))) { + debug("convert to date", val) + val = new Date(val) + } + } + + if (!types.hasOwnProperty(k)) { + return val + } + + // allow `--no-blah` to set 'blah' to null if null is allowed + if (val === false && ~type.indexOf(null) && + !(~type.indexOf(false) || ~type.indexOf(Boolean))) { + val = null + } + + var d = {} + d[k] = val + debug("prevalidated val", d, val, types[k]) + if (!validate(d, k, val, types[k], typeDefs)) { + if (exports.invalidHandler) { + exports.invalidHandler(k, val, types[k], data) + } else if (exports.invalidHandler !== false) { + debug("invalid: "+k+"="+val, types[k]) + } + return remove + } + debug("validated val", d, val, types[k]) + return d[k] + }).filter(function (val) { return val !== remove }) + + if (!val.length) delete data[k] + else if (isArray) { + debug(isArray, data[k], val) + data[k] = val + } else data[k] = val[0] + + debug("k=%s val=%j", k, val, data[k]) + }) +} + +function validateString (data, k, val) { + data[k] = String(val) +} + +function validatePath (data, k, val) { + if (val === true) return false + val = String(val) + var homePattern = process.platform === 'win32' ? /^~(\/|\\)/ : /^~\// + if (val.match(homePattern) && process.env.HOME) { + val = path.resolve(process.env.HOME, val.substr(2)) + } + data[k] = path.resolve(String(val)) + return true +} + +function validateNumber (data, k, val) { + debug("validate Number %j %j %j", k, val, isNaN(val)) + if (isNaN(val)) return false + data[k] = +val +} + +function validateDate (data, k, val) { + debug("validate Date %j %j %j", k, val, Date.parse(val)) + var s = Date.parse(val) + if (isNaN(s)) return false + data[k] = new Date(val) +} + +function validateBoolean (data, k, val) { + if (val instanceof Boolean) val = val.valueOf() + else if (typeof val === "string") { + if (!isNaN(val)) val = !!(+val) + else if (val === "null" || val === "false") val = false + else val = true + } else val = !!val + data[k] = val +} + +function validateUrl (data, k, val) { + val = url.parse(String(val)) + if (!val.host) return false + data[k] = val.href +} + +function validateStream (data, k, val) { + if (!(val instanceof Stream)) return false + data[k] = val +} + +function validate (data, k, val, type, typeDefs) { + // arrays are lists of types. + if (Array.isArray(type)) { + for (var i = 0, l = type.length; i < l; i ++) { + if (type[i] === Array) continue + if (validate(data, k, val, type[i], typeDefs)) return true + } + delete data[k] + return false + } + + // an array of anything? + if (type === Array) return true + + // NaN is poisonous. Means that something is not allowed. + if (type !== type) { + debug("Poison NaN", k, val, type) + delete data[k] + return false + } + + // explicit list of values + if (val === type) { + debug("Explicitly allowed %j", val) + // if (isArray) (data[k] = data[k] || []).push(val) + // else data[k] = val + data[k] = val + return true + } + + // now go through the list of typeDefs, validate against each one. + var ok = false + , types = Object.keys(typeDefs) + for (var i = 0, l = types.length; i < l; i ++) { + debug("test type %j %j %j", k, val, types[i]) + var t = typeDefs[types[i]] + if (t && type === t.type) { + var d = {} + ok = false !== t.validate(d, k, val) + val = d[k] + if (ok) { + // if (isArray) (data[k] = data[k] || []).push(val) + // else data[k] = val + data[k] = val + break + } + } + } + debug("OK? %j (%j %j %j)", ok, k, val, types[i]) + + if (!ok) delete data[k] + return ok +} + +function parse (args, data, remain, types, shorthands) { + debug("parse", args, data, remain) + + var key = null + , abbrevs = abbrev(Object.keys(types)) + , shortAbbr = abbrev(Object.keys(shorthands)) + + for (var i = 0; i < args.length; i ++) { + var arg = args[i] + debug("arg", arg) + + if (arg.match(/^-{2,}$/)) { + // done with keys. + // the rest are args. + remain.push.apply(remain, args.slice(i + 1)) + args[i] = "--" + break + } + var hadEq = false + if (arg.charAt(0) === "-" && arg.length > 1) { + if (arg.indexOf("=") !== -1) { + hadEq = true + var v = arg.split("=") + arg = v.shift() + v = v.join("=") + args.splice.apply(args, [i, 1].concat([arg, v])) + } + + // see if it's a shorthand + // if so, splice and back up to re-parse it. + var shRes = resolveShort(arg, shorthands, shortAbbr, abbrevs) + debug("arg=%j shRes=%j", arg, shRes) + if (shRes) { + debug(arg, shRes) + args.splice.apply(args, [i, 1].concat(shRes)) + if (arg !== shRes[0]) { + i -- + continue + } + } + arg = arg.replace(/^-+/, "") + var no = null + while (arg.toLowerCase().indexOf("no-") === 0) { + no = !no + arg = arg.substr(3) + } + + if (abbrevs[arg]) arg = abbrevs[arg] + + var isArray = types[arg] === Array || + Array.isArray(types[arg]) && types[arg].indexOf(Array) !== -1 + + // allow unknown things to be arrays if specified multiple times. + if (!types.hasOwnProperty(arg) && data.hasOwnProperty(arg)) { + if (!Array.isArray(data[arg])) + data[arg] = [data[arg]] + isArray = true + } + + var val + , la = args[i + 1] + + var isBool = typeof no === 'boolean' || + types[arg] === Boolean || + Array.isArray(types[arg]) && types[arg].indexOf(Boolean) !== -1 || + (typeof types[arg] === 'undefined' && !hadEq) || + (la === "false" && + (types[arg] === null || + Array.isArray(types[arg]) && ~types[arg].indexOf(null))) + + if (isBool) { + // just set and move along + val = !no + // however, also support --bool true or --bool false + if (la === "true" || la === "false") { + val = JSON.parse(la) + la = null + if (no) val = !val + i ++ + } + + // also support "foo":[Boolean, "bar"] and "--foo bar" + if (Array.isArray(types[arg]) && la) { + if (~types[arg].indexOf(la)) { + // an explicit type + val = la + i ++ + } else if ( la === "null" && ~types[arg].indexOf(null) ) { + // null allowed + val = null + i ++ + } else if ( !la.match(/^-{2,}[^-]/) && + !isNaN(la) && + ~types[arg].indexOf(Number) ) { + // number + val = +la + i ++ + } else if ( !la.match(/^-[^-]/) && ~types[arg].indexOf(String) ) { + // string + val = la + i ++ + } + } + + if (isArray) (data[arg] = data[arg] || []).push(val) + else data[arg] = val + + continue + } + + if (types[arg] === String && la === undefined) + la = "" + + if (la && la.match(/^-{2,}$/)) { + la = undefined + i -- + } + + val = la === undefined ? true : la + if (isArray) (data[arg] = data[arg] || []).push(val) + else data[arg] = val + + i ++ + continue + } + remain.push(arg) + } +} + +function resolveShort (arg, shorthands, shortAbbr, abbrevs) { + // handle single-char shorthands glommed together, like + // npm ls -glp, but only if there is one dash, and only if + // all of the chars are single-char shorthands, and it's + // not a match to some other abbrev. + arg = arg.replace(/^-+/, '') + + // if it's an exact known option, then don't go any further + if (abbrevs[arg] === arg) + return null + + // if it's an exact known shortopt, same deal + if (shorthands[arg]) { + // make it an array, if it's a list of words + if (shorthands[arg] && !Array.isArray(shorthands[arg])) + shorthands[arg] = shorthands[arg].split(/\s+/) + + return shorthands[arg] + } + + // first check to see if this arg is a set of single-char shorthands + var singles = shorthands.___singles + if (!singles) { + singles = Object.keys(shorthands).filter(function (s) { + return s.length === 1 + }).reduce(function (l,r) { + l[r] = true + return l + }, {}) + shorthands.___singles = singles + debug('shorthand singles', singles) + } + + var chrs = arg.split("").filter(function (c) { + return singles[c] + }) + + if (chrs.join("") === arg) return chrs.map(function (c) { + return shorthands[c] + }).reduce(function (l, r) { + return l.concat(r) + }, []) + + + // if it's an arg abbrev, and not a literal shorthand, then prefer the arg + if (abbrevs[arg] && !shorthands[arg]) + return null + + // if it's an abbr for a shorthand, then use that + if (shortAbbr[arg]) + arg = shortAbbr[arg] + + // make it an array, if it's a list of words + if (shorthands[arg] && !Array.isArray(shorthands[arg])) + shorthands[arg] = shorthands[arg].split(/\s+/) + + return shorthands[arg] +} diff --git a/node_modules/nopt/package.json b/node_modules/nopt/package.json new file mode 100644 index 0000000..80a05bd --- /dev/null +++ b/node_modules/nopt/package.json @@ -0,0 +1,22 @@ +{ + "name": "nopt", + "version": "2.2.1", + "description": "Option parsing for Node, supporting types, shorthands, etc. Used by npm.", + "author": "Isaac Z. Schlueter (http://blog.izs.me/)", + "main": "lib/nopt.js", + "scripts": { + "test": "tap test/*.js" + }, + "repository": "http://github.com/isaacs/nopt", + "bin": "./bin/nopt.js", + "license": { + "type": "MIT", + "url": "https://github.com/isaacs/nopt/raw/master/LICENSE" + }, + "dependencies": { + "abbrev": "1" + }, + "devDependencies": { + "tap": "~0.4.8" + } +} diff --git a/node_modules/nopt/test/basic.js b/node_modules/nopt/test/basic.js new file mode 100644 index 0000000..b31dccf --- /dev/null +++ b/node_modules/nopt/test/basic.js @@ -0,0 +1,243 @@ +var nopt = require("../") + , test = require('tap').test + + +test("passing a string results in a string", function (t) { + var parsed = nopt({ key: String }, {}, ["--key", "myvalue"], 0) + t.same(parsed.key, "myvalue") + t.end() +}) + +// https://github.com/npm/nopt/issues/31 +test("Empty String results in empty string, not true", function (t) { + var parsed = nopt({ empty: String }, {}, ["--empty"], 0) + t.same(parsed.empty, "") + t.end() +}) + +test("~ path is resolved to $HOME", function (t) { + var path = require("path") + if (!process.env.HOME) process.env.HOME = "/tmp" + var parsed = nopt({key: path}, {}, ["--key=~/val"], 0) + t.same(parsed.key, path.resolve(process.env.HOME, "val")) + t.end() +}) + +test("other tests", function (t) { + + var util = require("util") + , Stream = require("stream") + , path = require("path") + , url = require("url") + + , shorthands = + { s : ["--loglevel", "silent"] + , d : ["--loglevel", "info"] + , dd : ["--loglevel", "verbose"] + , ddd : ["--loglevel", "silly"] + , noreg : ["--no-registry"] + , reg : ["--registry"] + , "no-reg" : ["--no-registry"] + , silent : ["--loglevel", "silent"] + , verbose : ["--loglevel", "verbose"] + , h : ["--usage"] + , H : ["--usage"] + , "?" : ["--usage"] + , help : ["--usage"] + , v : ["--version"] + , f : ["--force"] + , desc : ["--description"] + , "no-desc" : ["--no-description"] + , "local" : ["--no-global"] + , l : ["--long"] + , p : ["--parseable"] + , porcelain : ["--parseable"] + , g : ["--global"] + } + + , types = + { aoa: Array + , nullstream: [null, Stream] + , date: Date + , str: String + , browser : String + , cache : path + , color : ["always", Boolean] + , depth : Number + , description : Boolean + , dev : Boolean + , editor : path + , force : Boolean + , global : Boolean + , globalconfig : path + , group : [String, Number] + , gzipbin : String + , logfd : [Number, Stream] + , loglevel : ["silent","win","error","warn","info","verbose","silly"] + , long : Boolean + , "node-version" : [false, String] + , npaturl : url + , npat : Boolean + , "onload-script" : [false, String] + , outfd : [Number, Stream] + , parseable : Boolean + , pre: Boolean + , prefix: path + , proxy : url + , "rebuild-bundle" : Boolean + , registry : url + , searchopts : String + , searchexclude: [null, String] + , shell : path + , t: [Array, String] + , tag : String + , tar : String + , tmp : path + , "unsafe-perm" : Boolean + , usage : Boolean + , user : String + , username : String + , userconfig : path + , version : Boolean + , viewer: path + , _exit : Boolean + , path: path + } + + ; [["-v", {version:true}, []] + ,["---v", {version:true}, []] + ,["ls -s --no-reg connect -d", + {loglevel:"info",registry:null},["ls","connect"]] + ,["ls ---s foo",{loglevel:"silent"},["ls","foo"]] + ,["ls --registry blargle", {}, ["ls"]] + ,["--no-registry", {registry:null}, []] + ,["--no-color true", {color:false}, []] + ,["--no-color false", {color:true}, []] + ,["--no-color", {color:false}, []] + ,["--color false", {color:false}, []] + ,["--color --logfd 7", {logfd:7,color:true}, []] + ,["--color=true", {color:true}, []] + ,["--logfd=10", {logfd:10}, []] + ,["--tmp=/tmp -tar=gtar",{tmp:"/tmp",tar:"gtar"},[]] + ,["--tmp=tmp -tar=gtar", + {tmp:path.resolve(process.cwd(), "tmp"),tar:"gtar"},[]] + ,["--logfd x", {}, []] + ,["a -true -- -no-false", {true:true},["a","-no-false"]] + ,["a -no-false", {false:false},["a"]] + ,["a -no-no-true", {true:true}, ["a"]] + ,["a -no-no-no-false", {false:false}, ["a"]] + ,["---NO-no-No-no-no-no-nO-no-no"+ + "-No-no-no-no-no-no-no-no-no"+ + "-no-no-no-no-NO-NO-no-no-no-no-no-no"+ + "-no-body-can-do-the-boogaloo-like-I-do" + ,{"body-can-do-the-boogaloo-like-I-do":false}, []] + ,["we are -no-strangers-to-love "+ + "--you-know=the-rules --and=so-do-i "+ + "---im-thinking-of=a-full-commitment "+ + "--no-you-would-get-this-from-any-other-guy "+ + "--no-gonna-give-you-up "+ + "-no-gonna-let-you-down=true "+ + "--no-no-gonna-run-around false "+ + "--desert-you=false "+ + "--make-you-cry false "+ + "--no-tell-a-lie "+ + "--no-no-and-hurt-you false" + ,{"strangers-to-love":false + ,"you-know":"the-rules" + ,"and":"so-do-i" + ,"you-would-get-this-from-any-other-guy":false + ,"gonna-give-you-up":false + ,"gonna-let-you-down":false + ,"gonna-run-around":false + ,"desert-you":false + ,"make-you-cry":false + ,"tell-a-lie":false + ,"and-hurt-you":false + },["we", "are"]] + ,["-t one -t two -t three" + ,{t: ["one", "two", "three"]} + ,[]] + ,["-t one -t null -t three four five null" + ,{t: ["one", "null", "three"]} + ,["four", "five", "null"]] + ,["-t foo" + ,{t:["foo"]} + ,[]] + ,["--no-t" + ,{t:["false"]} + ,[]] + ,["-no-no-t" + ,{t:["true"]} + ,[]] + ,["-aoa one -aoa null -aoa 100" + ,{aoa:["one", null, 100]} + ,[]] + ,["-str 100" + ,{str:"100"} + ,[]] + ,["--color always" + ,{color:"always"} + ,[]] + ,["--no-nullstream" + ,{nullstream:null} + ,[]] + ,["--nullstream false" + ,{nullstream:null} + ,[]] + ,["--notadate=2011-01-25" + ,{notadate: "2011-01-25"} + ,[]] + ,["--date 2011-01-25" + ,{date: new Date("2011-01-25")} + ,[]] + ,["-cl 1" + ,{config: true, length: 1} + ,[] + ,{config: Boolean, length: Number, clear: Boolean} + ,{c: "--config", l: "--length"}] + ,["--acount bla" + ,{"acount":true} + ,["bla"] + ,{account: Boolean, credentials: Boolean, options: String} + ,{a:"--account", c:"--credentials",o:"--options"}] + ,["--clear" + ,{clear:true} + ,[] + ,{clear:Boolean,con:Boolean,len:Boolean,exp:Boolean,add:Boolean,rep:Boolean} + ,{c:"--con",l:"--len",e:"--exp",a:"--add",r:"--rep"}] + ,["--file -" + ,{"file":"-"} + ,[] + ,{file:String} + ,{}] + ,["--file -" + ,{"file":true} + ,["-"] + ,{file:Boolean} + ,{}] + ,["--path" + ,{"path":null} + ,[]] + ,["--path ." + ,{"path":process.cwd()} + ,[]] + ].forEach(function (test) { + var argv = test[0].split(/\s+/) + , opts = test[1] + , rem = test[2] + , actual = nopt(test[3] || types, test[4] || shorthands, argv, 0) + , parsed = actual.argv + delete actual.argv + for (var i in opts) { + var e = JSON.stringify(opts[i]) + , a = JSON.stringify(actual[i] === undefined ? null : actual[i]) + if (e && typeof e === "object") { + t.deepEqual(e, a) + } else { + t.equal(e, a) + } + } + t.deepEqual(rem, parsed.remain) + }) + t.end() +}) diff --git a/node_modules/runforcover/README.markdown b/node_modules/runforcover/README.markdown new file mode 100644 index 0000000..1e56ebd --- /dev/null +++ b/node_modules/runforcover/README.markdown @@ -0,0 +1,56 @@ +runforcover +====== + +Runforcover is a require-hook library that uses node-bunker to provide code coverage data +for your unit test library, whatever it might be. + +methods +======= +var runforcover = require('runforcover'); + +var coverage = runforcover.cover([RegExp | path]); +------- + +Attach runforcover to the global `require` object and patch `require.extensions['.js']` to +provide coverage metadata for all files required after this point. Returns a function +object that can be called to obtain a object keying files to `CoverageData` objects, with +a method for releasing control back to vanilla `require`. Usage: + +````javascript + +var coverage = runforcover.cover(/.*/g); + +require('some/library'); + +coverage(function(coverageData) { + // coverageData is an object keyed by filename. + var stats = coverageData['/full/path/to/file.js'].stats() + + // the percentage of lines run versus total lines in file + console.log(stats.percentage); + + // the number of missing lines + console.log(stats.missing); + + // the number of lines run (seen) + console.log(stats.seen); + + // an array of line objects representing 'missed' lines + stats.lines; + + stats.lines.forEach(function(line) { + // the line number of the line: + console.log(line.number); + + // returns a string containing the source data for the line: + console.log(line.source()); + }); + + // return control back to the original require function + coverage.release(); +}); +```` + +license +======= +new BSD. diff --git a/node_modules/runforcover/index.js b/node_modules/runforcover/index.js new file mode 100644 index 0000000..b5318ac --- /dev/null +++ b/node_modules/runforcover/index.js @@ -0,0 +1,127 @@ +var bunker = require('bunker'), + Module = require('module').Module, + path = require('path'), + fs = require('fs'), + vm = require('vm'); + +function CoverageData (filename, bunker) { + this.bunker = bunker; + this.filename = filename; + this.nodes = {}; +}; + +CoverageData.prototype.visit = function(node) { + ++(this.nodes[node.id] = this.nodes[node.id] || {node:node, count:0}).count; +}; + +CoverageData.prototype.missing = function() { + var nodes = this.nodes, + missing = this.bunker.nodes.filter(function(node) { + return !nodes[node.id]; + }); + + return missing; +}; + +CoverageData.prototype.stats = function() { + var missing = this.missing(), + filedata = fs.readFileSync(this.filename, 'utf8').split('\n'); + + var seenLines = [], + lines = + missing.sort(function(lhs, rhs) { + return lhs.node[0].start.line < rhs.node[0].start.line ? -1 : + lhs.node[0].start.line > rhs.node[0].start.line ? 1 : + 0; + }).filter(function(node) { + + var okay = (seenLines.indexOf(node.node[0].start.line) < 0); + if(okay) + seenLines.push(node.node[0].start.line); + return okay; + + }).map(function(node, idx, all) { + return { + lineno:node.node[0].start.line + 1, + source:function() { return filedata[node.node[0].start.line]; } + }; + }); + + return { + percentage:(filedata.length-seenLines.length)/filedata.length, + lines:lines, + missing:seenLines.length, + seen:(filedata.length-seenLines.length) + }; +}; + +module.exports.createEnvironment = function(module, filename) { + var req = function(path) { + return Module._load(path, module); + }; + req.resolve = function(request) { + return Module._resolveFilename(request, module)[1]; + } + req.paths = Module._paths; + req.main = process.mainModule; + req.extensions = Module._extensions; + req.registerExtension = function() { + throw new Error('require.registerExtension() removed. Use ' + + 'require.extensions instead.'); + } + require.cache = Module._cache; + + var ctxt = {}; + for(var k in global) + ctxt[k] = global[k]; + + ctxt.require = req; + ctxt.exports = module.exports; + ctxt.__filename = filename; + ctxt.__dirname = path.dirname(filename); + ctxt.process = process; + ctxt.console = console; + ctxt.module = module; + ctxt.global = ctxt; + + return ctxt; +}; + +module.exports.cover = function(fileRegex) { + var originalRequire = require.extensions['.js'], + coverageData = {}, + match = fileRegex instanceof RegExp ? + fileRegex : new RegExp( + fileRegex ? fileRegex.replace(/\//g, '\\/').replace(/\./g, '\\.') : '.*' + , 'g'), + target = this; + + require.extensions['.js'] = function(module, filename) { + if(!match.test(filename)) return originalRequire(module, filename); + + var context = target.createEnvironment(module, filename), + data = fs.readFileSync(filename, 'utf8'), + bunkerized = bunker(data), + coverage = coverageData[filename] = new CoverageData(filename, bunkerized); + + bunkerized.on('node', coverage.visit.bind(coverage)); + bunkerized.assign(context); + + var wrapper = '(function(ctxt) { with(ctxt) { return '+Module.wrap(bunkerized.compile())+'; } })', + compiledWrapper = vm.runInThisContext(wrapper, filename, true)(context); + + var args = [context.exports, context.require, module, filename, context.__dirname]; + return compiledWrapper.apply(module.exports, args); + }; + + var retval = function(ready) { + ready(coverageData); + }; + + retval.release = function() { + require.extensions['.js'] = originalRequire; + }; + + return retval; +}; + diff --git a/node_modules/runforcover/package.json b/node_modules/runforcover/package.json new file mode 100644 index 0000000..f2a2ac6 --- /dev/null +++ b/node_modules/runforcover/package.json @@ -0,0 +1,32 @@ +{ + "name" : "runforcover", + "version" : "0.0.2", + "description" : "require plugin for js code coverage using bunker", + "main" : "index.js", + "directories" : { + "lib" : ".", + "test" : "test" + }, + "dependencies" : { + "bunker" : "0.1.X" + }, + "scripts" : { + "test" : "node test/index.js" + }, + "repository" : { + "type" : "git", + "url" : "http://github.com/chrisdickinson/node-runforcover.git" + }, + "keywords" : [ + "code", + "coverage", + "bunker" + ], + "author" : { + "name" : "Chris Dickinson", + "email" : "chris@neversaw.us", + "url" : "http://neversaw.us" + }, + "license" : "new BSD", + "engine" : { "node" : ">=0.4" } +} diff --git a/node_modules/runforcover/test/index.js b/node_modules/runforcover/test/index.js new file mode 100644 index 0000000..ea59662 --- /dev/null +++ b/node_modules/runforcover/test/index.js @@ -0,0 +1 @@ +require('./interface').coverageInterface() diff --git a/node_modules/runforcover/test/interface.js b/node_modules/runforcover/test/interface.js new file mode 100644 index 0000000..a6455ed --- /dev/null +++ b/node_modules/runforcover/test/interface.js @@ -0,0 +1,50 @@ +var assert = require('assert'); +var runforcover = require('../'); + +exports.coverageInterface = function() { + assert.ok(runforcover.cover); + + var originalRequire = require.extensions['.js']; + + var coverage = runforcover.cover(); + + assert.notEqual(originalRequire, require.extensions['.js']); + + var file = require('./src/coverage'); + + coverage(function(coverageData) { + assert.equal(Object.keys(coverageData).length, 1); + assert.equal(Object.keys(coverageData)[0], __dirname + '/src/coverage.js'); + + var fileCoverageData = coverageData[Object.keys(coverageData)[0]]; + + assert.ok(fileCoverageData.stats); + assert.ok(fileCoverageData.missing); + + var stats = fileCoverageData.stats(); + + assert.ok(stats.percentage !== undefined); + assert.ok(stats.lines !== undefined); + assert.ok(stats.missing !== undefined); + assert.ok(stats.seen !== undefined); + + assert.equal(stats.lines.length, 3); + assert.equal(stats.lines[0].source(), ' if(a > 0) {'); + assert.equal(stats.lines[1].source(), ' return a + 1;'); + assert.equal(stats.lines[2].source(), ' return a - 1;'); + + file.something(1); + stats = fileCoverageData.stats(); + + assert.equal(stats.lines.length, 1); + assert.equal(stats.lines[0].source(), ' return a - 1;'); + + file.something(-1); + stats = fileCoverageData.stats(); + + assert.equal(stats.lines.length, 0); + + coverage.release(); + assert.equal(require.extensions['.js'], originalRequire); + }); +}; diff --git a/node_modules/runforcover/test/src/coverage.js b/node_modules/runforcover/test/src/coverage.js new file mode 100644 index 0000000..5b88dfe --- /dev/null +++ b/node_modules/runforcover/test/src/coverage.js @@ -0,0 +1,7 @@ +exports.something = function(a) { + if(a > 0) { + return a + 1; + } else { + return a - 1; + } +}; diff --git a/node_modules/slide/LICENSE b/node_modules/slide/LICENSE new file mode 100644 index 0000000..05eeeb8 --- /dev/null +++ b/node_modules/slide/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/node_modules/slide/README.md b/node_modules/slide/README.md new file mode 100644 index 0000000..59ad738 --- /dev/null +++ b/node_modules/slide/README.md @@ -0,0 +1,143 @@ +# Controlling Flow: callbacks are easy + +## What's actually hard? + +- Doing a bunch of things in a specific order. +- Knowing when stuff is done. +- Handling failures. +- Breaking up functionality into parts (avoid nested inline callbacks) + + +## Common Mistakes + +- Abandoning convention and consistency. +- Putting all callbacks inline. +- Using libraries without grokking them. +- Trying to make async code look sync. + +## Define Conventions + +- Two kinds of functions: *actors* take action, *callbacks* get results. +- Essentially the continuation pattern. Resulting code *looks* similar + to fibers, but is *much* simpler to implement. +- Node works this way in the lowlevel APIs already, and it's very flexible. + +## Callbacks + +- Simple responders +- Must always be prepared to handle errors, that's why it's the first argument. +- Often inline anonymous, but not always. +- Can trap and call other callbacks with modified data, or pass errors upwards. + +## Actors + +- Last argument is a callback. +- If any error occurs, and can't be handled, pass it to the callback and return. +- Must not throw. Return value ignored. +- return x ==> return cb(null, x) +- throw er ==> return cb(er) + +```javascript +// return true if a path is either +// a symlink or a directory. +function isLinkOrDir (path, cb) { + fs.lstat(path, function (er, s) { + if (er) return cb(er) + return cb(null, s.isDirectory() || s.isSymbolicLink()) + }) +} +``` + +# asyncMap + +## Usecases + +- I have a list of 10 files, and need to read all of them, and then continue when they're all done. +- I have a dozen URLs, and need to fetch them all, and then continue when they're all done. +- I have 4 connected users, and need to send a message to all of them, and then continue when that's done. +- I have a list of n things, and I need to dosomething with all of them, in parallel, and get the results once they're all complete. + + +## Solution + +```javascript +var asyncMap = require("slide").asyncMap +function writeFiles (files, what, cb) { + asyncMap(files, function (f, cb) { + fs.writeFile(f, what, cb) + }, cb) +} +writeFiles([my, file, list], "foo", cb) +``` + +# chain + +## Usecases + +- I have to do a bunch of things, in order. Get db credentials out of a file, + read the data from the db, write that data to another file. +- If anything fails, do not continue. +- I still have to provide an array of functions, which is a lot of boilerplate, + and a pita if your functions take args like + +```javascript +function (cb) { + blah(a, b, c, cb) +} +``` + +- Results are discarded, which is a bit lame. +- No way to branch. + +## Solution + +- reduces boilerplate by converting an array of [fn, args] to an actor + that takes no arguments (except cb) +- A bit like Function#bind, but tailored for our use-case. +- bindActor(obj, "method", a, b, c) +- bindActor(fn, a, b, c) +- bindActor(obj, fn, a, b, c) +- branching, skipping over falsey arguments + +```javascript +chain([ + doThing && [thing, a, b, c] +, isFoo && [doFoo, "foo"] +, subChain && [chain, [one, two]] +], cb) +``` + +- tracking results: results are stored in an optional array passed as argument, + last result is always in results[results.length - 1]. +- treat chain.first and chain.last as placeholders for the first/last + result up until that point. + + +## Non-trivial example + +- Read number files in a directory +- Add the results together +- Ping a web service with the result +- Write the response to a file +- Delete the number files + +```javascript +var chain = require("slide").chain +function myProgram (cb) { + var res = [], last = chain.last, first = chain.first + chain([ + [fs, "readdir", "the-directory"] + , [readFiles, "the-directory", last] + , [sum, last] + , [ping, "POST", "example.com", 80, "/foo", last] + , [fs, "writeFile", "result.txt", last] + , [rmFiles, "./the-directory", first] + ], res, cb) +} +``` + +# Conclusion: Convention Profits + +- Consistent API from top to bottom. +- Sneak in at any point to inject functionality. Testable, reusable, ... +- When ruby and python users whine, you can smile condescendingly. diff --git a/node_modules/slide/index.js b/node_modules/slide/index.js new file mode 100644 index 0000000..0a9277f --- /dev/null +++ b/node_modules/slide/index.js @@ -0,0 +1 @@ +module.exports=require("./lib/slide") diff --git a/node_modules/slide/lib/async-map-ordered.js b/node_modules/slide/lib/async-map-ordered.js new file mode 100644 index 0000000..5cca79a --- /dev/null +++ b/node_modules/slide/lib/async-map-ordered.js @@ -0,0 +1,65 @@ + +throw new Error("TODO: Not yet implemented.") + +/* +usage: + +Like asyncMap, but only can take a single cb, and guarantees +the order of the results. +*/ + +module.exports = asyncMapOrdered + +function asyncMapOrdered (list, fn, cb_) { + if (typeof cb_ !== "function") throw new Error( + "No callback provided to asyncMapOrdered") + + if (typeof fn !== "function") throw new Error( + "No map function provided to asyncMapOrdered") + + if (list === undefined || list === null) return cb_(null, []) + if (!Array.isArray(list)) list = [list] + if (!list.length) return cb_(null, []) + + var errState = null + , l = list.length + , a = l + , res = [] + , resCount = 0 + , maxArgLen = 0 + + function cb (index) { return function () { + if (errState) return + var er = arguments[0] + var argLen = arguments.length + maxArgLen = Math.max(maxArgLen, argLen) + res[index] = argLen === 1 ? [er] : Array.apply(null, arguments) + + // see if any new things have been added. + if (list.length > l) { + var newList = list.slice(l) + a += (list.length - l) + var oldLen = l + l = list.length + process.nextTick(function () { + newList.forEach(function (ar, i) { fn(ar, cb(i + oldLen)) }) + }) + } + + if (er || --a === 0) { + errState = er + cb_.apply(null, [errState].concat(flip(res, resCount, maxArgLen))) + } + }} + // expect the supplied cb function to be called + // "n" times for each thing in the array. + list.forEach(function (ar) { + steps.forEach(function (fn, i) { fn(ar, cb(i)) }) + }) +} + +function flip (res, resCount, argLen) { + var flat = [] + // res = [[er, x, y], [er, x1, y1], [er, x2, y2, z2]] + // return [[x, x1, x2], [y, y1, y2], [undefined, undefined, z2]] + diff --git a/node_modules/slide/lib/async-map.js b/node_modules/slide/lib/async-map.js new file mode 100644 index 0000000..ccf345f --- /dev/null +++ b/node_modules/slide/lib/async-map.js @@ -0,0 +1,54 @@ + +/* +usage: + +// do something to a list of things +asyncMap(myListOfStuff, function (thing, cb) { doSomething(thing.foo, cb) }, cb) +// do more than one thing to each item +asyncMap(list, fooFn, barFn, cb) + +*/ + +module.exports = asyncMap + +function asyncMap () { + var steps = Array.prototype.slice.call(arguments) + , list = steps.shift() || [] + , cb_ = steps.pop() + if (typeof cb_ !== "function") throw new Error( + "No callback provided to asyncMap") + if (!list) return cb_(null, []) + if (!Array.isArray(list)) list = [list] + var n = steps.length + , data = [] // 2d array + , errState = null + , l = list.length + , a = l * n + if (!a) return cb_(null, []) + function cb (er) { + if (er && !errState) errState = er + + var argLen = arguments.length + for (var i = 1; i < argLen; i ++) if (arguments[i] !== undefined) { + data[i - 1] = (data[i - 1] || []).concat(arguments[i]) + } + // see if any new things have been added. + if (list.length > l) { + var newList = list.slice(l) + a += (list.length - l) * n + l = list.length + process.nextTick(function () { + newList.forEach(function (ar) { + steps.forEach(function (fn) { fn(ar, cb) }) + }) + }) + } + + if (--a === 0) cb_.apply(null, [errState].concat(data)) + } + // expect the supplied cb function to be called + // "n" times for each thing in the array. + list.forEach(function (ar) { + steps.forEach(function (fn) { fn(ar, cb) }) + }) +} diff --git a/node_modules/slide/lib/bind-actor.js b/node_modules/slide/lib/bind-actor.js new file mode 100644 index 0000000..6a37072 --- /dev/null +++ b/node_modules/slide/lib/bind-actor.js @@ -0,0 +1,16 @@ +module.exports = bindActor +function bindActor () { + var args = + Array.prototype.slice.call + (arguments) // jswtf. + , obj = null + , fn + if (typeof args[0] === "object") { + obj = args.shift() + fn = args.shift() + if (typeof fn === "string") + fn = obj[ fn ] + } else fn = args.shift() + return function (cb) { + fn.apply(obj, args.concat(cb)) } +} diff --git a/node_modules/slide/lib/chain.js b/node_modules/slide/lib/chain.js new file mode 100644 index 0000000..17b3711 --- /dev/null +++ b/node_modules/slide/lib/chain.js @@ -0,0 +1,20 @@ +module.exports = chain +var bindActor = require("./bind-actor.js") +chain.first = {} ; chain.last = {} +function chain (things, cb) { + var res = [] + ;(function LOOP (i, len) { + if (i >= len) return cb(null,res) + if (Array.isArray(things[i])) + things[i] = bindActor.apply(null, + things[i].map(function(i){ + return (i===chain.first) ? res[0] + : (i===chain.last) + ? res[res.length - 1] : i })) + if (!things[i]) return LOOP(i + 1, len) + things[i](function (er, data) { + if (er) return cb(er, res) + if (data !== undefined) res = res.concat(data) + LOOP(i + 1, len) + }) + })(0, things.length) } diff --git a/node_modules/slide/lib/slide.js b/node_modules/slide/lib/slide.js new file mode 100644 index 0000000..6e9ec23 --- /dev/null +++ b/node_modules/slide/lib/slide.js @@ -0,0 +1,3 @@ +exports.asyncMap = require("./async-map") +exports.bindActor = require("./bind-actor") +exports.chain = require("./chain") diff --git a/node_modules/slide/package.json b/node_modules/slide/package.json new file mode 100644 index 0000000..7799184 --- /dev/null +++ b/node_modules/slide/package.json @@ -0,0 +1,20 @@ +{ + "name": "slide", + "version": "1.1.6", + "author": "Isaac Z. Schlueter (http://blog.izs.me/)", + "contributors": [ + "S. Sriram (http://www.565labs.com)" + ], + "description": "A flow control lib small enough to fit on in a slide presentation. Derived live at Oak.JS", + "main": "./lib/slide.js", + "dependencies": {}, + "devDependencies": {}, + "engines": { + "node": "*" + }, + "repository": { + "type": "git", + "url": "git://github.com/isaacs/slide-flow-control.git" + }, + "license": "ISC" +} diff --git a/node_modules/tap/.npmignore b/node_modules/tap/.npmignore new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/tap/AUTHORS b/node_modules/tap/AUTHORS new file mode 100644 index 0000000..898b613 --- /dev/null +++ b/node_modules/tap/AUTHORS @@ -0,0 +1,8 @@ +# contributors sorted by whether or not they're me +Isaac Z. Schlueter +baudehlo +James Halliday +Jason Smith (air) +Pedro P. Candel +Stein Martin Hustad +Trent Mick diff --git a/node_modules/tap/LICENSE b/node_modules/tap/LICENSE new file mode 100644 index 0000000..05a4010 --- /dev/null +++ b/node_modules/tap/LICENSE @@ -0,0 +1,23 @@ +Copyright 2009, 2010, 2011 Isaac Z. Schlueter. +All rights reserved. + +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/tap/README.md b/node_modules/tap/README.md new file mode 100644 index 0000000..7e061aa --- /dev/null +++ b/node_modules/tap/README.md @@ -0,0 +1,82 @@ +This is a mix-and-match set of utilities that you can use to write test +harnesses and frameworks that communicate with one another using the +Test Anything Protocol. + +If you don't yet know what TAP is, [you better ask +somebody](http://testanything.org/). + +Default Usage: + +1. Make a directory. Maybe call it 'test'. That'd be nice and obvious. +2. Put a bunch of test scripts in there. If they're node programs, then + they should be ".js". Anything else is assumed to be some kind of shell + script, which should have a shebang line. +3. `npm install tap` +4. `tap ./tests` + +The output will be TAP-compliant. + +For extra special bonus points, you can do something like this: + + var test = require("tap").test + test("make sure the thingie is a thing", function (t) { + t.equal(thingie, "thing", "thingie should be thing") + t.type(thingie, "string", "type of thingie is string") + t.ok(true, "this is always true") + t.notOk(false, "this is never true") + t.test("a child test", function (t) { + t.equal(this, superEasy, "right!?") + t.similar(7, 2, "ever notice 7 is kinda like 2?", {todo: true}) + t.test("so skippable", {skip: true}, function (t) { + t.plan(1) // only one test in this block + t.ok(true, "but when the flag changes, it'll pass") + // no need to end, since we had a plan. + }) + t.end() + }) + t.ok(99, "can also skip individual assertions", {skip: true}) + // end lets it know it's over. + t.end() + }) + test("another one", function (t) { + t.plan(1) + t.ok(true, "It's ok to plan, and also end. Watch.") + t.end() // but it must match the plan! + }) + +Node-tap is actually a collection of several modules, any of which may be +mixed and matched however you please. + +If you don't like this test framework, and think you can do much much +better, *I strongly encourage you to do so!* If you use this library, +however, at least to output TAP-compliant results when `process.env.TAP` +is set, then the data coming out of your framework will be much more +consumable by machines. + +You can also use this to build programs that *consume* the TAP data, so +this is very useful for CI systems and such. + +* tap-assert: A collection of assert functions that return TAP result + objects. +* tap-consumer: A stream interface for consuming TAP data. +* tap-producer: A class that produces a TAP stream by taking in result + objects. +* tap-results: A class for keeping track of TAP result objects as they + pass by, counting up skips, passes, fails, and so on. +* tap-runner: A program that runs through a directory running all the + tests in it. (Tests which may or may not be TAP-outputting tests. But + it's better if they are.) +* tap-test: A class for actually running tests. +* tap-harness: A class that runs tests. (Tests are also Harnesses, + which is how sub-tests run.) +* tap-global-harness: A default harness that provides the top-level + support for running TAP tests. + +## Experimental Code Coverage with runforcover & bunker: + +``` +TAP_COV=1 tap ./tests [--cover=./lib,foo.js] [--cover-dir=./coverage] +``` + +This feature is experimental, and will most likely change somewhat +before being finalized. Feedback welcome. diff --git a/node_modules/tap/bin/tap-http.js b/node_modules/tap/bin/tap-http.js new file mode 100644 index 0000000..296910f --- /dev/null +++ b/node_modules/tap/bin/tap-http.js @@ -0,0 +1,19 @@ +#!/usr/bin/env node + +// just an example, really +// Run with `node tap-http.js path/to/tests/` + +var argv = process.argv.slice(2) + , path = require("path") + , Runner = require("../lib/tap-runner") + + , http = require("http") + , server = http.createServer(function (req, res) { + // it'd be nice to return a non-200 if the tests fail, but we don't + // know the status until it's done, so that would mean not being able + // to pipe the output + res.writeHead(200, {'content-type': 'text/plain'}) + new Runner(argv, null).pipe(res) + }) + +server.listen(1337) diff --git a/node_modules/tap/bin/tap-reader.js b/node_modules/tap/bin/tap-reader.js new file mode 100755 index 0000000..b196cc2 --- /dev/null +++ b/node_modules/tap/bin/tap-reader.js @@ -0,0 +1,33 @@ +#!/usr/bin/env node + +// read a tap stream from stdin. + +var TapConsumer = require("../lib/tap-consumer") + , TapProducer = require("../lib/tap-producer") + +var tc = new TapConsumer + , tp = new TapProducer + +//process.stdin.pipe(tc) +process.stdin.on("data", function (c) { + c = c + "" + // console.error(JSON.stringify(c).substr(0, 100)) + tc.write(c) +}) +process.stdin.on("end", function () { tc.end() }) +process.stdin.resume() +//tc.pipe(tp) +tc.on("data", function (c) { + tp.write(c) +}) +tc.on("end", function () { tp.end() }) + +tp.on("data", function (c) { + console.error(["output write", c]) + process.stdout.write(c) +}) + +tp.on("end", function (er, total, ok) { + if (er) throw er + process.exit(total - ok) +}) diff --git a/node_modules/tap/bin/tap.js b/node_modules/tap/bin/tap.js new file mode 100755 index 0000000..e6e7c8e --- /dev/null +++ b/node_modules/tap/bin/tap.js @@ -0,0 +1,127 @@ +#!/usr/bin/env node + +var argv = process.argv.slice(2) + , path = require("path") + , Runner = require("../lib/tap-runner") + + , nopt = require("nopt") + + , knownOpts = + { cover: [path, false] + , "cover-dir": path + , stderr: Boolean + , stdout: Boolean + , diag: Boolean + , version: Boolean + , tap: Boolean + , timeout: Number + } + + , shorthands = + // debugging 1: show stderr + { d: ["--stderr"] + // debugging 2: show stderr and tap + , dd: ["--stderr", "--tap"] + // debugging 3: show stderr, tap, AND always show diagnostics. + , ddd: ["--stderr", "--tap", "--diag"] + , e: ["--stderr"] + , t: ["--timeout"] + , o: ["--tap"] + , c: ["--cover"] + , v: ["--version"] + , "?": ["--help"] + , h: ["--help"] + } + + , defaults = + { cover: "./lib" + , "cover-dir": "./coverage" + , stderr: process.env.TAP_STDERR + , tap: process.env.TAP + , diag: process.env.TAP_DIAG + , timeout: +process.env.TAP_TIMEOUT || 30 + , version: false + , help: false } + + , options = nopt(knownOpts, shorthands) + +if (options.version) { + console.log(require("../package.json").version) + process.exit(0) +} + +if (options.help) { + console.log(function(){/* + +Usage: + tap + + Run the files as tap tests, parse the output, and report the results + +Options: + + --stderr Print standard error output of tests to standard error. + --tap Print raw tap output. + --diag Print diagnostic output for passed tests, as well as failed. + (Implies --tap) + --timeout Maximum time to wait for a subtest, in seconds. Default: 30 + --version Print the version of node tap + --help Print this help + +Please report bugs! https://github.com/isaacs/node-tap/issues + +*/}.toString().split(/\n/).slice(1, -1).join("\n")) + process.exit(0) +} + + +Object.keys(defaults).forEach(function (k) { + if (!options.hasOwnProperty(k)) options[k] = defaults[k] +}) + +// other tests that might rely on these +if (options.diag) process.env.TAP_DIAG = true +if (options.tap) process.env.TAP = true +if (options.timeout) process.env.TAP_TIMEOUT = options.timeout + +var r = new Runner(options) + , TapProducer = require("../lib/tap-producer") + +if (options.tap || options.diag) { + r.pipe(process.stdout) +} else { + r.on("file", function (file, results, details) { + var s = (details.ok ? "" : "not ") + "ok "+results.name + , n = details.pass + "/" + details.testsTotal + , dots = new Array(Math.max(1, 60 - s.length - n.length)).join(".") + console.log("%s %s %s", s, dots, n) + if (details.ok) { + if (details.skip) { + console.log(" skipped: %s", details.skipTotal) + } + } else { + // console.error(details) + console.log(" Command: %s", results.command) + console.log(" " + TapProducer.encode(details.list) + .split(/\n/).join("\n ")) + } + }) + r.on("end", function () { + //console.log(r) + var s = "total" + , n = r.results.pass + "/" + r.results.testsTotal + , dots = new Array(60 - s.length - n.length).join(".") + , ok = r.results.ok ? "ok" : "not ok" + console.log("%s %s %s\n\n%s", s, dots, n, ok) + if (r.doCoverage) { + console.error( "\nCoverage: %s\n" + , path.resolve(r.coverageOutDir, "index.html") ) + } + }) +} + + + +r.on("end", function () { + process.exit(r.results.tests - r.results.pass) +}) diff --git a/node_modules/tap/coverage-example/lib/bar.js b/node_modules/tap/coverage-example/lib/bar.js new file mode 100644 index 0000000..e7cb7ad --- /dev/null +++ b/node_modules/tap/coverage-example/lib/bar.js @@ -0,0 +1,15 @@ +var Bar = module.exports = function(str) { + this.bar = str; + this.str = str; +}; + +Bar.prototype.foo = function() { + var self = this; + return self.bar; +}; + +Bar.prototype.baz = function() { + var self = this; + return self.str; +}; + diff --git a/node_modules/tap/coverage-example/lib/foo.js b/node_modules/tap/coverage-example/lib/foo.js new file mode 100644 index 0000000..cb9ee8f --- /dev/null +++ b/node_modules/tap/coverage-example/lib/foo.js @@ -0,0 +1,15 @@ +var Foo = module.exports = function(str) { + this.foo = str; + this.str = str; +}; + +Foo.prototype.bar = function() { + var self = this; + return self.foo; +}; + +Foo.prototype.baz = function() { + var self = this; + return self.str; +}; + diff --git a/node_modules/tap/coverage-example/test/bar.test.js b/node_modules/tap/coverage-example/test/bar.test.js new file mode 100644 index 0000000..91e4bc2 --- /dev/null +++ b/node_modules/tap/coverage-example/test/bar.test.js @@ -0,0 +1,20 @@ +var test = require('tap').test, + Bar = require('../lib/bar'), + bar; + +test('setup', function(t) { + bar = new Bar('baz'); + t.ok(bar); + t.end(); +}); + +test('bar', function(t) { + t.equal('baz', bar.foo()); + t.end(); +}); + +test('teardown', function(t) { + t.ok(true); + t.end(); +}); + diff --git a/node_modules/tap/coverage-example/test/baz.test.js b/node_modules/tap/coverage-example/test/baz.test.js new file mode 100644 index 0000000..fae22d8 --- /dev/null +++ b/node_modules/tap/coverage-example/test/baz.test.js @@ -0,0 +1,29 @@ +var test = require('tap').test, + Foo = require('../lib/foo'), + Bar = require('../lib/bar'), + foo, bar; + +test('setup', function(t) { + foo = new Foo('baz'); + t.ok(foo); + bar = new Bar('baz'); + t.ok(bar); + t.end(); +}); + +test('baz from Foo', function(t) { + t.equal('baz', foo.baz()); + t.end(); +}); + +test('baz from Bar', function(t) { + t.equal('baz', bar.baz()); + t.end(); +}); + + +test('teardown', function(t) { + t.ok(true); + t.end(); +}); + diff --git a/node_modules/tap/coverage-example/test/foo.test.js b/node_modules/tap/coverage-example/test/foo.test.js new file mode 100644 index 0000000..2aed8fd --- /dev/null +++ b/node_modules/tap/coverage-example/test/foo.test.js @@ -0,0 +1,20 @@ +var test = require('tap').test, + Foo = require('../lib/foo'), + foo; + +test('setup', function(t) { + foo = new Foo('baz'); + t.ok(foo); + t.end(); +}); + +test('bar', function(t) { + t.equal('baz', foo.bar()); + t.end(); +}); + +test('teardown', function(t) { + t.ok(true); + t.end(); +}); + diff --git a/node_modules/tap/example/lib/math.js b/node_modules/tap/example/lib/math.js new file mode 100644 index 0000000..f798626 --- /dev/null +++ b/node_modules/tap/example/lib/math.js @@ -0,0 +1 @@ +module.exports = Math diff --git a/node_modules/tap/example/test/test-example.js b/node_modules/tap/example/test/test-example.js new file mode 100644 index 0000000..cd2549b --- /dev/null +++ b/node_modules/tap/example/test/test-example.js @@ -0,0 +1,237 @@ +var tap = require("tap") + , test = tap.test + , plan = tap.plan + , math + +test("load sut", function (t) { + math = require("../lib/math") + t.ok(math, "object loaded") + t.end() +}) + +test("validate constants", function (t) { + t.equal(math.LN10, 2.302585092994046, "ln 10") + t.equal(math.PI, 3.141592653589793, "pi") + t.equal(math.E, 2.718281828459045, "e") + t.equal(math.LOG10E, 0.4342944819032518, "log 10 e") + t.equal(math.SQRT2, 1.4142135623730951, "sqrt 2") + t.equal(math.SQRT1_2, 0.7071067811865476, "sqrt 1/2") + t.equal(math.LN2, 0.6931471805599453, "ln2") + t.end() +}) + +test("using this", function (t) { + // this also works. + this.equal(t, this, "call in scope of test obj") + this.end() +}) + +// test setTimeout, just a trivial example. +test("setTimeout", function (t) { + var start = Date.now() + setTimeout(function () { + t.ok(Date.now() >= start + 50, "timeout fired after delay") + t.end() + }, 50) +}) + +// another way to do the same, using a plan. +// this is more robust, but annoying when you have a long list +// of tests for something. For async stuff, it's generally better, +// since there's a higher risk of the control flowing off to lala land. +test("setTimeout planned", function (t) { + t.plan(1) + var start = Date.now() + setTimeout(function () { + t.ok(Date.now() >= start + 50, "timeout fired after delay") + }, 50) +}) + +// plans also are good for cases where things may fire in a non-deterministic +// order, since it won't be as obvious when everything is done. +test("setTimeout parallel", function (t) { + t.plan(2) + var start = Date.now() + setTimeout(function A () { + t.ok(Date.now() >= start + 50, "timeout A fired after delay") + }, 50) + setTimeout(function B () { + t.ok(Date.now() >= start + 50, "timeout B fired after delay") + }, 50) +}) + +// something slightly less hello worldy +test("async test", function (t) { + t.plan(4) + var fs = require("fs") + t.ok(fs, "fs library should load") + var rs = fs.createReadStream(__filename) + t.ok(rs, "read stream should start fine.") + rs.on("open", function (fd) { + t.type(fd, "number", "file descriptor should be a number") + t.equal(fd, rs.fd, "fd should match stream fd") + }) +}) + +// you can bail out of the entire everything if something is just +// Not Right (db not installed, etc.) +test("tarp", function (parent) { + if (7 === 5) { + parent.bailout("math is broken") + } + // bailout bubbles up a bit like "error" events + // if unhandled, then the parent will bail, as well. + parent.test("child bailouts", function (child) { + child.on("bailout", function (s) { + parent.fail("children shouldn't bail.") + }) + child.bailout("try to bail out, but instead just fail a test") + }) + + parent.test("child bailout 2", function (child) { + child.bailout("this one will bail out") + }) +}) + +// tests marked "todo" can fail without counting against the overall score +// never ever ever write tests to "verify" incorrect behavior! +test("unfinished test", function (t) { + t.equal(math.cos(math.PI), -1, "cos(PI)") + t.equal(math.sin(math.PI), 0, "sin(PI)") + t.equal(math.face, "your face", "math.face should be your face # TODO") + t.end() +}) + +// tests can have children. +test("http server", function (t) { + // one test plus 4 children. + t.plan(5) + + var http = require("http") + , PORT = 12346 + + t.ok(http, "http module should load") + var server + + t.test("set up server", function (t) { + t.plan(2) + server = http.createServer(function (req, res) { + t.comment("Request: "+req.url) + res.writeHead(200, {}) + res.end(req.method + " " + req.url) + }) + t.ok(server, "createServer should create a server") + server.listen(PORT, t.cb("listen should fire callback")) + }) + + // set the "parallel" flag on this one. + // That signals the harness to proceed immediately to the next test, + // and run them in parallel. + // Default behavior is to wait for each test to complete before proceeding + // to the next one. + // The first not-parallel test encountered will cause it to wait for that + // test, as well as all the parallel tests before it. + // A, B', C', D', E (where ' means "parallel") + // Runs A, and then B, C, and D in parallel, and then E. + t.test("testing POST", {parallel: true}, function (t) { + t.plan(1) + http.request("POST", { method: "POST" + , host: "localhost" + , path: "/foo" + , port: PORT }).on("response", function (res) { + t.bufferStream(res, function (s) { t.equal(s, "POST /foo") }) + }).end() + }) + + t.test("testing GET", {parallel: true}, function (t) { + t.plan(1) + http.request("POST", { method: "GET" + , host: "localhost" + , path: "/foo" + , port: PORT }).on("response", function (res) { + t.bufferStream(res, function (s) { t.equal(s, "GET /foo") }) + }).end() + }) + + // wrap in a test so that if this throws, it'll log as a failed test. + t.test("teardown", function (t) { + server.close() + t.end() + }) +}) + +// yo dawg! +test("meta-tests", function (t) { + t.plan(5) + + // t.fails() wraps a child test and succeeds if it fails. + t.fails(t.test("this should fail", function (t) { + t.ok(false, "assert false") + t.end() + })) + + // t.timesOut() wraps a child test and succeeds if it times out. + // if t.end() is called, or if a plan is completed, then it fails. + // set the timeout really low so that it will not take forever. + t.timesOut(t.test("this should timeout", { timeout: 1 }, function (t) { + t.ok(true, "assert true") + // t.end() never called. + })) + + // t.incomplete() wraps a child test and succeeds if it ends before + // the plan is finished. + t.incomplete(t.test("this should be incomplete", function (t) { + t.plan(100) + t.ok(true, "assert true") + // calling end prematurely. + t.end() + })) + + // t.bailsOut() wraps a child test and succeeds if it calls bailout() + t.bailsOut(t.test("this should bailout", function (t) { + t.bailout("oh noes, bailing out!") + })) + + // low-level analysis of subtests + t.test("verifying test success/failure expectations", function (t) { + t.once("end", function () { + var res = t.results + , is = t.equal + // hijack! + t.clear() + is(res.ok, false, "ok") + + is(res.bailedOut, false, "bailed out") + + is(res.skip, 2, "skips") + is(res.skipPass, 1, "skip that passed") + is(res.skipFail, 1, "skip that failed") + + is(res.todo, 2, "todos") + is(res.todoPass, 1, "todo that passed") + is(res.todoFail, 1, "todo that failed") + + is(res.failTotal, 3, "failures total") + is(res.fail, 1, "relevant failure") + + is(res.passTotal, 3, "passes total") + is(res.pass, 1, "relevant pass") + + is(res.testsTotal, 6, "total tests") + is(res.tests, 2, "should be 2 relevant tests") + + t.end() + }) + + // run the metatest. + // *this* is the actual SUT in this case. + t.ok(false, "failing todo #todo") + // can also set #todo or #skip explicitly + t.ok(true, "succeeding todo", {todo: true}) + t.ok(false, "failing skip #skip", {skip: true}) + t.ok(true, "suceeding skip #skip") + t.ok(false, "failing test") + t.ok(true, "succeeding test") + t.end() + }) +}) diff --git a/node_modules/tap/lib/main.js b/node_modules/tap/lib/main.js new file mode 100644 index 0000000..a9a520a --- /dev/null +++ b/node_modules/tap/lib/main.js @@ -0,0 +1,16 @@ + +var GlobalHarness = require("./tap-global-harness") + +// this lets you do stuff like: +// var test = require("tap").test +// test(...) +// to run stuff in the global harness. +exports = module.exports = new GlobalHarness() + +exports.createProducer = exports.Producer = require("./tap-producer") +exports.createConsumer = exports.Consumer = require("./tap-consumer") +exports.yamlish = require("yamlish") +exports.createTest = exports.Test = require("./tap-test") +exports.createHarness = exports.Harness = require("./tap-harness") +exports.createRunner = exports.Runner = require("./tap-runner") +exports.assert = require("./tap-assert") diff --git a/node_modules/tap/lib/tap-assert.js b/node_modules/tap/lib/tap-assert.js new file mode 100644 index 0000000..bde5f11 --- /dev/null +++ b/node_modules/tap/lib/tap-assert.js @@ -0,0 +1,442 @@ +// an assert module that returns tappable data for each assertion. +var difflet = require('difflet') + , deepEqual = require('deep-equal') + , bufferEqual = require('buffer-equal') + +module.exports = assert + +var syns = {} + , id = 1 + +function assert (ok, message, extra) { + if (extra && extra.skip) return assert.skip(message, extra) + + //console.error("assert %j", [ok, message, extra]) + //if (extra && extra.skip) return assert.skip(message, extra) + //console.error("assert", [ok, message, extra]) + ok = !!ok + var res = { id : id ++, ok: ok } + + var caller = getCaller(extra && extra.error) + if (extra && extra.error) { + res.type = extra.error.name + res.message = extra.error.message + res.code = extra.error.code + || extra.error.type + res.errno = extra.error.errno + delete extra.error + } + if (caller.file) { + res.file = caller.file + res.line = +caller.line + res.column = +caller.column + } + res.stack = caller.stack + + res.name = message || "(unnamed assert)" + + if (extra) Object.keys(extra).forEach(function (k) { + if (!res.hasOwnProperty(k)) res[k] = extra[k] + }) + + // strings and objects are hard to diff by eye + if (!ok && + res.hasOwnProperty("found") && + res.hasOwnProperty("wanted") && + res.found !== res.wanted) { + if (typeof res.wanted !== typeof res.found || + typeof res.wanted === "object" && (!res.found || !res.wanted)) { + res.type = { found: typeof found + , wanted: typeof wanted } + } else if (typeof res.wanted === "string") { + res.diff = diffString(res.found, res.wanted) + } else if (typeof res.wanted === "object") { + res.diff = diffObject(res.found, res.wanted) + } + } + + //console.error("assert return", res) + + return res +} +assert.ok = assert +syns.ok = [ "true", "assert" ] + + +function notOk (ok, message, extra) { + return assert(!ok, message, extra) +} +assert.notOk = notOk +syns.notOk = [ "false", "notok" ] + +function error (er, message, extra) { + if (!er) { + // just like notOk(er) + return assert(!er, message, extra) + } + message = message || er.message + extra = extra || {} + extra.error = er + return assert.fail(message, extra) +} +assert.error = error +syns.error = [ "ifError", "ifErr", "iferror" ] + + +function pass (message, extra) { + return assert(true, message, extra) +} +assert.pass = pass + +function fail (message, extra) { + //console.error("assert.fail", [message, extra]) + //if (extra && extra.skip) return assert.skip(message, extra) + return assert(false, message, extra) +} +assert.fail = fail + +function skip (message, extra) { + //console.error("assert.skip", message, extra) + if (!extra) extra = {} + return { id: id ++, skip: true, name: message || "" } +} +assert.skip = skip + +function throws (fn, wanted, message, extra) { + if (typeof wanted === "string") { + extra = message + message = wanted + wanted = null + } + + if (extra && extra.skip) return assert.skip(message, extra) + + var found = null + try { + fn() + } catch (e) { + found = { name: e.name, message: e.message } + } + + extra = extra || {} + + extra.found = found + if (wanted) { + wanted = { name: wanted.name, message: wanted.message } + extra.wanted = wanted + } + + if (!message) { + message = "Expected to throw" + if (wanted) message += ": "+wanted.name + " " + wanted.message + } + + return (wanted) ? assert.similar(found, wanted, message, extra) + : assert.ok(found, message, extra) +} +assert.throws = throws + + +function doesNotThrow (fn, message, extra) { + if (extra && extra.skip) return assert.skip(message, extra) + var found = null + try { + fn() + } catch (e) { + found = {name: e.name, message: e.message} + } + message = message || "Should not throw" + + return assert.equal(found, null, message, extra) +} +assert.doesNotThrow = doesNotThrow + + +function equal (a, b, message, extra) { + if (extra && extra.skip) return assert.skip(message, extra) + extra = extra || {} + message = message || "should be equal" + extra.found = a + extra.wanted = b + return assert(a === b, message, extra) +} +assert.equal = equal +syns.equal = ["equals" + ,"isEqual" + ,"is" + ,"strictEqual" + ,"strictEquals"] + + +function equivalent (a, b, message, extra) { + if (extra && extra.skip) return assert.skip(message, extra) + var extra = extra || {} + message = message || "should be equivalent" + extra.found = a + extra.wanted = b + + if (Buffer.isBuffer(a) && Buffer.isBuffer(b)) { + return assert(bufferEqual(a, b), message, extra) + } else { + return assert(deepEqual(a, b), message, extra) + } +} +assert.equivalent = equivalent +syns.equivalent = ["isEquivalent" + ,"looseEqual" + ,"looseEquals" + ,"isDeeply" + ,"same" + ,"deepEqual" + ,"deepEquals"] + + +function inequal (a, b, message, extra) { + if (extra && extra.skip) return assert.skip(message, extra) + extra = extra || {} + message = message || "should not be equal" + extra.found = a + extra.doNotWant = b + return assert(a !== b, message, extra) +} +assert.inequal = inequal +syns.inequal = ["notEqual" + ,"notEquals" + ,"isNotEqual" + ,"isNot" + ,"not" + ,"doesNotEqual" + ,"isInequal"] + + +function inequivalent (a, b, message, extra) { + if (extra && extra.skip) return assert.skip(message, extra) + extra = extra || {} + message = message || "should not be equivalent" + extra.found = a + extra.doNotWant = b + + if (Buffer.isBuffer(a) && Buffer.isBuffer(b)) { + return assert(!bufferEqual(a, b), message, extra) + } else { + return assert(!deepEqual(a, b), message, extra) + } +} +assert.inequivalent = inequivalent +syns.inequivalent = ["notEquivalent" + ,"notDeepEqual" + ,"notDeeply" + ,"notSame" + ,"isNotDeepEqual" + ,"isNotDeeply" + ,"isNotEquivalent" + ,"isInequivalent"] + +function similar (a, b, message, extra, flip) { + if (extra && extra.skip) return assert.skip(message, extra) + // test that a has all the fields in b + message = message || "should be similar" + + if (typeof a === "string" && + (Object.prototype.toString.call(b) === "[object RegExp]")) { + extra = extra || {} + extra.pattern = b + extra.string = a + var ok = a.match(b) + extra.match = ok + if (flip) ok = !ok + return assert.ok(ok, message, extra) + } + + var isObj = assert(a && typeof a === "object", message, extra) + if (!isObj.ok) { + // not an object + if (a == b) isObj.ok = true + if (flip) isObj.ok = !isObj.ok + return isObj + } + + var eq = flip ? inequivalent : equivalent + return eq(selectFields(a, b), b, message, extra) +} +assert.similar = similar +syns.similar = ["isSimilar" + ,"has" + ,"hasFields" + ,"like" + ,"isLike"] + +function dissimilar (a, b, message, extra) { + if (extra && extra.skip) return assert.skip(message, extra) + message = message || "should be dissimilar" + return similar(a, b, message, extra, true) +} +assert.dissimilar = dissimilar +syns.dissimilar = ["unsimilar" + ,"notSimilar" + ,"unlike" + ,"isUnlike" + ,"notLike" + ,"isNotLike" + ,"doesNotHave" + ,"isNotSimilar" + ,"isDissimilar"] + +function type (thing, t, message, extra) { + if (extra && extra.skip) return assert.skip(message, extra) + var name = t + if (typeof name === "function") name = name.name || "(anonymous ctor)" + //console.error("name=%s", name) + message = message || "type is "+name + var type = typeof thing + //console.error("type=%s", type) + if (!thing && type === "object") type = "null" + if (type === "object" && t !== "object") { + if (typeof t === "function") { + //console.error("it is a function!") + extra = extra || {} + extra.found = Object.getPrototypeOf(thing).constructor.name + extra.wanted = name + //console.error(thing instanceof t, name) + return assert.ok(thing instanceof t, message, extra) + } + + //console.error("check prototype chain") + // check against classnames or objects in prototype chain, as well. + // type(new Error("asdf"), "Error") + // type(Object.create(foo), foo) + var p = thing + while (p = Object.getPrototypeOf(p)) { + if (p === t || p.constructor && p.constructor.name === t) { + type = name + break + } + } + } + //console.error(type, name, type === name) + return assert.equal(type, name, message, extra) +} +assert.type = type +syns.type = ["isa"] + +// synonyms are helpful. +Object.keys(syns).forEach(function (c) { + syns[c].forEach(function (s) { + Object.defineProperty(assert, s, { value: assert[c], enumerable: false }) + }) +}) + +// helpers below + +function selectFields (a, b) { + // get the values in A of the fields in B + var ret = Array.isArray(b) ? [] : {} + Object.keys(b).forEach(function (k) { + if (!a.hasOwnProperty(k)) return + var v = b[k] + , av = a[k] + if (v && av && typeof v === "object" && typeof av === "object" + && !(v instanceof Date) + && !(v instanceof RegExp) + && !(v instanceof String) + && !(v instanceof Boolean) + && !(v instanceof Number) + && !(Array.isArray(v))) { + ret[k] = selectFields(av, v) + } else ret[k] = av + }) + return ret +} + +function sortObject (obj) { + if (typeof obj !== 'object' || Array.isArray(obj) || obj === null) { + return obj + } + + return Object.keys(obj).sort().reduce(function (acc, key) { + acc[key] = sortObject(obj[key]) + return acc + }, {}) +} + +function stringify (a) { + return JSON.stringify(sortObject(a), (function () { + var seen = [] + , keys = [] + return function (key, val) { + var s = seen.indexOf(val) + if (s !== -1) { + return "[Circular: "+keys[s]+"]" + } + if (val && typeof val === "object" || typeof val === "function") { + seen.push(val) + keys.push(val["!"] || val.name || key || "") + if (typeof val === "function") { + return val.toString().split(/\n/)[0] + } else if (typeof val.toUTCString === "function") { + return val.toUTCString() + } + } + return val + }})()) +} + +function diffString (f, w) { + if (w === f) return null + var p = 0 + , l = w.length + while (p < l && w.charAt(p) === f.charAt(p)) p ++ + w = stringify(w).substr(1).replace(/"$/, "") + f = stringify(f).substr(1).replace(/"$/, "") + return diff(f, w, p) +} + +function diffObject (f, w) { + return difflet({ indent : 2, comment : true }).compare(w, f) +} + +function diff (f, w, p) { + if (w === f) return null + var i = p || 0 // it's going to be at least p. JSON can only be bigger. + , l = w.length + while (i < l && w.charAt(i) === f.charAt(i)) i ++ + var pos = Math.max(0, i - 20) + w = w.substr(pos, 40) + f = f.substr(pos, 40) + var pointer = i - pos + return "FOUND: "+f+"\n" + + "WANTED: "+w+"\n" + + (new Array(pointer + 9).join(" ")) + + "^ (at position = "+p+")" +} + +function getCaller (er) { + // get the first file/line that isn't this file. + if (!er) er = new Error + var stack = er.stack || "" + stack = stack.split(/\n/) + for (var i = 1, l = stack.length; i < l; i ++) { + var s = stack[i].match(/\(([^):]+):([0-9]+):([0-9]+)\)$/) + if (!s) continue + var file = s[1] + , line = +s[2] + , col = +s[3] + if (file.indexOf(__dirname) === 0) continue + if (file.match(/tap-test\/test.js$/)) continue + else break + } + var res = {} + if (file && file !== __filename && !file.match(/tap-test\/test.js$/)) { + res.file = file + res.line = line + res.column = col + } + + res.stack = stack.slice(1).map(function (s) { + return s.replace(/^\s*at\s*/, "") + }) + + return res +} + + diff --git a/node_modules/tap/lib/tap-browser-harness.js b/node_modules/tap/lib/tap-browser-harness.js new file mode 100644 index 0000000..6e6cda7 --- /dev/null +++ b/node_modules/tap/lib/tap-browser-harness.js @@ -0,0 +1,63 @@ +// this is just a harness that pipes to stdout. +// It's the default one. +module.exports = BrowserHarness + +var BrowserHarness = global.TAP_Browser_Harness + , inherits = require("inherits") + , Results = require("./tap-results") + , Harness = require("./tap-harness") + , Test = require("./tap-test") + +inherits(BrowserHarness, Harness) +function BrowserHarness (outPipe) { + //console.error("calling BrowserHarness") + if (browserHarness) return browserHarness + if (!(this instanceof BrowserHarness)) { + return browserHarness = new BrowserHarness + } + browserHarness = global.TAP_Browser_Harness = this + BrowserHarness.super.call(this, Test) + + if (outPipe) this.output.pipe(outPipe) + + this.test = this.test.bind(this) + + this.plan = this.plan.bind(this) + + var output = this.output + this.on("childEnd", function (child) { + //console.error("childEnd in global harness") + //console.error(child.results) + // write out the stuff for this child. + //console.error("child.conf", child.conf) + output.write(child.conf.name || "(unnamed test)") + // maybe write some other stuff about the number of tests in this + // thing, etc. I dunno. + //console.error("child results", child.results) + this.results.list.forEach(function (res) { + //delete res.error + //console.error("child resuilt", res) + output.write(res) + }) + //console.error("wrote child results") + this.results.list.length = 0 + }) + + var streamEnded = false + this.on("end", function () { + //console.error("global ending the stream") + if (!streamEnded) { + this.results.list.forEach(function (res) { + output.write(res) + }) + this.results.list.length = 0 + output.end() + streamEnded = true + } + }) + + // TODO: handle global errors + // process.on("unhandledException", function (e) { + // this.bailout("unhandled exception: " + e.message) + // }) +} diff --git a/node_modules/tap/lib/tap-consumer.js b/node_modules/tap/lib/tap-consumer.js new file mode 100644 index 0000000..3fd8fea --- /dev/null +++ b/node_modules/tap/lib/tap-consumer.js @@ -0,0 +1,243 @@ +module.exports = TapConsumer + +// pipe a stream into this that's emitting tap-formatted data, +// and it'll emit "data" events with test objects or comment strings +// and an "end" event with the final results. + +var yamlish = require("yamlish") + , Results = require("./tap-results") + , inherits = require("inherits") + +TapConsumer.decode = TapConsumer.parse = function (str) { + var tc = new TapConsumer + , list = [] + tc.on("data", function (res) { + list.push(res) + }) + tc.end(str) + tc.results.list = list + return tc.results +} + +inherits(TapConsumer, require("stream").Stream) +function TapConsumer () { + if (!(this instanceof TapConsumer)) { + return new TapConsumer + } + + TapConsumer.super.call(this) + this.results = new Results + this.readable = this.writable = true + + this.on("data", function (res) { + if (typeof res === "object") this.results.add(res) + }) + + this._plan = null + this._buffer = "" + this._indent = [] + this._current = null + this._actualCount = 0 + this._passed = [] + this._failed = [] + //console.error("TapConsumer ctor done") +} + +TapConsumer.prototype.bailedOut = false + +TapConsumer.prototype.write = function (chunk) { + if (!this.writable) this.emit("error", new Error("not writable")) + if (this.bailedOut) return true + + this._buffer = this._buffer + chunk + // split it up into lines. + var lines = this._buffer.split(/\r?\n/) + // ignore the last line, since it might be incomplete. + this._buffer = lines.pop() + + for (var i = 0, l = lines.length; i < l; i ++) { + //console.error([i, lines[i]]) + // see if it's indented. + var line = lines[i] + , spaces = (this._indent.length && !line.trim()) + || line.match(/^\s/) + // at this level, only interested in fully undented stuff. + if (spaces) { + var c = i + while (c < l && (!lines[c].trim() || lines[c].match(/^\s/))) { + this._indent.push(lines[c++]) + } + //console.error(c-i, "indented", this._indent, this._current) + i = c - 1 + continue + } + // some kind of line. summary, ok, notok, comment, or garbage. + // this also finishes parsing any of the indented lines from before + this._parseLine(line) + } + return true +} + +TapConsumer.prototype.end = function () { + // finish up any hanging indented sections or final buffer + if (this._buffer.match(/^\s/)) this._indent.push(this.buffer) + else this._parseLine(this._buffer) + + if (!this.bailedOut && + this._plan !== null && + this.results.testsTotal !== this._plan) { + while (this._actualCount < this._plan) { + this.emit("data", {ok: false, name:"MISSING TEST", + id:this._actualCount ++ }) + } + } + + this._parseLine("") + this._buffer = "" + this.writable = false + this.emit("end", null, this._actualCount, this._passed) +} + +TapConsumer.prototype._parseLine = function (line) { + if (this.bailedOut) return + //console.error("_parseLine", [line]) + // if there are any indented lines, and there is a + // current object already, then they belong to it. + // if there is not a current object, then they're garbage. + if (this._current && this._indent.length) { + this._parseIndented() + } + this._indent.length = 0 + if (this._current) { + if (this._current.ok) this._passed.push(this._current.id) + else this._failed.push(this._current.id) + this.emit("data", this._current) + } + this._current = null + line = line.trim() + if (!line) return + // try to see what kind of line this is. + + var bo + if (bo = line.match(/^bail out!\s*(.*)$/i)) { + this.bailedOut = true + // this.emit("error", new Error(line)) + this.emit("bailout", bo[1]) + return + } + + if (line.match(/^#/)) { // just a comment + line = line.replace(/^#+/, "").trim() + // console.error("outputting comment", [line]) + if (line) this.emit("data", line) + return + } + + var plan = line.match(/^([0-9]+)\.\.([0-9]+)(?:\s+#(.*))?$/) + if (plan) { + var start = +(plan[1]) + , end = +(plan[2]) + , comment = plan[3] + + // TODO: maybe do something else with this? + // it might be something like: "1..0 #Skip because of reasons" + this._plan = end + this.emit("plan", end, comment) + // plan must come before or after all tests. + if (this._actualCount !== 0) { + this._sawPlan = true + } + return + } + + if (line.match(/^(not )?ok(?:\s+([0-9]+))?/)) { + this._parseResultLine(line) + return + } + + // garbage. emit as a comment. + //console.error("emitting", [line.trim()]) + if (line.trim()) this.emit("data", line.trim()) +} + +TapConsumer.prototype._parseDirective = function (line) { + line = line.trim() + if (line.match(/^TODO\b/i)) { + return { todo:true, explanation: line.replace(/^TODO\s*/i, "") } + } else if (line.match(/^SKIP\b/i)) { + return { skip:true, explanation: line.replace(/^SKIP\s*/i, "") } + } +} + +TapConsumer.prototype._parseResultLine = function (line) { + this._actualCount ++ + if (this._sawPlan) { + this.emit("data", {ok: false, name:"plan in the middle of tests" + ,id:this._actualCount ++}) + } + var parsed = line.match(/^(not )?ok(?: ([0-9]+))?(?:(?: - )?(.*))?$/) + , ok = !parsed[1] + , id = +(parsed[2] || this._actualCount) + , rest = parsed[3] || "" + , name + , res = { id:id, ok:ok } + + // split on un-escaped # characters + + //console.log("# "+JSON.stringify([name, rest])) + rest = rest.replace(/([^\\])((?:\\\\)*)#/g, "$1\n$2").split("\n") + name = rest.shift() + rest = rest.filter(function (r) { return r.trim() }).join("#") + //console.log("# "+JSON.stringify([name, rest])) + + // now, let's see if there's a directive in there. + var dir = this._parseDirective(rest.trim()) + if (!dir) name += rest ? "#" + rest : "" + else { + res.ok = true + if (dir.skip) res.skip = true + else if (dir.todo) res.todo = true + if (dir.explanation) res.explanation = dir.explanation + } + res.name = name + + //console.error(line, [ok, id, name]) + this._current = res +} + +TapConsumer.prototype._parseIndented = function () { + // pull yamlish block out + var ind = this._indent + , ys + , ye + , yind + , diag + //console.error(ind, this._indent) + for (var i = 0, l = ind.length; i < l; i ++) { + var line = ind[i] + , lt = line.trim() + if (!ys) { + ys = line.match(/^(\s*)---(.*)$/) + if (ys) { + yind = ys[1] + diag = [ys[2]] + //console.error([line,ys, diag]) + continue + } else if (lt) this.emit("data", lt) + } else if (ys && !ye) { + if (line === yind + "...") ye = true + else { + diag.push(line.substr(yind.length)) + } + } else if (ys && ye && lt) this.emit("data", lt) + } + if (diag) { + //console.error('about to parse', diag) + diag = yamlish.decode(diag.join("\n")) + //console.error('parsed', diag) + Object.keys(diag).forEach(function (k) { + //console.error(this._current, k) + if (!this._current.hasOwnProperty(k)) this._current[k] = diag[k] + }, this) + } +} diff --git a/node_modules/tap/lib/tap-cov-html.js b/node_modules/tap/lib/tap-cov-html.js new file mode 100644 index 0000000..3c1c192 --- /dev/null +++ b/node_modules/tap/lib/tap-cov-html.js @@ -0,0 +1,78 @@ +var fs = require('fs'), + path = require('path'), + asyncMap = require("slide").asyncMap, + util = require('util'); + +var CovHtml = module.exports = function(cov_stats, cov_dir, cb) { + var index = []; + + asyncMap( + Object.keys(cov_stats), + function(f, cb) { + var st = cov_stats[f], + missing_lines = st.missing.map(function(l) { + return l.number; + }), + out = '\n\n\n ' + + '\n ' + + + f + ' (' + st.loc + ')\n' + + '\n' + + '\n\n' + + '

' + f + ' (' + st.loc + ')' + '

' + + '

Run: ' + (st.missing.length ? st.loc - st.missing.length : st.loc) + ', Missing: ' + + st.missing.length + ', Percentage: ' + st.percentage + '

' + + '

Source:

\n' + + '
    \n' + + st.lines.map(function(line) { + var number = line.number, + color = (missing_lines.indexOf(number) !== -1) ? '#fcc' : '#cfc'; + return '
  1. ' + line.source.replace(/'; + }).join('\n') + + '
\n' + + '

Data

\n'+ + '
' + util.inspect(st, true, Infinity, false).replace(/\n';
+
+      fs.writeFile(
+        cov_dir + '/' + 
+        f.replace(process.cwd() + '/', '').replace(/\//g, '+') + '.html',
+        out,
+        'utf8',
+        function(err) {
+          if (err) {
+            throw err;
+          }
+          index.push(f);
+          cb();
+        });
+    },
+    function(err) {
+      if (err) {
+        throw err;
+      }
+      var out = '\n\n\n  ' +
+          '\n  Coverage Index\n\n' +
+          '\n

Code Coverage Information

\n
\n\n'; + + fs.writeFile(cov_dir + '/index.html', out, 'utf8', function(err) { + if (err) { + throw err; + } + cb(); + }); + } + ); +}; + + diff --git a/node_modules/tap/lib/tap-global-harness.js b/node_modules/tap/lib/tap-global-harness.js new file mode 100644 index 0000000..0bcb3a4 --- /dev/null +++ b/node_modules/tap/lib/tap-global-harness.js @@ -0,0 +1,68 @@ +// this is just a harness that pipes to stdout. +// It's the default one. +module.exports = GlobalHarness + +var globalHarness = global.TAP_Global_Harness + , inherits = require("inherits") + , Results = require("./tap-results") + , Harness = require("./tap-harness") + , Test = require("./tap-test") + +inherits(GlobalHarness, Harness) +function GlobalHarness () { + //console.error("calling GlobalHarness") + if (globalHarness) return globalHarness + if (!(this instanceof GlobalHarness)) { + return globalHarness = new GlobalHarness + } + + globalHarness = global.TAP_Global_Harness = this + GlobalHarness.super.call(this, Test) + + this.output.pipe(process.stdout) + //this.output.on("data", function () { + // process.nextTick(process.stdout.flush.bind(process.stdout)) + //}) + + this.test = this.test.bind(this) + + this.plan = this.plan.bind(this) + + var output = this.output + this.on("childEnd", function (child) { + //console.error("childEnd in global harness") + //console.error(child.results) + // write out the stuff for this child. + //console.error("child.conf", child.conf) + output.write(child.conf.name || "(unnamed test)") + // maybe write some other stuff about the number of tests in this + // thing, etc. I dunno. + //console.error("child results", child.results) + this.results.list.forEach(function (res) { + //delete res.error + //console.error("child resuilt", res) + output.write(res) + }) + //console.error("wrote child results") + this.results.list.length = 0 + }) + + var streamEnded = false + this.on("end", function () { + //console.error("global ending the stream") + if (!streamEnded) { + this.results.list.forEach(function (res) { + output.write(res) + }) + this.results.list.length = 0 + output.end() + streamEnded = true + } + }) + + //this.on("end", this.output.end.bind(this.output)) + + process.on("unhandledException", function (e) { + this.bailout("unhandled exception: " + e.message) + }) +} diff --git a/node_modules/tap/lib/tap-harness.js b/node_modules/tap/lib/tap-harness.js new file mode 100644 index 0000000..7aa6cd6 --- /dev/null +++ b/node_modules/tap/lib/tap-harness.js @@ -0,0 +1,219 @@ +// a thing that runs tests. +// Every "test" is also a harness. If they do not have a harness, +// then they are attached to the defaut "global harness", +// which writes its results to stdout. + + +// TODO: +// - Bailout should stop running any tests. +// - "skip" in the test config obj should skip it. + +module.exports = Harness +require("inherits")(Harness, require("events").EventEmitter) + +var Results = require("./tap-results") + , TapProducer = require("./tap-producer") + , assert = require("./tap-assert") + +function Harness (Test) { + if (!(this instanceof Harness)) return new Harness(Test) + + //console.error("Test in "+this.constructor.name, Test) + + this._Test = Test + this._plan = null + this._children = [] + this._started = false + + this._testCount = 0 + this._planSum = 0 + + this.results = new Results() + // emit result events on the harness. + //this.results.on("result", function (res) { + // console.error("proxying result ev from res to harness") + // this.emit("result", res) + //}.bind(this)) + var me = this + this.results.on("result", this.emit.bind(this, "result")) + + var p = this.process.bind(this) + this.process = function () { + this._started = true + process.nextTick(p) + } + + this.output = new TapProducer() + Harness.super.call(this) +} + +// this function actually only gets called bound to +// the Harness object, and on process.nextTick. Even if +// passed as an event handler, everything *else* will +// happen before it gets called. +Harness.prototype.process = function () { + //console.error("harness process") + // "end" can emit multiple times, so only actually move on + // to the next test if the current one is actually over. + // TODO: multiple in-process tests, if all are marked "async" + if (this._current) { + if (!this._current._ended) return + // handle the current one before moving onto the next. + this.childEnd(this._current) + } + var skip = true + while (skip) { + //console.error("checking for skips") + var current = this._current = this._children.shift() + if (current) { + skip = current.conf.skip + if (skip) { + //console.error("add a failure for the skipping") + this.results.add(assert.fail(current.conf.name + ,{skip:true, diag:false})) + } + } else skip = false + } + + // keep processing through skipped tests, instead of running them. + if (current && this._bailedOut) { + return this.process() + } + + //console.error("got current?", !!current) + if (current) { + current.on("end", this.process) + current.emit("ready") + //console.error("emitted ready") + //console.error("_plan", this._plan, this.constructor.name) + } else { + //console.error("Harness process: no more left. ending") + if (this._endNice) { + this._endNice() + } else { + this.end() + } + } +} + +Harness.prototype.end = function () { + if (this._children.length) { + return this.process() + } + //console.error("harness end", this.constructor.name) + if (this._bailedOut) return + + // can't call .end() more than once. + if (this._ended) { + //console.error("adding failure for end calling") + this.results.add(assert.fail("end called more than once")) + } + + // see if the plan is completed properly, if there was one. + if (this._plan !== null) { + var total = this._testCount + if (total !== this._plan) { + this.results.add(assert.equal(total, this._plan, "test count != plan")) + } + this._plan = total + } + + //console.error("setting ended true", this.constructor.name) + this._ended = true + this.emit("end") +} + +Harness.prototype.plan = function (p) { + //console.error("setting plan", new Error().stack) + if (this._plan !== null) { + //console.error("about to add failure for calling plan") + return this.results.add(assert.fail("plan set multiple times")) + } + this._plan = p + if (p === 0 || this.results.testsTotal) { + this.end() + } +} + +Harness.prototype.childEnd = function (child) { + //console.error("childEnd") + this._testCount ++ + this._planSum += child._plan + //console.error("adding set of child.results") + this.results.addSet(child.results) + this.emit("childEnd", child) + // was this planned? + if (this._plan === this._testCount) { + //console.error("plan", [this._plan, this._testCount]) + return this.end() + } +} + +function copyObj(o) { + var copied = {} + Object.keys(o).forEach(function (k) { copied[k] = o[k] }) + return copied +} + +Harness.prototype.test = function test (name, conf, cb) { + if (this._bailedOut) return + + if (typeof conf === "function") cb = conf, conf = null + if (typeof name === "object") conf = name, name = null + if (typeof name === "function") cb = name, name = null + + conf = (conf ? copyObj(conf) : {}) + name = name || "" + + //console.error("making test", [name, conf, cb]) + + // timeout: value in milliseconds. Defaults to 30s + // Set to Infinity to have no timeout. + if (isNaN(conf.timeout)) conf.timeout = 30000 + var t = new this._Test(this, name, conf) + var self = this + if (cb) { + //console.error("attaching cb to ready event") + t.on("ready", function () { + if (!isNaN(conf.timeout) && isFinite(conf.timeout)) { + var timer = setTimeout(this.timeout.bind(this), conf.timeout) + var clear = clearTimeout.bind(null, timer) + t.on("end", clear) + t.on("bailout", function (message) { + self.bailout(message) + clear() + }) + } + }) + t.on("ready", cb.bind(t, t)) + // proxy the child results to this object. + //t.on("result", function (res) { + // console.error("in harness, proxying result up") + // t.results.add(res) + //}) + } + return t +} + +Harness.prototype.bailout = function (message) { + // console.error("Harness bailout", this.constructor.name) + message = message || "" + //console.error("adding bailout message result") + this.results.add({bailout: message}) + // console.error(">>> results after bailout" , this.results) + this._bailedOut = true + this.emit("bailout", message) + this.output.end({bailout: message}) +} + +Harness.prototype.add = function (child) { + //console.error("adding child") + this._children.push(child) + if (!this._started) this.process() +} + +// the tearDown function is *always* guaranteed to happen. +// Even if there's a bailout. +Harness.prototype.tearDown = function (fn) { + this.on("end", fn) +} diff --git a/node_modules/tap/lib/tap-producer.js b/node_modules/tap/lib/tap-producer.js new file mode 100644 index 0000000..c6593a9 --- /dev/null +++ b/node_modules/tap/lib/tap-producer.js @@ -0,0 +1,130 @@ +module.exports = TapProducer + +var Results = require("./tap-results") + , inherits = require("inherits") + , yamlish = require("yamlish") + +TapProducer.encode = function (result, diag) { + var tp = new TapProducer(diag) + , out = "" + tp.on("data", function (c) { out += c }) + if (Array.isArray(result)) { + result.forEach(tp.write, tp) + } else tp.write(result) + tp.end() + return out +} + +inherits(TapProducer, require("stream").Stream) +function TapProducer (diag) { + TapProducer.super.call(this) + this.diag = diag + this.count = 0 + this.readable = this.writable = true + this.results = new Results +} + +TapProducer.prototype.trailer = true + +TapProducer.prototype.write = function (res) { + // console.error("TapProducer.write", res) + if (typeof res === "function") throw new Error("wtf?") + if (!this.writable) this.emit("error", new Error("not writable")) + + if (!this._didHead) { + this.emit("data", "TAP version 13\n") + this._didHead = true + } + + var diag = res.diag + if (diag === undefined) diag = this.diag + + this.emit("data", encodeResult(res, this.count + 1, diag)) + + if (typeof res === "string") return true + + if (res.bailout) { + var bo = "bail out!" + if (typeof res.bailout === "string") bo += " " + res.bailout + this.emit("data", bo) + return + } + this.results.add(res, false) + + this.count ++ +} + +TapProducer.prototype.end = function (res) { + if (res) this.write(res) + // console.error("TapProducer end", res, this.results) + this.emit("data", "\n1.."+this.results.testsTotal+"\n") + if (this.trailer && typeof this.trailer !== "string") { + // summary trailer. + var trailer = "tests "+this.results.testsTotal + "\n" + if (this.results.pass) { + trailer += "pass " + this.results.pass + "\n" + } + if (this.results.fail) { + trailer += "fail " + this.results.fail + "\n" + } + if (this.results.skip) { + trailer += "skip "+this.results.skip + "\n" + } + if (this.results.todo) { + trailer += "todo "+this.results.todo + "\n" + } + if (this.results.bailedOut) { + trailer += "bailed out" + "\n" + } + + if (this.results.testsTotal === this.results.pass) { + trailer += "\nok\n" + } + this.trailer = trailer + } + if (this.trailer) this.write(this.trailer) + this.writable = false + this.emit("end", null, this.count, this.ok) +} + +function encodeResult (res, count, diag) { + // console.error(res, count, diag) + if (typeof res === "string") { + res = res.split(/\r?\n/).map(function (l) { + if (!l.trim()) return l.trim() + return "# " + l + }).join("\n") + if (res.substr(-1) !== "\n") res += "\n" + return res + } + + if (res.bailout) return "" + + + if (!!process.env.TAP_NODIAG) diag = false + else if (!!process.env.TAP_DIAG) diag = true + else if (diag === undefined) diag = !res.ok + + var output = "" + res.name = res.name && ("" + res.name).trim() + output += ( !res.ok ? "not " : "") + "ok " + count + + ( !res.name ? "" + : " " + res.name.replace(/[\r\n]/g, " ") ) + + ( res.skip ? " # SKIP" + : res.todo ? " # TODO" + : "" ) + + "\n" + + if (!diag) return output + var d = {} + , dc = 0 + Object.keys(res).filter(function (k) { + return k !== "ok" && k !== "name" && k !== "id" + }).forEach(function (k) { + dc ++ + d[k] = res[k] + }) + //console.error(d, "about to encode") + if (dc > 0) output += " ---"+yamlish.encode(d)+"\n ...\n" + return output +} diff --git a/node_modules/tap/lib/tap-results.js b/node_modules/tap/lib/tap-results.js new file mode 100644 index 0000000..6fe90e8 --- /dev/null +++ b/node_modules/tap/lib/tap-results.js @@ -0,0 +1,71 @@ +// A class for counting up results in a test harness. + +module.exports = Results + +var inherits = require("inherits") + , EventEmitter = require("events").EventEmitter + +inherits(Results, EventEmitter) + +function Results (r) { + //console.error("result constructor", r) + this.ok = true + this.addSet(r) +} + +Results.prototype.addSet = function (r) { + //console.error("add set of results", r) + r = r || {ok: true} + ; [ "todo" + , "todoPass" + , "todoFail" + , "skip" + , "skipPass" + , "skipFail" + , "pass" + , "passTotal" + , "fail" + , "failTotal" + , "tests" + , "testsTotal" ].forEach(function (k) { + this[k] = (this[k] || 0) + (r[k] || 0) + //console.error([k, this[k]]) + }, this) + + this.ok = this.ok && r.ok && true + this.bailedOut = this.bailedOut || r.bailedOut || false + this.list = (this.list || []).concat(r.list || []) + this.emit("set", this.list) + //console.error("after addSet", this) +} + +Results.prototype.add = function (r, addToList) { + //console.error("add result", r) + var pf = r.ok ? "pass" : "fail" + , PF = r.ok ? "Pass" : "Fail" + + this.testsTotal ++ + this[pf + "Total"] ++ + + if (r.skip) { + this["skip" + PF] ++ + this.skip ++ + } else if (r.todo) { + this["todo" + PF] ++ + this.todo ++ + } else { + this.tests ++ + this[pf] ++ + } + + if (r.bailout || typeof r.bailout === "string") { + // console.error("Bailing out in result") + this.bailedOut = true + } + this.ok = !!(this.ok && r.ok) + + if (addToList === false) return + this.list = this.list || [] + this.list.push(r) + this.emit("result", r) +} diff --git a/node_modules/tap/lib/tap-runner.js b/node_modules/tap/lib/tap-runner.js new file mode 100644 index 0000000..4f3f117 --- /dev/null +++ b/node_modules/tap/lib/tap-runner.js @@ -0,0 +1,434 @@ +var fs = require("fs") + , child_process = require("child_process") + , path = require("path") + , chain = require("slide").chain + , asyncMap = require("slide").asyncMap + , TapProducer = require("./tap-producer.js") + , TapConsumer = require("./tap-consumer.js") + , assert = require("./tap-assert.js") + , inherits = require("inherits") + , util = require("util") + , CovHtml = require("./tap-cov-html.js") + + // XXX Clean up the coverage options + , doCoverage = process.env.TAP_COV + || process.env.npm_package_config_coverage + || process.env.npm_config_coverage + +module.exports = Runner + +inherits(Runner, TapProducer) + +function Runner (options, cb) { + this.options = options + + var diag = this.options.diag + var dir = this.options.argv.remain + Runner.super.call(this, diag) + + this.doCoverage = doCoverage + // An array of full paths to files to obtain coverage + this.coverageFiles = [] + // The source of these files + this.coverageFilesSource = {} + // Where to write coverage information + this.coverageOutDir = this.options["coverage-dir"] + // Temporary test files bunkerified we'll remove later + this.f2delete = [] + // Raw coverage stats, as read from JSON files + this.rawCovStats = [] + // Processed coverage information, per file to cover: + this.covStats = {} + + if (dir) { + var filesToCover = this.options.cover + + if (doCoverage) { + var mkdirp = require("mkdirp") + this.coverageOutDir = path.resolve(this.coverageOutDir) + this.getFilesToCover(filesToCover) + var self = this + return mkdirp(this.coverageOutDir, 0755, function (er) { + if (er) return self.emit("error", er) + self.run(dir, cb) + }) + } + + this.run(dir, cb) + } +} + + +Runner.prototype.run = function() { + var self = this + , args = Array.prototype.slice.call(arguments) + , cb = args.pop() || finish + + function finish (er) { + if (er) { + self.emit("error", er) + } + + if (!doCoverage) return self.end() + + // Cleanup temporary test files with coverage: + self.f2delete.forEach(function(f) { + fs.unlinkSync(f) + }) + self.getFilesToCoverSource(function(err, data) { + if (err) { + self.emit("error", err) + } + self.getPerFileCovInfo(function(err, data) { + if (err) { + self.emit("error", err) + } + self.mergeCovStats(function(err, data) { + if (err) { + self.emit("error", err) + } + CovHtml(self.covStats, self.coverageOutDir, function() { + self.end() + }) + }) + }) + }) + } + + if (Array.isArray(args[0])) { + args = args[0] + } + self.runFiles(args, "", cb) +} + +Runner.prototype.runDir = function (dir, cb) { + var self = this + fs.readdir(dir, function (er, files) { + if (er) { + self.write(assert.fail("failed to readdir " + dir, { error: er })) + self.end() + return + } + files = files.sort(function(a, b) { + return a > b ? 1 : -1 + }) + files = files.filter(function(f) { + return !f.match(/^\./) + }) + files = files.map(path.resolve.bind(path, dir)) + + self.runFiles(files, path.resolve(dir), cb) + }) +} + + +Runner.prototype.runFiles = function (files, dir, cb) { + + var self = this + chain(files.map(function(f) { + return function (cb) { + if (self._bailedOut) return + var relDir = dir || path.dirname(f) + , fileName = relDir === "." ? f : f.substr(relDir.length + 1) + + self.write(fileName) + fs.lstat(f, function(er, st) { + if (er) { + self.write(assert.fail("failed to stat " + f, {error: er})) + return cb() + } + + var cmd = f, args = [], env = {} + + if (path.extname(f) === ".js") { + cmd = "node" + args = [fileName] + } else if (path.extname(f) === ".coffee") { + cmd = "coffee" + args = [fileName] + } + + if (st.isDirectory()) { + return self.runDir(f, cb) + } + + if (doCoverage && path.extname(f) === ".js") { + var foriginal = fs.readFileSync(f, "utf8") + , fcontents = self.coverHeader() + foriginal + self.coverFooter() + , tmpBaseName = path.basename(f, path.extname(f)) + + ".with-coverage." + process.pid + path.extname(f) + , tmpFname = path.resolve(path.dirname(f), tmpBaseName) + , i + + fs.writeFileSync(tmpFname, fcontents, "utf8") + args = [tmpFname] + } + + for (i in process.env) { + env[i] = process.env[i] + } + env.TAP = 1 + + var cp = child_process.spawn(cmd, args, { env: env, cwd: relDir }) + , out = "" + , err = "" + , tc = new TapConsumer() + , childTests = [f] + + var timeout = setTimeout(function () { + if (!cp._ended) { + cp._timedOut = true + cp.kill() + } + }, self.options.timeout * 1000) + + tc.on("data", function(c) { + self.emit("result", c) + self.write(c) + }) + + tc.on("bailout", function (message) { + clearTimeout(timeout) + console.log("# " + f.substr(process.cwd().length + 1)) + process.stderr.write(err) + process.stdout.write(out + "\n") + self._bailedOut = true + cp._ended = true + cp.kill() + }) + + cp.stdout.pipe(tc) + cp.stdout.on("data", function (c) { out += c }) + cp.stderr.on("data", function (c) { + if (self.options.stderr) process.stderr.write(c) + err += c + }) + + cp.on("exit", function (code) { + if (cp._ended) return + cp._ended = true + var ok = !cp._timedOut && !code + clearTimeout(timeout) + //childTests.forEach(function (c) { self.write(c) }) + var res = { name: path.dirname(f).replace(process.cwd() + "/", "") + + "/" + fileName + , ok: ok + , timedOut: cp._timedOut + , exit: code } + + if (err) { + res.stderr = err + if (tc.results.ok && + tc.results.tests === 0 && + !self.options.stderr) { + // perhaps a compilation error or something else failed. + // no need if stderr is set, since it will have been + // output already anyway. + console.error(err) + } + } + + // tc.results.ok = tc.results.ok && ok + tc.results.add(res) + res.command = [cmd].concat(args).map(JSON.stringify).join(" ") + self.emit("result", res) + self.emit("file", f, res, tc.results) + self.write(res) + self.write("\n") + if (doCoverage) { + self.f2delete.push(tmpFname) + } + cb() + }) + }) + } + }), cb) + + return self +} + + +// Get an array of full paths to files we are interested into obtain +// code coverage. +Runner.prototype.getFilesToCover = function(filesToCover) { + var self = this + filesToCover = filesToCover.split(",").map(function(f) { + return path.resolve(f) + }).filter(function(f) { + return path.existsSync(f) + }) + + function recursive(f) { + if (path.extname(f) === "") { + // Is a directory: + fs.readdirSync(f).forEach(function(p) { + recursive(f + "/" + p) + }) + } else { + self.coverageFiles.push(f) + } + } + filesToCover.forEach(function(f) { + recursive(f) + }) +} + +// Prepend to every test file to run. Note tap.test at the very top due it +// "plays" with include paths. +Runner.prototype.coverHeader = function() { + // semi here since we're injecting it before the first line, + // and don't want to mess up line numbers in the test files. + return "var ___TAP_COVERAGE = require(" + + JSON.stringify(require.resolve("runforcover")) + + ").cover(/.*/g);" +} + +// Append at the end of every test file to run. Actually, the stuff which gets +// the coverage information. +// Maybe it would be better to move into a separate file template so editing +// could be easier. +Runner.prototype.coverFooter = function() { + var self = this + // This needs to be a string with proper interpolations: + return [ "" + , "var ___TAP = require(" + JSON.stringify(require.resolve("./main.js")) + ")" + , "if (typeof ___TAP._plan === 'number') ___TAP._plan ++" + , "___TAP.test(" + JSON.stringify("___coverage") + ", function(t) {" + , " var covFiles = " + JSON.stringify(self.coverageFiles) + , " , covDir = " + JSON.stringify(self.coverageOutDir) + , " , path = require('path')" + , " , fs = require('fs')" + , " , testFnBase = path.basename(__filename, '.js') + '.json'" + , " , testFn = path.resolve(covDir, testFnBase)" + , "" + , " function asyncForEach(arr, fn, callback) {" + , " if (!arr.length) {" + , " return callback()" + , " }" + , " var completed = 0" + , " arr.forEach(function(i) {" + , " fn(i, function (err) {" + , " if (err) {" + , " callback(err)" + , " callback = function () {}" + , " } else {" + , " completed += 1" + , " if (completed === arr.length) {" + , " callback()" + , " }" + , " }" + , " })" + , " })" + , " }" + , "" + , " ___TAP_COVERAGE(function(coverageData) {" + , " var outObj = {}" + , " asyncForEach(covFiles, function(f, cb) {" + , " if (coverageData[f]) {" + , " var stats = coverageData[f].stats()" + , " , stObj = stats" + , " stObj.lines = stats.lines.map(function (l) {" + , " return { number: l.lineno, source: l.source() }" + , " })" + , " outObj[f] = stObj" + , " }" + , " cb()" + , " }, function(err) {" + , " ___TAP_COVERAGE.release()" + , " fs.writeFileSync(testFn, JSON.stringify(outObj))" + , " t.end()" + , " })" + , " })" + , "})" ].join("\n") +} + + +Runner.prototype.getFilesToCoverSource = function(cb) { + var self = this + asyncMap(self.coverageFiles, function(f, cb) { + fs.readFile(f, "utf8", function(err, data) { + var lc = 0 + if (err) { + cb(err) + } + self.coverageFilesSource[f] = data.split("\n").map(function(l) { + lc += 1 + return { number: lc, source: l } + }) + cb() + }) + }, cb) +} + +Runner.prototype.getPerFileCovInfo = function(cb) { + var self = this + , covPath = path.resolve(self.coverageOutDir) + + fs.readdir(covPath, function(err, files) { + if (err) { + self.emit("error", err) + } + var covFiles = files.filter(function(f) { + return path.extname(f) === ".json" + }) + asyncMap(covFiles, function(f, cb) { + fs.readFile(path.resolve(covPath, f), "utf8", function(err, data) { + if (err) { + cb(err) + } + self.rawCovStats.push(JSON.parse(data)) + cb() + }) + }, function(f, cb) { + fs.unlink(path.resolve(covPath, f), cb) + }, cb) + }) +} + +Runner.prototype.mergeCovStats = function(cb) { + var self = this + self.rawCovStats.forEach(function(st) { + Object.keys(st).forEach(function(i) { + // If this is the first time we reach this file, just add the info: + if (!self.covStats[i]) { + self.covStats[i] = { + missing: st[i].lines + } + } else { + // If we already added info for this file before, we need to remove + // from self.covStats any line not duplicated again (since it has + // run on such case) + self.covStats[i].missing = self.covStats[i].missing.filter( + function(l) { + return (st[i].lines.indexOf(l)) + }) + } + }) + }) + + // This is due to a bug into + // chrisdickinson/node-bunker/blob/feature/add-coverage-interface + // which is using array indexes for line numbers instead of the right number + Object.keys(self.covStats).forEach(function(f) { + self.covStats[f].missing = self.covStats[f].missing.map(function(line) { + return { number: line.number, source: line.source } + }) + }) + + Object.keys(self.coverageFilesSource).forEach(function(f) { + if (!self.covStats[f]) { + self.covStats[f] = { missing: self.coverageFilesSource[f] + , percentage: 0 + } + } + self.covStats[f].lines = self.coverageFilesSource[f] + self.covStats[f].loc = self.coverageFilesSource[f].length + + if (!self.covStats[f].percentage) { + self.covStats[f].percentage = + 1 - (self.covStats[f].missing.length / self.covStats[f].loc) + } + + }) + cb() +} diff --git a/node_modules/tap/lib/tap-test.js b/node_modules/tap/lib/tap-test.js new file mode 100644 index 0000000..3c8f138 --- /dev/null +++ b/node_modules/tap/lib/tap-test.js @@ -0,0 +1,109 @@ +// This is a very simple test framework that leverages the tap framework +// to run tests and output tap-parseable results. + +module.exports = Test + +var assert = require("./tap-assert") + , inherits = require("inherits") + , Results = require("./tap-results") + +// tests are also test harnesses +inherits(Test, require("./tap-harness")) + +function Test (harness, name, conf) { + //console.error("test ctor") + if (!(this instanceof Test)) return new Test(harness, name, conf) + + Test.super.call(this, Test) + + conf.name = name || conf.name || "(anonymous)" + this.conf = conf + + this.harness = harness + this.harness.add(this) +} + +// it's taking too long! +Test.prototype.timeout = function () { + // detect false alarms + if (this._ended) return + this.fail("Timeout!") + this.end() +} + +Test.prototype.clear = function () { + this._started = false + this._ended = false + this._plan = null + this._bailedOut = false + this._testCount = 0 + this.results = new Results() +} + +// this gets called if a test throws ever +Test.prototype.threw = function (ex) { + //console.error("threw!", ex.stack) + this.fail(ex.name + ": " + ex.message, { error: ex, thrown: true }) + // may emit further failing tests if the plan is not completed + //console.error("end, because it threw") + this.end() +} + +Test.prototype.comment = function (m) { + if (typeof m !== "string") { + return this.fail("Test.comment argument must be a string") + } + this.result("\n" + m.trim()) +} + +Test.prototype.result = function (res) { + this.results.add(res) + this._testCount ++ + this.emit("result", res) + if (this._plan === this._testCount) { + process.nextTick(this._endNice.bind(this)) + } +} + +Test.prototype._endNice = function () { + if (!this._ended) this.end() +} + +// parasitic +// Who says you can't do multiple inheritance in js? +Object.getOwnPropertyNames(assert).forEach(function (k) { + if (k === "prototype" || k === "name") return + var d = Object.getOwnPropertyDescriptor(assert, k) + , v = d.value + if (!v) return + d.value = assertParasite(v) + Object.defineProperty(Test.prototype, k, d) +}) + +function assertParasite (fn) { return function _testAssert () { + //console.error("_testAssert", fn.name, arguments) + if (this._bailedOut) return + var res = fn.apply(assert, arguments) + this.result(res) + return res +}} + +// a few tweaks on the EE emit function, because +// we want to catch all thrown errors and bubble up "bailout" +Test.prototype.emit = (function (em) { return function (t) { + // bailouts bubble until handled + if (t === "bailout" && + this.listeners(t).length === 0 && + this.harness) { + return this.harness.bailout(arguments[1]) + } + + if (t === "error") return em.apply(this, arguments) + try { + em.apply(this, arguments) + } catch (ex) { + // any exceptions in a test are a failure + //console.error("caught!", ex.stack) + this.threw(ex) + } +}})(Test.super.prototype.emit) diff --git a/node_modules/tap/node_modules/inherits/LICENSE b/node_modules/tap/node_modules/inherits/LICENSE new file mode 100644 index 0000000..5a8e332 --- /dev/null +++ b/node_modules/tap/node_modules/inherits/LICENSE @@ -0,0 +1,14 @@ + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + Version 2, December 2004 + + Copyright (C) 2004 Sam Hocevar + + Everyone is permitted to copy and distribute verbatim or modified + copies of this license document, and changing it is allowed as long + as the name is changed. + + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. You just DO WHAT THE FUCK YOU WANT TO. + diff --git a/node_modules/tap/node_modules/inherits/README.md b/node_modules/tap/node_modules/inherits/README.md new file mode 100644 index 0000000..b2beaed --- /dev/null +++ b/node_modules/tap/node_modules/inherits/README.md @@ -0,0 +1,51 @@ +A dead simple way to do inheritance in JS. + + var inherits = require("inherits") + + function Animal () { + this.alive = true + } + Animal.prototype.say = function (what) { + console.log(what) + } + + inherits(Dog, Animal) + function Dog () { + Dog.super.apply(this) + } + Dog.prototype.sniff = function () { + this.say("sniff sniff") + } + Dog.prototype.bark = function () { + this.say("woof woof") + } + + inherits(Chihuahua, Dog) + function Chihuahua () { + Chihuahua.super.apply(this) + } + Chihuahua.prototype.bark = function () { + this.say("yip yip") + } + + // also works + function Cat () { + Cat.super.apply(this) + } + Cat.prototype.hiss = function () { + this.say("CHSKKSS!!") + } + inherits(Cat, Animal, { + meow: function () { this.say("miao miao") } + }) + Cat.prototype.purr = function () { + this.say("purr purr") + } + + + var c = new Chihuahua + assert(c instanceof Chihuahua) + assert(c instanceof Dog) + assert(c instanceof Animal) + +The actual function is laughably small. 10-lines small. diff --git a/node_modules/tap/node_modules/inherits/inherits-old.js b/node_modules/tap/node_modules/inherits/inherits-old.js new file mode 100644 index 0000000..ef39252 --- /dev/null +++ b/node_modules/tap/node_modules/inherits/inherits-old.js @@ -0,0 +1,40 @@ +// This is a less perfect implementation of the inherits function, +// designed to work in cases where ES5 is not available. +// +// Note that it is a bit longer, and doesn't properly deal with +// getter/setters or property descriptor flags (enumerable, etc.) + +module.exports = inheritsOld + +function inheritsOld (c, p, proto) { + function F () { this.constructor = c } + F.prototype = p.prototype + var e = {} + for (var i in c.prototype) if (c.prototype.hasOwnProperty(i)) { + e[i] = c.prototype[i] + } + if (proto) for (var i in proto) if (proto.hasOwnProperty(i)) { + e[i] = proto[i] + } + c.prototype = new F() + for (var i in e) if (e.hasOwnProperty(i)) { + c.prototype[i] = e[i] + } + c.super = p +} + +// function Child () { +// Child.super.call(this) +// console.error([this +// ,this.constructor +// ,this.constructor === Child +// ,this.constructor.super === Parent +// ,Object.getPrototypeOf(this) === Child.prototype +// ,Object.getPrototypeOf(Object.getPrototypeOf(this)) +// === Parent.prototype +// ,this instanceof Child +// ,this instanceof Parent]) +// } +// function Parent () {} +// inheritsOld(Child, Parent) +// new Child diff --git a/node_modules/tap/node_modules/inherits/inherits.js b/node_modules/tap/node_modules/inherits/inherits.js new file mode 100644 index 0000000..061b396 --- /dev/null +++ b/node_modules/tap/node_modules/inherits/inherits.js @@ -0,0 +1,29 @@ +module.exports = inherits + +function inherits (c, p, proto) { + proto = proto || {} + var e = {} + ;[c.prototype, proto].forEach(function (s) { + Object.getOwnPropertyNames(s).forEach(function (k) { + e[k] = Object.getOwnPropertyDescriptor(s, k) + }) + }) + c.prototype = Object.create(p.prototype, e) + c.super = p +} + +//function Child () { +// Child.super.call(this) +// console.error([this +// ,this.constructor +// ,this.constructor === Child +// ,this.constructor.super === Parent +// ,Object.getPrototypeOf(this) === Child.prototype +// ,Object.getPrototypeOf(Object.getPrototypeOf(this)) +// === Parent.prototype +// ,this instanceof Child +// ,this instanceof Parent]) +//} +//function Parent () {} +//inherits(Child, Parent) +//new Child diff --git a/node_modules/tap/node_modules/inherits/package.json b/node_modules/tap/node_modules/inherits/package.json new file mode 100644 index 0000000..487b6fa --- /dev/null +++ b/node_modules/tap/node_modules/inherits/package.json @@ -0,0 +1,8 @@ +{ "name" : "inherits" +, "description": "A tiny simple way to do classic inheritance in js" +, "version" : "1.0.0" +, "keywords" : ["inheritance", "class", "klass", "oop", "object-oriented"] +, "main" : "./inherits.js" +, "repository" : "https://github.com/isaacs/inherits" +, "license": { "type": "WTFPL2" } +, "author" : "Isaac Z. Schlueter (http://blog.izs.me/)" } diff --git a/node_modules/tap/node_modules/yamlish/LICENSE b/node_modules/tap/node_modules/yamlish/LICENSE new file mode 100644 index 0000000..187e8db --- /dev/null +++ b/node_modules/tap/node_modules/yamlish/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2011 Isaac Z. Schlueter + +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/tap/node_modules/yamlish/README.md b/node_modules/tap/node_modules/yamlish/README.md new file mode 100644 index 0000000..954d063 --- /dev/null +++ b/node_modules/tap/node_modules/yamlish/README.md @@ -0,0 +1,20 @@ +This is a thingie to parse the "yamlish" format used to serialize +objects in the TAP format. + +It's like yaml, but just a tiny little bit smaller. + +Usage: + + var yamlish = require("yamlish") + // returns a string like: + /* + some: + object: + - full + - of + pretty: things + */ + yamlish.encode({some:{object:["full", "of"]}, pretty:"things"}) + + // returns the object + yamlish.decode(someYamlishString) diff --git a/node_modules/tap/node_modules/yamlish/package.json b/node_modules/tap/node_modules/yamlish/package.json new file mode 100644 index 0000000..359300d --- /dev/null +++ b/node_modules/tap/node_modules/yamlish/package.json @@ -0,0 +1,9 @@ +{ "name" : "yamlish" +, "description" : "Parser/encoder for the yamlish format" +, "repository":"https://github.com/isaacs/yamlish" +, "version" : "0.0.5" +, "main" : "yamlish.js" +, "keywords" : [ "yaml", "yamlish", "test", "anything", "protocol", "tap"] +, "license" : { "type" : "MIT" + , "url" : "http://github.com/isaacs/yamlish/raw/master/LICENSE" } +, "author" : "Isaac Z. Schlueter (http://blog.izs.me/)" } diff --git a/node_modules/tap/node_modules/yamlish/yamlish.js b/node_modules/tap/node_modules/yamlish/yamlish.js new file mode 100644 index 0000000..dd8c370 --- /dev/null +++ b/node_modules/tap/node_modules/yamlish/yamlish.js @@ -0,0 +1,260 @@ +exports.encode = encode +exports.decode = decode + +var seen = [] +function encode (obj, indent) { + var deep = arguments[2] + if (!indent) indent = " " + + if (obj instanceof String || + Object.prototype.toString.call(obj) === "[object String]") { + obj = obj.toString() + } + + if (obj instanceof Number || + Object.prototype.toString.call(obj) === "[object Number]") { + obj = obj.valueOf() + } + + // take out the easy ones. + switch (typeof obj) { + case "string": + obj = obj.trim() + if (obj.indexOf("\n") !== -1) { + return "|\n" + indent + obj.split(/\r?\n/).join("\n"+indent) + } else { + return (obj) + } + + case "number": + return obj.toString(10) + + case "function": + return encode(obj.toString(), indent, true) + + case "boolean": + return obj.toString() + + case "undefined": + // fallthrough + case "object": + // at this point we know it types as an object + if (!obj) return "~" + + if (obj instanceof Date || + Object.prototype.toString.call(obj) === "[object Date]") { + return JSON.stringify("[Date " + obj.toISOString() + "]") + } + + if (obj instanceof RegExp || + Object.prototype.toString.call(obj) === "[object RegExp]") { + return JSON.stringify(obj.toString()) + } + + if (obj instanceof Boolean || + Object.prototype.toString.call(obj) === "[object Boolean]") { + return obj.toString() + } + + if (seen.indexOf(obj) !== -1) { + return "[Circular]" + } + seen.push(obj) + + if (typeof Buffer === "function" && + typeof Buffer.isBuffer === "function" && + Buffer.isBuffer(obj)) return obj.inspect() + + if (obj instanceof Error) { + var o = { name: obj.name + , message: obj.message + , type: obj.type } + + if (obj.code) o.code = obj.code + if (obj.errno) o.errno = obj.errno + if (obj.type) o.type = obj.type + obj = o + } + + var out = "" + + if (Array.isArray(obj)) { + var out = "\n" + indent + "- " +obj.map(function (item) { + return encode(item, indent + " ", true) + }).join("\n"+indent + "- ") + break + } + + // an actual object + var keys = Object.keys(obj) + , niceKeys = keys.map(function (k) { + return (k.match(/^[a-zA-Z0-9_]+$/) ? k : JSON.stringify(k)) + ": " + }) + //console.error(keys, niceKeys, obj) + var maxLength = Math.max.apply(Math, niceKeys.map(function (k) { + return k.length + }).concat(0)) + //console.error(niceKeys, maxLength) + + var spaces = new Array(maxLength + 1).join(" ") + + if (!deep) indent += " " + out = "\n" + indent + keys.map(function (k, i) { + var niceKey = niceKeys[i] + return niceKey + spaces.substr(niceKey.length) + + encode(obj[k], indent + " ", true) + }).join("\n" + indent) + break + + default: return "" + } + if (!deep) seen.length = 0 + return out +} + +function decode (str) { + var v = str.trim() + , d + , dateRe = /^\[Date ([0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}(?::[0-9]{2})?(?:\.[0-9]{3})?(?:[A-Z]+)?)\]$/ + + if (v === "~") return null + + try { + var jp = JSON.parse(str) + } catch (e) { + var jp = "" + } + + if (jp && + typeof jp === "string" && + (d = jp.match(dateRe)) && + (d = Date.parse(d[1]))) { + return new Date(d) + } + + if (typeof jp === "boolean") return jp + if (v && !isNaN(v)) return parseInt(v, 10) + + // something interesting. + var lines = str.split(/\r?\n/) + // check if it's some kind of string or something. + // if the first line is > or | then it's a wrapping indented string. + // if the first line is blank, and there are many lines, + // then it's an array or object. + // otherwise, it's just "" + var first = lines.shift().trim() + if (lines.length) lines = undent(lines) + switch (first) { + case "|": + return lines.join("\n") + case ">": + return lines.join("\n").split(/\n{2,}/).map(function (l) { + return l.split(/\n/).join(" ") + }).join("\n") + default: + if (!lines.length) return first + // array or object. + // the first line will be either "- value" or "key: value" + return lines[0].charAt(0) === "-" ? decodeArr(lines) : decodeObj(lines) + } +} + +function decodeArr (lines) { + var out = [] + , key = 0 + , val = [] + for (var i = 0, l = lines.length; i < l; i ++) { + // if it starts with a -, then it's a new thing + var line = lines[i] + if (line.charAt(0) === "-") { + if (val.length) { + out[key ++] = decode(val.join("\n")) + val.length = 0 + } + val.push(line.substr(1).trim()) + } else if (line.charAt(0) === " ") { + val.push(line) + } else return [] + } + if (val.length) { + out[key ++] = decode(val.join("\n")) + } + return out +} + +function decodeObj (lines) { + var out = {} + , val = [] + , key = null + + for (var i = 0, l = lines.length; i < l; i ++) { + var line = lines[i] + if (line.charAt(0) === " ") { + val.push(line) + continue + } + // some key:val + if (val.length) { + out[key] = decode(val.join("\n")) + val.length = 0 + } + // parse out the quoted key + var first + if (line.charAt(0) === "\"") { + for (var ii = 1, ll = line.length, esc = false; ii < ll; ii ++) { + var c = line.charAt(ii) + if (c === "\\") { + esc = !esc + } else if (c === "\"" && !esc) { + break + } + } + key = JSON.parse(line.substr(0, ii + 1)) + line = line.substr(ii + 1) + first = line.substr(line.indexOf(":") + 1).trim() + } else { + var kv = line.split(":") + key = kv.shift() + first = kv.join(":").trim() + } + // now we've set a key, and "first" has the first line of the value. + val.push(first.trim()) + } + if (val.length) out[key] = decode(val.join("\n")) + return out +} + +function undent (lines) { + var i = lines[0].match(/^\s*/)[0].length + return lines.map(function (line) { + return line.substr(i) + }) +} + + +// XXX Turn this into proper tests. +if (require.main === module) { +var obj = [{"bigstring":new Error().stack} + ,{ar:[{list:"of"},{some:"objects"}]} + ,{date:new Date()} + ,{"super huge string":new Error().stack} + ] + +Date.prototype.toJSON = function (k, val) { + console.error(k, val, this) + return this.toISOString() + " (it's a date)" +} + +var enc = encode(obj) + , dec = decode(enc) + , encDec = encode(dec) + +console.error(JSON.stringify({ obj : obj + , enc : enc.split(/\n/) + , dec : dec }, null, 2), encDec === enc) + +var num = 100 + , encNum = encode(num) + , decEncNum = decode(encNum) +console.error([num, encNum, decEncNum]) +} diff --git a/node_modules/tap/package.json b/node_modules/tap/package.json new file mode 100644 index 0000000..a8a3357 --- /dev/null +++ b/node_modules/tap/package.json @@ -0,0 +1,41 @@ +{ + "name": "tap", + "version": "0.2.6", + "author": "Isaac Z. Schlueter (http://blog.izs.me)", + "description": "A Test-Anything-Protocol library", + "bin": "bin/tap.js", + "main": "lib/main.js", + "dependencies": { + "inherits": "*", + "yamlish": "*", + "slide": "*", + "runforcover": "~0.0.2", + "nopt": "~2", + "mkdirp": "~0.3", + "difflet": "~0.2.0", + "deep-equal": "~0.0.0", + "buffer-equal": "~0.0.0" + }, + "bundledDependencies": [ + "inherits", + "tap-consumer", + "yamlish" + ], + "keywords": [ + "assert", + "test", + "tap" + ], + "contributors": [ + "Isaac Z. Schlueter (http://blog.izs.me)", + "baudehlo " + ], + "license": { + "type": "MIT", + "url": "https://github.com/isaacs/node-tap/raw/master/LICENSE" + }, + "repository": "git://github.com/isaacs/node-tap.git", + "scripts": { + "test": "bin/tap.js test" + } +} diff --git a/node_modules/tap/test-disabled/bailout.js b/node_modules/tap/test-disabled/bailout.js new file mode 100644 index 0000000..498035c --- /dev/null +++ b/node_modules/tap/test-disabled/bailout.js @@ -0,0 +1,36 @@ +var tap = require("tap") + , test = tap.test + +test("bailout test", { skip: false }, function (t) { + + // t.once("bailout", function () { + // console.error("bailout event")//, t) + // t.clear() + // }) + + // t.once("end", function () { + // console.error("end event") + // }) + + // simulate three tests where the second bails out. + t.test("first", function (t) { + t.pass("this is ok") + t.end() + }) + + t.test("bailout", function (t) { + console.error("bailout test") + t.pass("pass") + t.bailout("bail out message") + t.fail("fail") + t.end() + }) + + t.test("second (should not happen)", function (t) { + t.fail("this should not happen") + t.end() + }) + + t.end() + +}) diff --git a/node_modules/tap/test-disabled/foo.js b/node_modules/tap/test-disabled/foo.js new file mode 100644 index 0000000..6360156 --- /dev/null +++ b/node_modules/tap/test-disabled/foo.js @@ -0,0 +1 @@ +process.stdin diff --git a/node_modules/tap/test-disabled/t.js b/node_modules/tap/test-disabled/t.js new file mode 100644 index 0000000..581d24b --- /dev/null +++ b/node_modules/tap/test-disabled/t.js @@ -0,0 +1,16 @@ +var test = require('tap').test; + +function foo() { + throw new Error('one'); +} + +test('demonstrate bug in t.throws', function (t) { + t.throws( + function () { + foo(); + }, + new Error('two')), + // "this should throw", + // {}); // not 'one'! + t.end(); +}); diff --git a/node_modules/tap/test/buffer_compare.js b/node_modules/tap/test/buffer_compare.js new file mode 100644 index 0000000..b1e1505 --- /dev/null +++ b/node_modules/tap/test/buffer_compare.js @@ -0,0 +1,11 @@ +var test = require("../").test + +test("same buffers", function (t) { + t.same(new Buffer([3,4,243]), new Buffer([3,4,243])) + t.end() +}) + +test("not same buffers", function (t) { + t.notSame(new Buffer([3,5,243]), new Buffer([3,4,243])) + t.end() +}) diff --git a/node_modules/tap/test/common.js b/node_modules/tap/test/common.js new file mode 100644 index 0000000..7cc43c1 --- /dev/null +++ b/node_modules/tap/test/common.js @@ -0,0 +1,32 @@ +exports.taps = ["Tests for the foo module" + ,{ok:true, name:"test that the foo is fooish" + ,file:"foo.js", line:8, name:"fooish test" + ,stack:new Error("fooish").stack} + ,{ok:false, name:"a test that the bar is barish" + ,file:"bar.js", line:25 + ,expected:"bar\nbar\nbaz", actual:"rab\nrib\nzib" + ,hash:{more:"\nstuff\nhere\n",regexp:/asdf/}} + ,"Quux module tests" + ,"This is a longer comment" + ,{ok:true, name:"an easy one."} + ,{ok:false, name:"bloooooo" + ,expected:"blerggeyyy" + ,actual:"blorggeyy"} + ,{ok:false, name:"array test" + ,expected:[{ok:true},{ok:true},{stack:new Error().stack}] + ,actual:[1234567890,123456789,{error:new Error("yikes")}]} + ,{ok:true, name:"nulltest" + ,expected:undefined, actual:null} + ,{ok:true, name:"weird key test" + ,expected:"weird key" + ,actual:"weird key" + ,"this object":{"has a ":"weird key" + ,"and a looooooooonnnnnnnnnggg":"jacket"}} + ,{ok:true, name:"regexp test" + ,regexp:/asdf/,function:function (a,b) { return a + b }} + ] + +if (require.main === module) { + console.log("1..1") + console.log("ok 1 - just setup, nothing relevant") +} diff --git a/node_modules/tap/test/deep.js b/node_modules/tap/test/deep.js new file mode 100644 index 0000000..52b6110 --- /dev/null +++ b/node_modules/tap/test/deep.js @@ -0,0 +1,43 @@ +var tap = require("../") + , test = tap.test + +test("deepEquals shouldn't care about key order", function (t) { + t.deepEqual({ a : 1, b : 2 }, { b : 2, a : 1 }) + t.end() +}) + +test("deepEquals shouldn't care about key order recursively", function (t) { + t.deepEqual( + { x : { a : 1, b : 2 }, y : { c : 3, d : 4 } }, + { y : { d : 4, c : 3 }, x : { b : 2, a : 1 } } + ) + t.end() +}) + +test("deepEquals shoudn't care about key order but still might", function (t) { + t.deepEqual( + [ { foo: + { z: 100 + , y: 200 + , x: 300 } } + , "bar" + , 11 + , { baz: + { d : 4 + , a: 1 + , b: 2 + , c: 3 } } ] + , [ { foo : + { z: 100 + , y: 200 + , x: 300 } } + , "bar" + , 11 + , { baz: + { a: 1 + , b: 2 + , c: 3 + , d: 4 } } ] + ) + t.end() +}); diff --git a/node_modules/tap/test/independent-timeouts.js b/node_modules/tap/test/independent-timeouts.js new file mode 100644 index 0000000..5a35e61 --- /dev/null +++ b/node_modules/tap/test/independent-timeouts.js @@ -0,0 +1,16 @@ +// https://github.com/isaacs/node-tap/issues/23 + +var tap = require("../") + , test = tap.test + +test("finishes in time", {timeout: 500}, function(t) { + setTimeout(function () { + t.end(); + }, 300); +}) +test("finishes in time too", {timeout: 500}, function(t) { + setTimeout(function () { + t.end(); + }, 300); +}) + diff --git a/node_modules/tap/test/isolated-conf-test.js b/node_modules/tap/test/isolated-conf-test.js new file mode 100644 index 0000000..d8bfae6 --- /dev/null +++ b/node_modules/tap/test/isolated-conf-test.js @@ -0,0 +1,16 @@ +// https://github.com/isaacs/node-tap/issues/24 + +var tap = require("../") + , test = tap.test + +var config = {foo: "bar"} +test("one", config, function(t) { + t.equal(t.conf.foo, "bar") + t.equal(t.conf.name, "one") // before fix this would be "two" + t.end() +}) +test("two", config, function(t) { + t.equal(t.conf.foo, "bar") + t.equal(t.conf.name, "two") + t.end() +}) diff --git a/node_modules/tap/test/meta-test.js b/node_modules/tap/test/meta-test.js new file mode 100644 index 0000000..8f56f26 --- /dev/null +++ b/node_modules/tap/test/meta-test.js @@ -0,0 +1,73 @@ +var tap = require("../") + , test = tap.test + +test("meta test", { skip: false }, function (t) { + + function thr0w() { throw new Error('raburt') } + function noop () {} + + // this also tests the ok/notOk functions + t.once("end", section2) + t.ok(true, "true is ok") + t.ok(noop, "function is ok") + t.ok({}, "object is ok") + t.ok(t, "t is ok") + t.ok(100, "number is ok") + t.ok("asdf", "string is ok") + t.notOk(false, "false is notOk") + t.notOk(0, "0 is notOk") + t.notOk(null, "null is notOk") + t.notOk(undefined, "undefined is notOk") + t.notOk(NaN, "NaN is notOk") + t.notOk("", "empty string is notOk") + t.throws(thr0w, "Thrower throws"); + t.doesNotThrow(noop, "noop does not throw"); + t.similar({foo:"bar", bar:"foo"}, {foo:"bar"}, "similar objects are ok"); + t.dissimilar({}, {mandatory:"value"}, "dissimilar objects are ok"); + t.dissimilar(null, {}, "null is dissimilar from an object, even with no keys"); + + // a few failures. + t.ifError(new Error("this is an error")) + t.ifError({ message: "this is a custom error" }) + t.ok(false, "false is not ok") + t.notOk(true, "true is not not ok") + t.similar(null, {}, "Null is not similar to an object, even with no keys"); + t.throws(noop, "noop does not throw"); + t.throws(noop, new Error("Whoops!"), "noop does not throw an Error"); + t.throws(noop, {name:"MyError", message:"Whoops!"}, "noop does not throw a MyError"); + t.doesNotThrow(thr0w, "thrower does throw"); + + // things that are like other things + t.like("asdf", "asdf") + t.like("asdf", /^a.*f$/) + t.like(100, 100) + t.like(100, '100') + t.like(100, 100.0) + t.unlike("asdf", "fdsa") + t.unlike("asdf", /^you jelly, bro?/) + t.unlike(100, 100.1) + t.like(true, 1) + t.like(null, undefined) + t.like(true, [1]) + t.like(false, []) + t.like('', []) + t.end() + + function section2 () { + var results = t.results + t.clear() + t.ok(true, "sanity check") + t.notOk(results.ok, "not ok") + t.equal(results.tests, 39, "total test count") + t.equal(results.passTotal, 30, "tests passed") + t.equal(results.fail, 9, "tests failed") + t.type(results.ok, "boolean", "ok is boolean") + t.type(results.skip, "number", "skip is number") + t.type(results, "Results", "results isa Results") + t.type(t, "Test", "test isa Test") + t.type(t, "Harness", "test isa Harness") + t.end() + } +}) + + diff --git a/node_modules/tap/test/nested-test.js b/node_modules/tap/test/nested-test.js new file mode 100644 index 0000000..493f13a --- /dev/null +++ b/node_modules/tap/test/nested-test.js @@ -0,0 +1,23 @@ +var tap = require("../"), + test = tap.test, + util = require('util'); + +test("parent", function (t) { + // TODO: Make grandchildren tests count? + t.plan(3); + t.ok(true, 'p test'); + t.test("subtest", function (t) { + t.ok(true, 'ch test'); + t.test('nested subtest', function(t) { + t.ok(true, 'grch test'); + t.end(); + }); + t.end(); + }); + t.test('another subtest', function(t) { + t.ok(true, 'ch test 2'); + t.end(); + }); + t.end(); +}) + diff --git a/node_modules/tap/test/non-tap-output.js b/node_modules/tap/test/non-tap-output.js new file mode 100644 index 0000000..929e9aa --- /dev/null +++ b/node_modules/tap/test/non-tap-output.js @@ -0,0 +1,12 @@ +console.log("everything is fine\n" + +"there are no errors\n" + +"this output is not haiku.\n\n" + +"is 8 ok?\n" + +"ok, 8 can stay.\n" + +"ok 100 might be confusing\n" + +" but: nevertheless, here we are\n" + +" this: is indented\n" + +" and: it\n" + +" might: ~\n" + +" be: yaml?\n" + +"ok done now, exiting") diff --git a/node_modules/tap/test/result-trap.js b/node_modules/tap/test/result-trap.js new file mode 100644 index 0000000..1ac600f --- /dev/null +++ b/node_modules/tap/test/result-trap.js @@ -0,0 +1,25 @@ +var tap = require("../") + +tap.test("trap result #TODO", function (t0) { + + console.log("not ok 1 result event trapping #TODO") + return t0.end() + + t0.plan(3) + + var t1 = new(tap.Harness)(tap.Test).test() + + t1.plan(1) + + t1.on("result", function (res) { + if (res.wanted === 4) { + t0.equal(res.found, 3) + t0.equal(res.wanted, 4) + + t0.end() + t1.end() + } + }) + + t1.equal(1 + 2, 4) +}) diff --git a/node_modules/tap/test/simple-harness-test-with-plan.js b/node_modules/tap/test/simple-harness-test-with-plan.js new file mode 100644 index 0000000..813c4cf --- /dev/null +++ b/node_modules/tap/test/simple-harness-test-with-plan.js @@ -0,0 +1,16 @@ +var tap = require("../") + , test = tap.test + , plan = tap.plan + +plan(2) + +test("trivial success", function (t) { + t.ok(true, "it works") + t.end() +}) + +test("two tests", function (t) { + t.equal(255, 0xFF, "math should work") + t.notOk(false, "false should not be ok") + t.end() +}) diff --git a/node_modules/tap/test/simple-harness-test.js b/node_modules/tap/test/simple-harness-test.js new file mode 100644 index 0000000..64451ae --- /dev/null +++ b/node_modules/tap/test/simple-harness-test.js @@ -0,0 +1,13 @@ +var tap = require("../") + , test = tap.test + +test("trivial success", function (t) { + t.ok(true, "it works") + t.end() +}) + +test("two tests", function (t) { + t.equal(255, 0xFF, "math should work") + t.notOk(false, "false should not be ok") + t.end() +}) diff --git a/node_modules/tap/test/test-test.js b/node_modules/tap/test/test-test.js new file mode 100644 index 0000000..f383941 --- /dev/null +++ b/node_modules/tap/test/test-test.js @@ -0,0 +1,91 @@ +var tap = require("../") + , test = tap.test + , Test = require("../lib/tap-test") + , Harness = require("../lib/tap-harness") + +test("testing the test object", function (t) { + + t.isa(t, Test, "test object should be instanceof Test") + t.isa(t, Harness, "test object should be instanceof Harness") + t.is(t._Test, Test, "test._Test should be the Test class") + + // now test all the methods. + ; [ "isNotDeepEqual" + , "equals" + , "inequivalent" + , "threw" + , "strictEqual" + , "emit" + , "fail" + , "strictEquals" + , "notLike" + , "dissimilar" + , "true" + , "assert" + , "is" + , "ok" + , "isEqual" + , "isDeeply" + , "deepEqual" + , "deepEquals" + , "pass" + , "length" + , "skip" + , "isNotEqual" + , "looseEquals" + , "false" + , "notDeeply" + , "ifErr" + , "hasFields" + , "isNotDeeply" + , "like" + , "similar" + , "notOk" + , "isDissimilar" + , "isEquivalent" + , "doesNotEqual" + , "isSimilar" + , "notDeepEqual" + , "type" + , "notok" + , "isInequivalent" + , "isNot" + , "same" + , "isInequal" + , "_endNice" + , "ifError" + , "iferror" + , "clear" + , "has" + , "not" + , "timeout" + , "notSimilar" + , "isUnlike" + , "notEquals" + , "unsimilar" + , "result" + , "doesNotThrow" + , "error" + , "constructor" + , "notEqual" + , "throws" + , "isLike" + , "isNotSimilar" + , "isNotEquivalent" + , "inequal" + , "notEquivalent" + , "isNotLike" + , "equivalent" + , "looseEqual" + , "equal" + , "unlike" + , "doesNotHave" + , "comment" + , "isa" + ].forEach(function (method) { + t.ok(t[method], "should have "+method+" method") + t.isa(t[method], "function", method+" method should be a function") + }) + t.end() +}) + diff --git a/node_modules/tap/test/timeout.js b/node_modules/tap/test/timeout.js new file mode 100644 index 0000000..4ee409c --- /dev/null +++ b/node_modules/tap/test/timeout.js @@ -0,0 +1,33 @@ +var tap = require("../") + +tap.test("timeout test with plan only", function (t) { + console.error("timeout test") + t.plan(2) + console.error("t.plan="+t._plan) + setTimeout(function () { + console.error("a assert") + t.ok(true, "a") + }, 1000) + setTimeout(function () { + console.error("b assert") + t.ok(true, "b") + }, 1000) +}) + +tap.test("timeout test with plan and end", function (t) { + console.error("timeout test") + t.plan(2) + + var tc = 2 + console.error("t.plan="+t._plan) + setTimeout(function () { + console.error("a assert") + t.ok(true, "a") + if (-- tc === 0) t.end() + }, 1000) + setTimeout(function () { + console.error("b assert") + t.ok(true, "b") + if (-- tc === 0) t.end() + }, 1000) +}) diff --git a/node_modules/tap/test/trivial-success.js b/node_modules/tap/test/trivial-success.js new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/traverse/.eslintrc b/node_modules/traverse/.eslintrc new file mode 100644 index 0000000..1fc98be --- /dev/null +++ b/node_modules/traverse/.eslintrc @@ -0,0 +1,33 @@ +{ + "root": true, + + "extends": "@ljharb/eslint-config/node/0.4", + + "rules": { + "array-bracket-newline": 0, + "array-callback-return": 0, + "array-element-newline": 0, + "complexity": 0, + "func-style": [2, "declaration"], + "global-require": 1, + "max-lines-per-function": 0, + "max-statements-per-line": 1, + "multiline-comment-style": 0, + "no-proto": 0, + "no-sparse-arrays": 1, + "no-underscore-dangle": 0, + "no-invalid-this": 0, + "object-curly-newline": 0, + "sort-keys": 0, + }, + + "overrides": [ + { + "files": "examples/**", + "rules": { + "no-console": 0, + "no-plusplus": 0, + }, + }, + ], +} diff --git a/node_modules/traverse/.github/FUNDING.yml b/node_modules/traverse/.github/FUNDING.yml new file mode 100644 index 0000000..e7dd4fa --- /dev/null +++ b/node_modules/traverse/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: [ljharb] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: npm/traverse +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: # Replace with a single custom sponsorship URL diff --git a/node_modules/traverse/CHANGELOG.md b/node_modules/traverse/CHANGELOG.md new file mode 100644 index 0000000..82c6f63 --- /dev/null +++ b/node_modules/traverse/CHANGELOG.md @@ -0,0 +1,432 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [v0.6.7](https://github.com/ljharb/js-traverse/compare/v0.6.6...v0.6.7) - 2022-10-12 + +### Commits + +- [eslint] fix indentation and whitespace [`89fc65c`](https://github.com/ljharb/js-traverse/commit/89fc65c5c9f2778cb63d583b1fcd83a31ca104f4) +- [eslint] cleanup [`1921966`](https://github.com/ljharb/js-traverse/commit/1921966fff1933e086d413acc44c2cf43a130fae) +- [meta] add `auto-changelog` [`c291ed2`](https://github.com/ljharb/js-traverse/commit/c291ed225c7b5257372a3d30951eaefc186107e7) +- [actions] add reusable workflows [`9a8fd34`](https://github.com/ljharb/js-traverse/commit/9a8fd34a6111f3f6dff43a7f22d272c46243d68f) +- [Dev Deps] update `tape` [`afd6a95`](https://github.com/ljharb/js-traverse/commit/afd6a95c5ab6b8ed2e29d044b5ff8724ed992c4d) +- [eslint] add eslint [`559372e`](https://github.com/ljharb/js-traverse/commit/559372ec96b460c45953c4c00f931f7fee36dce7) +- [readme] rename, add badges [`0e613fd`](https://github.com/ljharb/js-traverse/commit/0e613fdf7d3712e9b18a678d45cadd639233c79e) +- [meta] create FUNDING.yml; add `funding` in package.json [`26a9ae3`](https://github.com/ljharb/js-traverse/commit/26a9ae3a2e6ff06a3af9f1301ec4ef08ceb99bec) +- [meta] use `npmignore` to autogenerate an npmignore file [`0e09fe6`](https://github.com/ljharb/js-traverse/commit/0e09fe6105466f5e11ff4e1d12fa5cb77848b900) +- Only apps should have lockfiles [`e1ac253`](https://github.com/ljharb/js-traverse/commit/e1ac253acfa4917617c01b7d76d80741cbe379ce) +- [meta] update URLs [`035e2c0`](https://github.com/ljharb/js-traverse/commit/035e2c05c52acde26d5c13599748a901d1bbf237) +- [meta] add `safe-publish-latest` [`c2797ac`](https://github.com/ljharb/js-traverse/commit/c2797ac1218e9c8da1a9dd3863ecf3698e57878f) +- [Tests] add `aud` in `posttest` [`ff93f53`](https://github.com/ljharb/js-traverse/commit/ff93f5380201ccbd0bf22188ed4943b739174589) + +## [v0.6.6](https://github.com/ljharb/js-traverse/compare/v0.6.5...v0.6.6) - 2013-09-23 + +### Commits + +- remove tap as a dep to get around the cyclic library issues [`85e1b23`](https://github.com/ljharb/js-traverse/commit/85e1b23ea360b4e6918f998c95ef84d8a0d9a1d2) +- guard for the presence of getTime [`98f278a`](https://github.com/ljharb/js-traverse/commit/98f278a34a957134688e147ec65b1b1115244234) +- use getTime() for firefox browser support [`ee928ca`](https://github.com/ljharb/js-traverse/commit/ee928ca5c2b6a3b19cecd01a743d38d3cddaccf5) + +## [v0.6.5](https://github.com/ljharb/js-traverse/compare/v0.6.4...v0.6.5) - 2013-08-30 + +### Commits + +- merge the null fix [`c405df2`](https://github.com/ljharb/js-traverse/commit/c405df2c8a8d49321ac8081b928b4e5df5f80237) +- fix for Cannot convert null to object at hasOwnProperty (native) when node is null [`d9f52fa`](https://github.com/ljharb/js-traverse/commit/d9f52fa400c53f5bf1b5e388c0dd457c4dc651e3) + +## [v0.6.4](https://github.com/ljharb/js-traverse/compare/v0.6.3...v0.6.4) - 2012-12-17 + +### Commits + +- upgraded readme [`c45db75`](https://github.com/ljharb/js-traverse/commit/c45db75c4a606b724156e50b14688b503e146cf3) +- using tape [`5c8e966`](https://github.com/ljharb/js-traverse/commit/5c8e966e8636fdab2c55cac0e4e0958f06f7ca1f) +- using testling-ci [`73f3061`](https://github.com/ljharb/js-traverse/commit/73f306146afa8ccc884cb0d43788338e294320cc) +- hasOwnProperty stub [`c889666`](https://github.com/ljharb/js-traverse/commit/c889666d81d79cbfd99372bea641e6938bd5531c) +- add a comma [`3f8d778`](https://github.com/ljharb/js-traverse/commit/3f8d778dbc0b070c972839fd1ac23b253a99cce2) + +## [v0.6.3](https://github.com/ljharb/js-traverse/compare/v0.6.2...v0.6.3) - 2012-06-18 + +### Commits + +- 0.6.3, fixes bugs when the replacement for an object is not an object [`09f560c`](https://github.com/ljharb/js-traverse/commit/09f560c0f910a9ac76fa0fc507655627cda6dd6f) +- fixed merge conflicts [`576832a`](https://github.com/ljharb/js-traverse/commit/576832a2e4d91197b88a002dec643310fa9b3b26) +- Update state with the current node before recursing [`3857dca`](https://github.com/ljharb/js-traverse/commit/3857dcaeaceca9a739300b0b846c1094ddf3b26f) +- Add test for replacing objects with strings and vice-versa [`28d5fb6`](https://github.com/ljharb/js-traverse/commit/28d5fb64e44237e21c01904d6e46b34626d66d33) +- s/Object_keys/objectKeys/g [`ef3694f`](https://github.com/ljharb/js-traverse/commit/ef3694f1fcfe948c39a5caaded33480bcbdafdfa) +- Only set state.keys when necessary [`ee66cd1`](https://github.com/ljharb/js-traverse/commit/ee66cd1c71db7701769323548916ce860f442d03) +- Fix crash when node is a string and this.update is called with an object. [`5c6f161`](https://github.com/ljharb/js-traverse/commit/5c6f161f2006df87f231317f3413bc38ad799b7d) + +## [v0.6.2](https://github.com/ljharb/js-traverse/compare/v0.6.1...v0.6.2) - 2012-06-16 + +### Commits + +- using tap [`4f4a3e5`](https://github.com/ljharb/js-traverse/commit/4f4a3e504e702bffa88ea15b687a3712b56938dd) +- re-generate the package.json [`99a0a15`](https://github.com/ljharb/js-traverse/commit/99a0a159b28d8175c159a208e276256a0240c056) +- fix to reconstruct prototypes in browsers without Object.create() [`0cb3f34`](https://github.com/ljharb/js-traverse/commit/0cb3f349e381109287c9fac1391472796b7fc0bd) +- using travis [`57e7ccd`](https://github.com/ljharb/js-traverse/commit/57e7ccd6b10e92e737ef41b332172b38b4d5cc2e) +- s/^js-// [`1c2bae3`](https://github.com/ljharb/js-traverse/commit/1c2bae3a286b38c5f7cd22ffe4bbcc165bab7245) +- drop 0.4 [`2331189`](https://github.com/ljharb/js-traverse/commit/2331189e047b94fc95edc6f6fce11cb0cfcbb435) + +## [v0.6.1](https://github.com/ljharb/js-traverse/compare/v0.6.0...v0.6.1) - 2012-04-06 + +### Commits + +- check builtins using the toString.call trick [`459378b`](https://github.com/ljharb/js-traverse/commit/459378b6dd18ea95e9a012fd96a5d0d30ce83d64) +- support for traversing an Error object. [`642dd51`](https://github.com/ljharb/js-traverse/commit/642dd51c41ca7e41774bbde948913d9a7996633e) +- fixed the tests for how typeof a regex is now "object" [`9250084`](https://github.com/ljharb/js-traverse/commit/925008491725beec15216147329f3df907285975) +- less annoying constructor [`2c5f693`](https://github.com/ljharb/js-traverse/commit/2c5f693b60daa8b0f2cc9566fa62ec6b733d6a84) +- bump for error fixes [`6b78600`](https://github.com/ljharb/js-traverse/commit/6b78600f53284b324e733f836b9fd3b47fa5b28d) + +## [v0.6.0](https://github.com/ljharb/js-traverse/compare/v0.5.2...v0.6.0) - 2012-02-20 + +### Commits + +- has() with tests, documented get() and set() too [`aeebf14`](https://github.com/ljharb/js-traverse/commit/aeebf1466c2b7b5660545cc4365b0a66bc54a765) + +## [v0.5.2](https://github.com/ljharb/js-traverse/compare/v0.5.1...v0.5.2) - 2011-10-16 + +### Commits + +- Should be able to stop traversing when removing or deleting [`4aa61ef`](https://github.com/ljharb/js-traverse/commit/4aa61ef874d81a633aec4b72c3b2bc5ede64947f) +- relative requires for the tests [`9d4d4c5`](https://github.com/ljharb/js-traverse/commit/9d4d4c5d4c3abb9ef38c6f878a7ee8c61f0264c1) +- Added documentation for stopHere-flag on remove and delete [`2bb8018`](https://github.com/ljharb/js-traverse/commit/2bb80186f15d860cd5e17934c270bd0814236004) +- bump for stopHere on delete and remove [`a23839a`](https://github.com/ljharb/js-traverse/commit/a23839a473d0e91814911210f01d2ec4a95d1098) + +## [v0.5.1](https://github.com/ljharb/js-traverse/compare/v0.5.0...v0.5.1) - 2011-08-23 + +### Commits + +- fix for brokenness in IE with using the wrong variable name for the prototype checking [`4cb7bcb`](https://github.com/ljharb/js-traverse/commit/4cb7bcbd155df29268c8b8fc249f0f838aaa94f3) + +## [v0.5.0](https://github.com/ljharb/js-traverse/compare/v0.4.6...v0.5.0) - 2011-08-23 + +### Commits + +- spun off deepEqual into a utility library [`9d5148a`](https://github.com/ljharb/js-traverse/commit/9d5148a22dbe1484286c216959625168275457db) +- traverse now works with all the IEs [`96d9e25`](https://github.com/ljharb/js-traverse/commit/96d9e2564fc0f1413a7a1371cfd9cc5600896771) +- tests all updated for the removal of deepEqual from the main lib [`9ebde92`](https://github.com/ljharb/js-traverse/commit/9ebde9226720231d4390ebdaea04a0c4652caf21) +- stubs for non-es5 browsers, didn't break any unit tests [`559a6f1`](https://github.com/ljharb/js-traverse/commit/559a6f18873d48a97b293c058cc2a8f334dfd535) + +## [v0.4.6](https://github.com/ljharb/js-traverse/compare/v0.4.5...v0.4.6) - 2011-07-27 + +### Commits + +- some minor adjustments to expose keys for sibling calculations [`a936bea`](https://github.com/ljharb/js-traverse/commit/a936bea1e4d164ab33459352234eaea9a1d84a38) + +## [v0.4.5](https://github.com/ljharb/js-traverse/compare/v0.4.4...v0.4.5) - 2011-07-24 + +### Commits + +- include circular ref example in the readme, Traverse => traverse [`4a6285f`](https://github.com/ljharb/js-traverse/commit/4a6285f71f4220550d4587090fd832ec9fcb10b7) +- scrub example [`ec1fb18`](https://github.com/ljharb/js-traverse/commit/ec1fb18b494f1bcb6b1ce4a2a86dce6560ae746d) +- bump for exposing parents [`5cb4ecb`](https://github.com/ljharb/js-traverse/commit/5cb4ecb37b2af64367f466cd1994d18c45def070) +- export 'parents' to context [`5af2f8d`](https://github.com/ljharb/js-traverse/commit/5af2f8d24e2e9dce5c43ae5abbe2ff23384610fc) + +## [v0.4.4](https://github.com/ljharb/js-traverse/compare/v0.4.3...v0.4.4) - 2011-07-20 + +### Commits + +- allow setting of keys (ordering) in before modifier [`9fb8e2c`](https://github.com/ljharb/js-traverse/commit/9fb8e2c126e5bcec59e382b59e040ae764ea9045) +- note about this.keys, bump [`1148bc7`](https://github.com/ljharb/js-traverse/commit/1148bc7603411c423b41a5cb396b27ab6ca2c565) + +## [v0.4.3](https://github.com/ljharb/js-traverse/compare/v0.4.2...v0.4.3) - 2011-06-14 + +### Commits + +- bump to 0.4.3 for guybrush's IE fixes [`c74a7ea`](https://github.com/ljharb/js-traverse/commit/c74a7eaa83edb86e20b2427bbd2068339b385aa8) +- another fix for IE [`ed86376`](https://github.com/ljharb/js-traverse/commit/ed86376b826284a858d040f8d0a40532a8d4d919) +- fix for IE [`35949ef`](https://github.com/ljharb/js-traverse/commit/35949ef979662e6a9118beca80d0f6a080828ddc) + +## [v0.4.2](https://github.com/ljharb/js-traverse/compare/v0.4.1...v0.4.2) - 2011-06-11 + +### Commits + +- bump to 0.4.2 for this.block() with a passing test [`d945818`](https://github.com/ljharb/js-traverse/commit/d945818e0e489d9ffe2dd25ea64c598085139c69) +- note about stopHere for update() in the readme [`18f3e27`](https://github.com/ljharb/js-traverse/commit/18f3e273c7ec22b7121438d517eaeb7832f18d99) + +## [v0.4.1](https://github.com/ljharb/js-traverse/compare/v0.4.0...v0.4.1) - 2011-06-10 + +### Commits + +- moved stop behavior in updates into a second keepGoing argument [`1d31897`](https://github.com/ljharb/js-traverse/commit/1d318974255df34a821da53cb3d573153a0682b2) + +## [v0.4.0](https://github.com/ljharb/js-traverse/compare/v0.3.8...v0.4.0) - 2011-06-10 + +### Commits + +- an amazing number of test descriptions were getting ignored [`1d043f0`](https://github.com/ljharb/js-traverse/commit/1d043f09e6eb6ecf8456295efdbe4e7298f7c3c8) +- better failing super deep test [`01d35ce`](https://github.com/ljharb/js-traverse/commit/01d35ce70d514243d1854bd4c50eb0fa5321ef2b) +- stop() passes its test [`79d615f`](https://github.com/ljharb/js-traverse/commit/79d615f8dc60dc491da82d80f0fdab1a53974d3d) +- passing test for deep reduce and this.stop() [`9aea0a1`](https://github.com/ljharb/js-traverse/commit/9aea0a10cdd48f23ef40aeaee54f2d50053d77ff) +- subexpr test passes by checking if update() happened [`44e731b`](https://github.com/ljharb/js-traverse/commit/44e731b972b864b1de1ef315bf1ce4dbba3a7d67) +- passing new tests yay [`3d5057a`](https://github.com/ljharb/js-traverse/commit/3d5057a832c14f51d07ddb7f3331769c37f6192d) +- failing test for this.stop() [`090c3d4`](https://github.com/ljharb/js-traverse/commit/090c3d4d2de99586ad89a8b51ab8ea5664747e3e) +- subexpressions from update()s shouldn't be traversed, failing test [`be2b574`](https://github.com/ljharb/js-traverse/commit/be2b5746670b213d1c57c8f1f6d59a78e8ff88e6) +- passing test for stop map too hooray [`0ee24cc`](https://github.com/ljharb/js-traverse/commit/0ee24cc01673ea3dfd63e854b70bcd7b36b9884d) +- test for arity shows more bugs [`da698d6`](https://github.com/ljharb/js-traverse/commit/da698d6c7f5b712c9d89b3fa42a00b9cf2b42b4c) + +## [v0.3.8](https://github.com/ljharb/js-traverse/compare/v0.3.7...v0.3.8) - 2011-06-06 + +### Commits + +- tests for some bugs in deepEqual [`2b15a41`](https://github.com/ljharb/js-traverse/commit/2b15a410f723f0ed5b3bdc019803deff7d70b7c0) +- deep equal tests now pass, delete map tests fail though [`bfdc40e`](https://github.com/ljharb/js-traverse/commit/bfdc40e35f7a3ec3acf96f7f8599602747ef999d) +- delete map redux test also passes for deleted element construction syntax [,,,] etc [`56553ff`](https://github.com/ljharb/js-traverse/commit/56553ff7753e21480023caa488791a4d88f36673) +- now passing all the equality tests again [`6721461`](https://github.com/ljharb/js-traverse/commit/6721461c4fc1323c5784f16ee5efcd7a18d77122) +- tests for remove() and delete() [`f5d429a`](https://github.com/ljharb/js-traverse/commit/f5d429a15a77e2a7ce33c2485a2b3ee43f41d341) +- remove tests [`7010fe2`](https://github.com/ljharb/js-traverse/commit/7010fe2bdc568f59576da576c09b5a7c90291b89) +- better failing levels test for deepEqual [`73efbe5`](https://github.com/ljharb/js-traverse/commit/73efbe5ea5f2c61c8c3f6e4cd6fbc2d290e33188) +- failing deepEqual comparison with undefined throws [`0a6d27d`](https://github.com/ljharb/js-traverse/commit/0a6d27d139baefbd2a19411a6a4805b2bbd5d664) +- remove unused seq devDependency, bump expresso version [`0c1e021`](https://github.com/ljharb/js-traverse/commit/0c1e0218a991fa6fd71468ee54cdd364cab5d1b5) + +## [v0.3.7](https://github.com/ljharb/js-traverse/compare/v0.3.6...v0.3.7) - 2011-06-05 + +### Commits + +- now with syntax-highlightable markdown snippets [`d4a7710`](https://github.com/ljharb/js-traverse/commit/d4a771015d6483859784a585912a816bd4d82484) +- failing circular map scrub test [`9f36635`](https://github.com/ljharb/js-traverse/commit/9f3663533d34d4280c6dd49387a8516b40ae67c4) +- fix for immutable removal, bump to 0.3.7 [`9528471`](https://github.com/ljharb/js-traverse/commit/9528471cad4bbe810d7b10133f53ea0937e6667d) + +## [v0.3.6](https://github.com/ljharb/js-traverse/compare/v0.3.5...v0.3.6) - 2011-06-03 + +### Commits + +- tests for not-yet-written deepEqual() [`5267ae1`](https://github.com/ljharb/js-traverse/commit/5267ae183ac44d82438da0c3665a31c456e27fdb) +- deepEqual now passes several tests [`6fe06a5`](https://github.com/ljharb/js-traverse/commit/6fe06a5a7e7d76e4cdeaae148fbd40964a8bd478) +- dox for deepEqual [`5eab662`](https://github.com/ljharb/js-traverse/commit/5eab662f486e423e8d1d4bde65c47f99243aa1fe) +- untested get and set [`7fa7247`](https://github.com/ljharb/js-traverse/commit/7fa7247dcfe2b2ddcc0ea9ecd2c7329a1e034151) +- missing comma fixed the regexp test and also an implementation for typeof "function" [`fc23e4f`](https://github.com/ljharb/js-traverse/commit/fc23e4fb50e8adf0891c416c994390b02545a197) +- a passing test for the other case of structural deep circular reference checking [`04e5492`](https://github.com/ljharb/js-traverse/commit/04e54928da73b2d02a4430bfa79e2505af51068a) +- some tests were wrong, regexp test rightly still fails [`b9d1110`](https://github.com/ljharb/js-traverse/commit/b9d11107f62367453eaf707b2cb29df1533043ea) +- circular test for topological circular equality passes [`b423996`](https://github.com/ljharb/js-traverse/commit/b4239962ab0312d660a7895b74fda36368d057f9) +- and another test just in case for non-root circular ref checks [`a914717`](https://github.com/ljharb/js-traverse/commit/a9147171961cbf7ae8a9a45fb73cd3c0591da33b) +- actually check function equality, all tests now passing [`cb7c1b0`](https://github.com/ljharb/js-traverse/commit/cb7c1b04cb7b4b1037419349000e96b13d824ab7) + +## [v0.3.5](https://github.com/ljharb/js-traverse/compare/v0.3.4...v0.3.5) - 2011-05-28 + +### Commits + +- took out up-front cloning, only fails date test [`718d01b`](https://github.com/ljharb/js-traverse/commit/718d01b06cdb9f9c948d1ac5886a7a3fc17d1008) +- cleaned up root handling, fails circDubMap still [`9ed99f3`](https://github.com/ljharb/js-traverse/commit/9ed99f3dd74123c17eb2787bfac6207c643d39d6) +- updated tests for expresso updates ages ago [`f95bf5e`](https://github.com/ljharb/js-traverse/commit/f95bf5e0eb7300832d326960289ec7f395630bfd) +- passes all its tests again [`d0dac52`](https://github.com/ljharb/js-traverse/commit/d0dac529201dc8b3e6a7dba3d853d839b746ffbf) + +## [v0.3.4](https://github.com/ljharb/js-traverse/compare/v0.3.3...v0.3.4) - 2011-04-16 + +### Commits + +- updated readme for this.delete() and this.remove() [`e4cea30`](https://github.com/ljharb/js-traverse/commit/e4cea309a1f035400c8f4e9ebd55e6e0cecf8a35) +- quote the delete keyword [`42d0460`](https://github.com/ljharb/js-traverse/commit/42d0460fc6624a38775bd65a4788cfa8b3f08825) + +## [v0.3.3](https://github.com/ljharb/js-traverse/compare/v0.3.2...v0.3.3) - 2011-04-15 + +### Commits + +- this.remove() and this.delete() with passing tests [`d603771`](https://github.com/ljharb/js-traverse/commit/d603771e1381e0d62c70bc1f47736c8eaa6cfa6f) + +## [v0.3.2](https://github.com/ljharb/js-traverse/compare/v0.3.1...v0.3.2) - 2011-04-10 + +### Commits + +- now traverses over dates correctly and should work for other builtins [`bb8d1b5`](https://github.com/ljharb/js-traverse/commit/bb8d1b567489a94507941f4a6bda2224ed2d9692) +- failing date map test [`a504425`](https://github.com/ljharb/js-traverse/commit/a504425aa3021371f67498b27d4a98e6f7a4283f) +- forgot the console.dir [`fb2c472`](https://github.com/ljharb/js-traverse/commit/fb2c4729ac1a7824358ee04ea840a35ac3ea17af) + +## [v0.3.1](https://github.com/ljharb/js-traverse/compare/v0.3.0...v0.3.1) - 2011-02-18 + +### Commits + +- updated readme and examples for the new interface changes [`aa2d4f3`](https://github.com/ljharb/js-traverse/commit/aa2d4f3f1cc88a230cdb8fae3b1b416773860ef4) +- mutability tests all pass [`36df874`](https://github.com/ljharb/js-traverse/commit/36df874ae431b0e31dc809c0b949073774f624b4) +- updated tests to not use sys anymore [`7a0969f`](https://github.com/ljharb/js-traverse/commit/7a0969fbb39a7a66f4bd46ca8172edef15b675ea) +- simpler clone implementation [`6a6cb49`](https://github.com/ljharb/js-traverse/commit/6a6cb49f2da571470a6b024b1e8db5ef2080b946) +- double circular ref test failing, not aggressive enough [`d190897`](https://github.com/ljharb/js-traverse/commit/d190897a9763549e2a077c01378520d519b402f7) +- reduce() now too [`c89ae4b`](https://github.com/ljharb/js-traverse/commit/c89ae4be025534494422cc1265f50595828398b3) +- fix for isRoot, check path.length, not node === root [`423066e`](https://github.com/ljharb/js-traverse/commit/423066e821070ffb8f8a29022175b08f4bfc5d99) +- passing circular ref update forEach test but failing for likewise with map [`d411695`](https://github.com/ljharb/js-traverse/commit/d4116955a4fbc00a2fd716e3885e334b9664d670) +- trade some space savings for less agressive circular reference algorithm (the same as console.dir it seems) [`ee52d80`](https://github.com/ljharb/js-traverse/commit/ee52d80d2b18ea069f38039b210f68b00aa29d4b) +- failing test for circular ref updates [`42b6b84`](https://github.com/ljharb/js-traverse/commit/42b6b84917f34f80729339127360c36bd62fa9bd) + +## [v0.3.0](https://github.com/ljharb/js-traverse/compare/v0.2.4...v0.3.0) - 2011-02-18 + +### Commits + +- completely rewrote Traverse, deleted hash.js and web.js [`414c726`](https://github.com/ljharb/js-traverse/commit/414c72637807c0e6e86f38f66146d729d0bbf3f2) +- tests pass again with the rewrite [`f0f76cc`](https://github.com/ljharb/js-traverse/commit/f0f76cc6b08849644a79a828e249be2d8896797a) + +## [v0.2.4](https://github.com/ljharb/js-traverse/compare/v0.2.3...v0.2.4) - 2011-02-03 + +### Commits + +- for some silly reason I was requiring sys [`95712d9`](https://github.com/ljharb/js-traverse/commit/95712d9de9e6182860418754690bb98c40462d62) + +## [v0.2.3](https://github.com/ljharb/js-traverse/compare/v0.2.2...v0.2.3) - 2010-11-19 + +### Commits + +- a hash exclude test and a package bump [`536b93d`](https://github.com/ljharb/js-traverse/commit/536b93dc0474a27a0f5c3f53b8a80cf3eb32e4e4) +- exclude to remove keys [`752f64f`](https://github.com/ljharb/js-traverse/commit/752f64f66da9fb424a4f78fc2d4ad0ef096ba65d) + +## [v0.2.2](https://github.com/ljharb/js-traverse/compare/v0.2.1...v0.2.2) - 2010-10-25 + +### Commits + +- detect test, package bump [`04b1d50`](https://github.com/ljharb/js-traverse/commit/04b1d50e73870026fd21ab9ccea609c3f1351080) +- detect like in ruby [`441f3b4`](https://github.com/ljharb/js-traverse/commit/441f3b4bef547cb4b07b10e139fa68ec1b9b4a95) + +## [v0.2.1](https://github.com/ljharb/js-traverse/compare/v0.2.0...v0.2.1) - 2010-09-11 + +### Commits + +- better compatability fallbacks for ff, maybe ie [`33577aa`](https://github.com/ljharb/js-traverse/commit/33577aae0ccdc441e40fab0a945d831805cc8148) +- compact and size for Hash (can't do .length since the function prototype has that) [`b9e6db5`](https://github.com/ljharb/js-traverse/commit/b9e6db57addbcc67a1cfec0ab9a380573d0cab8e) +- more correct string behavior in stringify example [`b9750ff`](https://github.com/ljharb/js-traverse/commit/b9750ff32be6ad76892bdf01a533bd13907d92f7) + +## [v0.2.0](https://github.com/ljharb/js-traverse/compare/v0.1.4...v0.2.0) - 2010-09-08 + +### Commits + +- deepEquals to make the tests simpler [`a962ed8`](https://github.com/ljharb/js-traverse/commit/a962ed8d0e5e3baf8279e5b3bf2476e5d2c7dbb8) +- top-level Hash functions more closely mirror Hash() functions [`35298be`](https://github.com/ljharb/js-traverse/commit/35298be61b782681f6d0a555a0ab8db673419293) +- .has with tests [`02727cf`](https://github.com/ljharb/js-traverse/commit/02727cfe1d86cf6c36daa700513861fe1f4a8066) +- test for valuesAt and now takes a single non-array key too [`3487771`](https://github.com/ljharb/js-traverse/commit/348777160fe2008186d5089fddd8e5686d0c1c3a) +- take out memoization since it breaks if the hash gets modified outside the fluent interface [`67b6d3d`](https://github.com/ljharb/js-traverse/commit/67b6d3d5ea7d8ed7127f7f9129660510f9292716) +- zip and zip constructor [`616514e`](https://github.com/ljharb/js-traverse/commit/616514ebd72a9c8a4e4b59763ee0462dcae89de0) +- zip test passes [`0226636`](https://github.com/ljharb/js-traverse/commit/0226636db7b8d3a49c2a7cbb26d18f7eeba061c1) + +## [v0.1.4](https://github.com/ljharb/js-traverse/compare/v0.1.3...v0.1.4) - 2010-09-08 + +### Commits + +- test for compact passes [`ec171ba`](https://github.com/ljharb/js-traverse/commit/ec171bab4d2b2339752cbab00c0d4b65652de0f0) +- compact like in ruby, but for hashes [`0d8e1e6`](https://github.com/ljharb/js-traverse/commit/0d8e1e624005b58aecd6a6dddaefc20da33cdf4a) + +## [v0.1.3](https://github.com/ljharb/js-traverse/compare/v0.1.2...v0.1.3) - 2010-09-04 + +### Commits + +- add stringify to examples [`6683529`](https://github.com/ljharb/js-traverse/commit/668352964878c1f896b3f57b69a989717c0fae5c) +- now isArray and instanceof works for arrays [`fa2d72b`](https://github.com/ljharb/js-traverse/commit/fa2d72b33705adccc74bf12e94e4e68d7261469c) + +## [v0.1.2](https://github.com/ljharb/js-traverse/compare/v0.1.1...v0.1.2) - 2010-09-04 + +### Commits + +- pushed walk() out of map [`e7ec7de`](https://github.com/ljharb/js-traverse/commit/e7ec7dee4b33968b0b380e54202d5d01af5e9a80) +- modifiers seem to work [`f0ee567`](https://github.com/ljharb/js-traverse/commit/f0ee567968c4b218ae729d76520ab2f3fe2c372f) +- stringify test for new modifiers [`6de18e5`](https://github.com/ljharb/js-traverse/commit/6de18e5012578b4a71faf442962ce999fc72624c) +- before, after, and between callbacks to fancier traversing [`5662b6f`](https://github.com/ljharb/js-traverse/commit/5662b6f5265bfec32dccb999b9749cf2569e7d9f) +- updated readme and negative example with new style [`5aa3f84`](https://github.com/ljharb/js-traverse/commit/5aa3f84584fb1a74652485e3cf809f5982a4cb88) +- deprecated .get() in favor of .value [`a8d1645`](https://github.com/ljharb/js-traverse/commit/a8d1645665ebb832ff82eca3317e61bf62ca83ed) +- non-coerced root test fixes an odd bug with array traversal [`f22580a`](https://github.com/ljharb/js-traverse/commit/f22580aacec7b2eb60c38ba8ba1b89324ed3e209) + +## [v0.1.1](https://github.com/ljharb/js-traverse/compare/v0.1.0...v0.1.1) - 2010-09-04 + +### Commits + +- only update when this.update is still around, tests for Traverse.functions [`cc59d56`](https://github.com/ljharb/js-traverse/commit/cc59d56b994759f6acd9efd70d9063ea40f45fbf) +- deprecate modify in favor of map [`f018025`](https://github.com/ljharb/js-traverse/commit/f018025989afdd6c9474d9e9095331500826d553) +- fix nodes and paths [`78edd30`](https://github.com/ljharb/js-traverse/commit/78edd30685e1d47deac4edd7bdd1e1b360a0244f) +- use return values to auto-update [`bc68fa5`](https://github.com/ljharb/js-traverse/commit/bc68fa5426363872835f1b4b73b8abf7920c9bfc) + +## [v0.1.0](https://github.com/ljharb/js-traverse/compare/v0.0.9...v0.1.0) - 2010-09-03 + +### Commits + +- circular refs don't crash it now [`2cdd854`](https://github.com/ljharb/js-traverse/commit/2cdd85460054f91e3130b269a6020e20cb59d7c0) +- new top-level map forEach paths and nodes [`e508823`](https://github.com/ljharb/js-traverse/commit/e5088233c9e09221f2ac766bd95c0ea55e7d0761) +- package bump to 0.1.0 and should work in IE better now too [`4400d88`](https://github.com/ljharb/js-traverse/commit/4400d886d7e33dd811121e7cd5ac5a31a0ca25b0) + +## [v0.0.9](https://github.com/ljharb/js-traverse/compare/v0.0.8...v0.0.9) - 2010-08-27 + +### Commits + +- broke up test into separate exports [`92046a4`](https://github.com/ljharb/js-traverse/commit/92046a4e0622d0db9502a2d6090041935d1bede6) +- forgot the return in ('traverse/web').source() [`188ee17`](https://github.com/ljharb/js-traverse/commit/188ee170de8b087a6bbec6dad92b39a0f1ffc67e) + +## [v0.0.8](https://github.com/ljharb/js-traverse/compare/v0.0.7...v0.0.8) - 2010-08-26 + +### Commits + +- memoization for keys, values, length [`9cffe15`](https://github.com/ljharb/js-traverse/commit/9cffe158a70f4945a6bf000dace4eddf4ca2c344) +- merge, update, and tap [`df5b737`](https://github.com/ljharb/js-traverse/commit/df5b737a7b82711261be325b7f9aa0e7aedc6804) +- length, clone, and copy [`249ec0f`](https://github.com/ljharb/js-traverse/commit/249ec0fcd2b62c6701488c17083433049060ae15) +- updated readme and f.call(self) [`03f6f1e`](https://github.com/ljharb/js-traverse/commit/03f6f1e03c9ccc2a6afb0525393acde13d2b009f) +- more explicit about the licensing (MIT/X11) [`c452103`](https://github.com/ljharb/js-traverse/commit/c4521038e845878ebb20984204f1db7520df9cad) +- oh right and this example file [`d98c125`](https://github.com/ljharb/js-traverse/commit/d98c125d9f9f17ca08260ed57ede2b1fac26da11) +- updated readme for hash traversal [`a56b629`](https://github.com/ljharb/js-traverse/commit/a56b629aae33e6bfe45bc3ec72b65bc84536f57b) +- tests for update, concat, and merge all pass [`7fc4eca`](https://github.com/ljharb/js-traverse/commit/7fc4ecaf203924becd9c88d800216ddad7ecbd4b) +- updated readme for hash stuff [`094ab55`](https://github.com/ljharb/js-traverse/commit/094ab556f795e554e8227016d8fd6acc36f0257c) +- more tests, all pass [`2d9f7a2`](https://github.com/ljharb/js-traverse/commit/2d9f7a245ac6793e8e58ba4c751e551650cfbaac) +- key and value getters [`459def9`](https://github.com/ljharb/js-traverse/commit/459def9529e381d38909f75b182b330e20d3f2f9) +- stupid markdown parens [`0bd932b`](https://github.com/ljharb/js-traverse/commit/0bd932bc6517d08f02ab3aac8cc551425072ead7) +- new valuesAt and extract functions [`883f015`](https://github.com/ljharb/js-traverse/commit/883f015c79ea79acc188a98be3bfa7ad54186266) +- tests for valuesAt and extract pass [`86d71a9`](https://github.com/ljharb/js-traverse/commit/86d71a97241ff84b071a0ff4aed68a99919014ff) +- hash example, some() [`c7a133c`](https://github.com/ljharb/js-traverse/commit/c7a133cbb59d5fa9aedfe3958b9a0898fc5dea4c) +- key and value tests [`92212e5`](https://github.com/ljharb/js-traverse/commit/92212e55cfb1f16f68c14885d644125a83951589) +- copy instead of clone for merge [`4fcece2`](https://github.com/ljharb/js-traverse/commit/4fcece2de64fbe90ef0250f31f4f399a103ec7ed) + +## [v0.0.7](https://github.com/ljharb/js-traverse/compare/v0.0.6...v0.0.7) - 2010-08-26 + +### Commits + +- new hash lib and clone sugar [`586124c`](https://github.com/ljharb/js-traverse/commit/586124cebb2b613ee63d0c76a0d636058c5c9213) +- hash test for map [`393444a`](https://github.com/ljharb/js-traverse/commit/393444a2add24b9dba4f68385518b96a3900de33) +- a test for instances [`1adf75a`](https://github.com/ljharb/js-traverse/commit/1adf75a9cdc13b094b660f17bc496a94fd9576fd) +- new modules format for package.json, boost to 0.0.7 [`0f11600`](https://github.com/ljharb/js-traverse/commit/0f11600d5cfb67b50fb4f4f79dda522d17c9df4f) +- __proto__ trick to make instanceof work on cloned objects [`130a833`](https://github.com/ljharb/js-traverse/commit/130a833014477b7463cb8fbf4de246fd93f990a5) + +## [v0.0.6](https://github.com/ljharb/js-traverse/compare/v0.0.5...v0.0.6) - 2010-08-01 + +### Commits + +- magical webified version of traverse with require('dnode/web').source() [`0043cd6`](https://github.com/ljharb/js-traverse/commit/0043cd6b57327a0d1962b7378e9f6897d963e3c0) +- directories.lib, I forgot. Also scrub requires for later [`2a1f530`](https://github.com/ljharb/js-traverse/commit/2a1f5301601984b09a1746bd0b1699fb88a18264) + +## [v0.0.5](https://github.com/ljharb/js-traverse/compare/v0.0.4...v0.0.5) - 2010-07-28 + +### Commits + +- test for stupid .constructor() bug [`6b9d85d`](https://github.com/ljharb/js-traverse/commit/6b9d85dac5eedd3e043c63fe2cff4881c25f9f98) +- stupid traversal bug, version bump [`4cf36f3`](https://github.com/ljharb/js-traverse/commit/4cf36f3f987a71704064dd6ab6b695ddce0cac47) + +## [v0.0.4](https://github.com/ljharb/js-traverse/compare/v0.0.3...v0.0.4) - 2010-07-27 + +### Commits + +- now using expresso for test suite, json test written [`7d448da`](https://github.com/ljharb/js-traverse/commit/7d448daa7c93444b302095da394f8f47bf3fb61f) +- leaves and negative tests to go with the example, also s/tests/test/ [`13e19bf`](https://github.com/ljharb/js-traverse/commit/13e19bf5441abc903a270eb5abfc985d75a7507b) +- clone in the constructor so updates don't mess up the root object's refs [`fc5903b`](https://github.com/ljharb/js-traverse/commit/fc5903b3b008377d7f06e83ad3bce84957900c8c) +- readme updates for expresso tests and version bump to 0.0.4 [`6993515`](https://github.com/ljharb/js-traverse/commit/69935153c1b54afaee42c58c8e33f15d21f55efe) + +## [v0.0.3](https://github.com/ljharb/js-traverse/compare/v0.0.2...v0.0.3) - 2010-07-21 + +### Commits + +- backwards compatible update for var Traverse = require('traverse') style [`d0f50e9`](https://github.com/ljharb/js-traverse/commit/d0f50e9a6f428b68fc51e1c582148196deb9e209) + +## [v0.0.2](https://github.com/ljharb/js-traverse/compare/v0.0.1...v0.0.2) - 2010-07-14 + +### Commits + +- special check for null, for which typeof(null) == 'object' [`a4128c0`](https://github.com/ljharb/js-traverse/commit/a4128c01a666132b40c69d57d9176a33a1f5046c) +- installation in readme [`a6fc0d6`](https://github.com/ljharb/js-traverse/commit/a6fc0d641970984fefab29773a930f22c925eb91) +- add output to negative example [`590045e`](https://github.com/ljharb/js-traverse/commit/590045e3bc9daf8dbb884f59b3579bf57a7dc42d) +- license file [`519fd1f`](https://github.com/ljharb/js-traverse/commit/519fd1ff6d225d2465899d102519e93ef5334bba) +- s/127/128/ [`5fcb3f5`](https://github.com/ljharb/js-traverse/commit/5fcb3f5256207e392e9500db720aa2aeb3f85304) + +## v0.0.1 - 2010-07-08 + +### Commits + +- initial commit with forEach, modify, get, paths, nodes [`e73bba8`](https://github.com/ljharb/js-traverse/commit/e73bba81dbc8630a0ef6003fa3c12ceaafc4188d) +- more examples [`16bf66e`](https://github.com/ljharb/js-traverse/commit/16bf66e5cf5c537441a98001eae9368d4bae7317) +- readme with json example [`fa8265b`](https://github.com/ljharb/js-traverse/commit/fa8265badad1dfe3df5d1aa6e561a3698e4b1338) +- json example [`607de69`](https://github.com/ljharb/js-traverse/commit/607de691cd1bdeb0ced603d5177e3f855dc20417) +- leaf example [`23ccea5`](https://github.com/ljharb/js-traverse/commit/23ccea575ce9b6984fcd8bb64ccd7f9ee765c258) +- package.json file for version 0.0.1 [`c3266e0`](https://github.com/ljharb/js-traverse/commit/c3266e060d8b5ebfb6472385dba323c7e951fd14) +- npm doesn't like newlines in package.json strings [`6840d4e`](https://github.com/ljharb/js-traverse/commit/6840d4e7c75aaafeca6778a48600759641dfa7f1) diff --git a/node_modules/traverse/LICENSE b/node_modules/traverse/LICENSE new file mode 100644 index 0000000..7b75500 --- /dev/null +++ b/node_modules/traverse/LICENSE @@ -0,0 +1,24 @@ +Copyright 2010 James Halliday (mail@substack.net) + +This project is free software released under the MIT/X11 license: +http://www.opensource.org/licenses/mit-license.php + +Copyright 2010 James Halliday (mail@substack.net) + +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/traverse/README.md b/node_modules/traverse/README.md new file mode 100644 index 0000000..0bce518 --- /dev/null +++ b/node_modules/traverse/README.md @@ -0,0 +1,228 @@ +# traverse [![Version Badge][npm-version-svg]][package-url] + +[![github actions][actions-image]][actions-url] +[![coverage][codecov-image]][codecov-url] +[![License][license-image]][license-url] +[![Downloads][downloads-image]][downloads-url] + +[![npm badge][npm-badge-png]][package-url] + +Traverse and transform objects by visiting every node on a recursive walk. + +# examples + +## transform negative numbers in-place + +negative.js + +````javascript +var traverse = require('traverse'); +var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + +traverse(obj).forEach(function (x) { + if (x < 0) this.update(x + 128); +}); + +console.dir(obj); +```` + +Output: + + [ 5, 6, 125, [ 7, 8, 126, 1 ], { f: 10, g: 115 } ] + +## collect leaf nodes + +leaves.js + +````javascript +var traverse = require('traverse'); + +var obj = { + a : [1,2,3], + b : 4, + c : [5,6], + d : { e : [7,8], f : 9 }, +}; + +var leaves = traverse(obj).reduce(function (acc, x) { + if (this.isLeaf) acc.push(x); + return acc; +}, []); + +console.dir(leaves); +```` + +Output: + + [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ] + +## scrub circular references + +scrub.js: + +````javascript +var traverse = require('traverse'); + +var obj = { a : 1, b : 2, c : [ 3, 4 ] }; +obj.c.push(obj); + +var scrubbed = traverse(obj).map(function (x) { + if (this.circular) this.remove() +}); +console.dir(scrubbed); +```` + +output: + + { a: 1, b: 2, c: [ 3, 4 ] } + +# methods + +Each method that takes an `fn` uses the context documented below in the context +section. + +## .map(fn) + +Execute `fn` for each node in the object and return a new object with the +results of the walk. To update nodes in the result use `this.update(value)`. + +## .forEach(fn) + +Execute `fn` for each node in the object but unlike `.map()`, when +`this.update()` is called it updates the object in-place. + +## .reduce(fn, acc) + +For each node in the object, perform a +[left-fold](http://en.wikipedia.org/wiki/Fold_(higher-order_function)) +with the return value of `fn(acc, node)`. + +If `acc` isn't specified, `acc` is set to the root object for the first step +and the root element is skipped. + +## .paths() + +Return an `Array` of every possible non-cyclic path in the object. +Paths are `Array`s of string keys. + +## .nodes() + +Return an `Array` of every node in the object. + +## .clone() + +Create a deep clone of the object. + +## .get(path) + +Get the element at the array `path`. + +## .set(path, value) + +Set the element at the array `path` to `value`. + +## .has(path) + +Return whether the element at the array `path` exists. + +# context + +Each method that takes a callback has a context (its `this` object) with these +attributes: + +## this.node + +The present node on the recursive walk + +## this.path + +An array of string keys from the root to the present node + +## this.parent + +The context of the node's parent. +This is `undefined` for the root node. + +## this.key + +The name of the key of the present node in its parent. +This is `undefined` for the root node. + +## this.isRoot, this.notRoot + +Whether the present node is the root node + +## this.isLeaf, this.notLeaf + +Whether or not the present node is a leaf node (has no children) + +## this.level + +Depth of the node within the traversal + +## this.circular + +If the node equals one of its parents, the `circular` attribute is set to the +context of that parent and the traversal progresses no deeper. + +## this.update(value, stopHere=false) + +Set a new value for the present node. + +All the elements in `value` will be recursively traversed unless `stopHere` is +true. + +## this.remove(stopHere=false) + +Remove the current element from the output. If the node is in an Array it will +be spliced off. Otherwise it will be deleted from its parent. + +## this.delete(stopHere=false) + +Delete the current element from its parent in the output. Calls `delete` even on +Arrays. + +## this.before(fn) + +Call this function before any of the children are traversed. + +You can assign into `this.keys` here to traverse in a custom order. + +## this.after(fn) + +Call this function after any of the children are traversed. + +## this.pre(fn) + +Call this function before each of the children are traversed. + +## this.post(fn) + +Call this function after each of the children are traversed. + + +# install + +Using [npm](http://npmjs.org) do: + + $ npm install traverse + +# license + +MIT + +[package-url]: https://npmjs.org/package/traverse +[npm-version-svg]: https://versionbadg.es/ljharb/traverse.svg +[deps-svg]: https://david-dm.org/ljharb/traverse.svg +[deps-url]: https://david-dm.org/ljharb/traverse +[dev-deps-svg]: https://david-dm.org/ljharb/traverse/dev-status.svg +[dev-deps-url]: https://david-dm.org/ljharb/traverse#info=devDependencies +[npm-badge-png]: https://nodei.co/npm/traverse.png?downloads=true&stars=true +[license-image]: https://img.shields.io/npm/l/traverse.svg +[license-url]: LICENSE +[downloads-image]: https://img.shields.io/npm/dm/traverse.svg +[downloads-url]: https://npm-stat.com/charts.html?package=traverse +[codecov-image]: https://codecov.io/gh/ljharb/traverse/branch/main/graphs/badge.svg +[codecov-url]: https://app.codecov.io/gh/ljharb/traverse/ +[actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/ljharb/traverse +[actions-url]: https://github.com/ljharb/traverse/actions diff --git a/node_modules/traverse/examples/json.js b/node_modules/traverse/examples/json.js new file mode 100755 index 0000000..af71883 --- /dev/null +++ b/node_modules/traverse/examples/json.js @@ -0,0 +1,18 @@ +'use strict'; + +var traverse = require('traverse'); + +var id = 54; +var callbacks = {}; +var obj = { moo: function () {}, foo: [2, 3, 4, function () {}] }; + +var scrubbed = traverse(obj).map(function (x) { + if (typeof x === 'function') { + callbacks[id] = { id: id, f: x, path: this.path }; + this.update('[Function]'); + id++; + } +}); + +console.dir(scrubbed); +console.dir(callbacks); diff --git a/node_modules/traverse/examples/leaves.js b/node_modules/traverse/examples/leaves.js new file mode 100755 index 0000000..0bbd67a --- /dev/null +++ b/node_modules/traverse/examples/leaves.js @@ -0,0 +1,17 @@ +'use strict'; + +var traverse = require('traverse'); + +var obj = { + a: [1, 2, 3], + b: 4, + c: [5, 6], + d: { e: [7, 8], f: 9 }, +}; + +var leaves = traverse(obj).reduce(function (acc, x) { + if (this.isLeaf) { acc.push(x); } + return acc; +}, []); + +console.dir(leaves); diff --git a/node_modules/traverse/examples/negative.js b/node_modules/traverse/examples/negative.js new file mode 100755 index 0000000..9224fac --- /dev/null +++ b/node_modules/traverse/examples/negative.js @@ -0,0 +1,10 @@ +'use strict'; + +var traverse = require('traverse'); +var obj = [5, 6, -3, [7, 8, -2, 1], { f: 10, g: -13 }]; + +traverse(obj).forEach(function (x) { + if (x < 0) { this.update(x + 128); } +}); + +console.dir(obj); diff --git a/node_modules/traverse/examples/scrub.js b/node_modules/traverse/examples/scrub.js new file mode 100755 index 0000000..7a8d1e2 --- /dev/null +++ b/node_modules/traverse/examples/scrub.js @@ -0,0 +1,12 @@ +'use strict'; + +// scrub out circular references +var traverse = require('traverse'); + +var obj = { a: 1, b: 2, c: [3, 4] }; +obj.c.push(obj); + +var scrubbed = traverse(obj).map(function () { + if (this.circular) { this.remove(); } +}); +console.dir(scrubbed); diff --git a/node_modules/traverse/examples/stringify.js b/node_modules/traverse/examples/stringify.js new file mode 100755 index 0000000..2f6e14a --- /dev/null +++ b/node_modules/traverse/examples/stringify.js @@ -0,0 +1,37 @@ +#!/usr/bin/env node + +'use strict'; + +var traverse = require('traverse'); + +var obj = ['five', 6, -3, [7, 8, -2, 1], { f: 10, g: -13 }]; + +var s = ''; +traverse(obj).forEach(function toS(node) { + if (Array.isArray(node)) { + this.before(function () { s += '['; }); + this.post(function (child) { + if (!child.isLast) { s += ','; } + }); + this.after(function () { s += ']'; }); + } else if (typeof node === 'object') { + this.before(function () { s += '{'; }); + this.pre(function (x, key) { + toS(key); + s += ':'; + }); + this.post(function (child) { + if (!child.isLast) { s += ','; } + }); + this.after(function () { s += '}'; }); + } else if (typeof node === 'string') { + s += '"' + node.toString().replace(/"/g, '\\"') + '"'; + } else if (typeof node === 'function') { + s += 'null'; + } else { + s += node.toString(); + } +}); + +console.log('JSON.stringify: ' + JSON.stringify(obj)); +console.log('this stringify: ' + s); diff --git a/node_modules/traverse/index.js b/node_modules/traverse/index.js new file mode 100644 index 0000000..032d0c5 --- /dev/null +++ b/node_modules/traverse/index.js @@ -0,0 +1,311 @@ +'use strict'; + +// TODO: use call-bind, is-date, is-regex, is-string, is-boolean-object, is-number-object +function toS(obj) { return Object.prototype.toString.call(obj); } +function isDate(obj) { return toS(obj) === '[object Date]'; } +function isRegExp(obj) { return toS(obj) === '[object RegExp]'; } +function isError(obj) { return toS(obj) === '[object Error]'; } +function isBoolean(obj) { return toS(obj) === '[object Boolean]'; } +function isNumber(obj) { return toS(obj) === '[object Number]'; } +function isString(obj) { return toS(obj) === '[object String]'; } + +// TODO: use isarray +var isArray = Array.isArray || function isArray(xs) { + return Object.prototype.toString.call(xs) === '[object Array]'; +}; + +// TODO: use for-each? +function forEach(xs, fn) { + if (xs.forEach) { return xs.forEach(fn); } + for (var i = 0; i < xs.length; i++) { + fn(xs[i], i, xs); + } + return void undefined; +} + +// TODO: use object-keys +var objectKeys = Object.keys || function keys(obj) { + var res = []; + for (var key in obj) { res.push(key); } // eslint-disable-line no-restricted-syntax + return res; +}; + +// TODO: use object.hasown +var hasOwnProperty = Object.prototype.hasOwnProperty || function (obj, key) { + return key in obj; +}; + +function copy(src) { + if (typeof src === 'object' && src !== null) { + var dst; + + if (isArray(src)) { + dst = []; + } else if (isDate(src)) { + dst = new Date(src.getTime ? src.getTime() : src); + } else if (isRegExp(src)) { + dst = new RegExp(src); + } else if (isError(src)) { + dst = { message: src.message }; + } else if (isBoolean(src) || isNumber(src) || isString(src)) { + dst = Object(src); + } else if (Object.create && Object.getPrototypeOf) { + dst = Object.create(Object.getPrototypeOf(src)); + } else if (src.constructor === Object) { + dst = {}; + } else { + var proto = (src.constructor && src.constructor.prototype) + || src.__proto__ + || {}; + var T = function T() {}; // eslint-disable-line func-style, func-name-matching + T.prototype = proto; + dst = new T(); + } + + forEach(objectKeys(src), function (key) { + dst[key] = src[key]; + }); + return dst; + } + return src; +} + +function walk(root, cb, immutable) { + var path = []; + var parents = []; + var alive = true; + + return (function walker(node_) { + var node = immutable ? copy(node_) : node_; + var modifiers = {}; + + var keepGoing = true; + + var state = { + node: node, + node_: node_, + path: [].concat(path), + parent: parents[parents.length - 1], + parents: parents, + key: path[path.length - 1], + isRoot: path.length === 0, + level: path.length, + circular: null, + update: function (x, stopHere) { + if (!state.isRoot) { + state.parent.node[state.key] = x; + } + state.node = x; + if (stopHere) { keepGoing = false; } + }, + delete: function (stopHere) { + delete state.parent.node[state.key]; + if (stopHere) { keepGoing = false; } + }, + remove: function (stopHere) { + if (isArray(state.parent.node)) { + state.parent.node.splice(state.key, 1); + } else { + delete state.parent.node[state.key]; + } + if (stopHere) { keepGoing = false; } + }, + keys: null, + before: function (f) { modifiers.before = f; }, + after: function (f) { modifiers.after = f; }, + pre: function (f) { modifiers.pre = f; }, + post: function (f) { modifiers.post = f; }, + stop: function () { alive = false; }, + block: function () { keepGoing = false; }, + }; + + if (!alive) { return state; } + + function updateState() { + if (typeof state.node === 'object' && state.node !== null) { + if (!state.keys || state.node_ !== state.node) { + state.keys = objectKeys(state.node); + } + + state.isLeaf = state.keys.length === 0; + + for (var i = 0; i < parents.length; i++) { + if (parents[i].node_ === node_) { + state.circular = parents[i]; + break; // eslint-disable-line no-restricted-syntax + } + } + } else { + state.isLeaf = true; + state.keys = null; + } + + state.notLeaf = !state.isLeaf; + state.notRoot = !state.isRoot; + } + + updateState(); + + // use return values to update if defined + var ret = cb.call(state, state.node); + if (ret !== undefined && state.update) { state.update(ret); } + + if (modifiers.before) { modifiers.before.call(state, state.node); } + + if (!keepGoing) { return state; } + + if ( + typeof state.node === 'object' + && state.node !== null + && !state.circular + ) { + parents.push(state); + + updateState(); + + forEach(state.keys, function (key, i) { + path.push(key); + + if (modifiers.pre) { modifiers.pre.call(state, state.node[key], key); } + + var child = walker(state.node[key]); + if (immutable && hasOwnProperty.call(state.node, key)) { + state.node[key] = child.node; + } + + child.isLast = i === state.keys.length - 1; + child.isFirst = i === 0; + + if (modifiers.post) { modifiers.post.call(state, child); } + + path.pop(); + }); + parents.pop(); + } + + if (modifiers.after) { modifiers.after.call(state, state.node); } + + return state; + }(root)).node; +} + +function Traverse(obj) { + this.value = obj; +} + +Traverse.prototype.get = function (ps) { + var node = this.value; + for (var i = 0; i < ps.length; i++) { + var key = ps[i]; + if (!node || !hasOwnProperty.call(node, key)) { + return void undefined; + } + node = node[key]; + } + return node; +}; + +Traverse.prototype.has = function (ps) { + var node = this.value; + for (var i = 0; i < ps.length; i++) { + var key = ps[i]; + if (!node || !hasOwnProperty.call(node, key)) { + return false; + } + node = node[key]; + } + return true; +}; + +Traverse.prototype.set = function (ps, value) { + var node = this.value; + for (var i = 0; i < ps.length - 1; i++) { + var key = ps[i]; + if (!hasOwnProperty.call(node, key)) { node[key] = {}; } + node = node[key]; + } + node[ps[i]] = value; + return value; +}; + +Traverse.prototype.map = function (cb) { + return walk(this.value, cb, true); +}; + +Traverse.prototype.forEach = function (cb) { + this.value = walk(this.value, cb, false); + return this.value; +}; + +Traverse.prototype.reduce = function (cb, init) { + var skip = arguments.length === 1; + var acc = skip ? this.value : init; + this.forEach(function (x) { + if (!this.isRoot || !skip) { + acc = cb.call(this, acc, x); + } + }); + return acc; +}; + +Traverse.prototype.paths = function () { + var acc = []; + this.forEach(function () { + acc.push(this.path); + }); + return acc; +}; + +Traverse.prototype.nodes = function () { + var acc = []; + this.forEach(function () { + acc.push(this.node); + }); + return acc; +}; + +Traverse.prototype.clone = function () { + var parents = []; + var nodes = []; + + return (function clone(src) { + for (var i = 0; i < parents.length; i++) { + if (parents[i] === src) { + return nodes[i]; + } + } + + if (typeof src === 'object' && src !== null) { + var dst = copy(src); + + parents.push(src); + nodes.push(dst); + + forEach(objectKeys(src), function (key) { + dst[key] = clone(src[key]); + }); + + parents.pop(); + nodes.pop(); + return dst; + } + + return src; + + }(this.value)); +}; + +function traverse(obj) { + return new Traverse(obj); +} + +// TODO: replace with object.assign? +forEach(objectKeys(Traverse.prototype), function (key) { + traverse[key] = function (obj) { + var args = [].slice.call(arguments, 1); + var t = new Traverse(obj); + return t[key].apply(t, args); + }; +}); + +module.exports = traverse; diff --git a/node_modules/traverse/package.json b/node_modules/traverse/package.json new file mode 100644 index 0000000..bba353b --- /dev/null +++ b/node_modules/traverse/package.json @@ -0,0 +1,93 @@ +{ + "name": "traverse", + "version": "0.6.7", + "description": "traverse and transform objects by visiting every node on a recursive walk", + "main": "index.js", + "directories": { + "example": "example", + "test": "test" + }, + "devDependencies": { + "@ljharb/eslint-config": "^21.0.0", + "aud": "^2.0.1", + "auto-changelog": "^2.4.0", + "eslint": "=8.8.0", + "in-publish": "^2.0.1", + "npmignore": "^0.3.0", + "safe-publish-latest": "^2.0.0", + "tape": "^5.6.1" + }, + "scripts": { + "prepack": "npmignore --auto --commentLines=autogenerated", + "prepublishOnly": "safe-publish-latest", + "prepublish": "not-in-publish || npm run prepublishOnly", + "lint": "eslint --ext=js,mjs .", + "pretest": "npm run lint", + "tests-only": "tape 'test/**/*.js'", + "test": "npm run tests-only", + "posttest": "aud --production", + "version": "auto-changelog && git add CHANGELOG.md", + "postversion": "auto-changelog && git add CHANGELOG.md && git commit --no-edit --amend && git tag -f \"v$(node -e \"console.log(require('./package.json').version)\")\"" + }, + "testling": { + "files": "test/*.js", + "browsers": { + "iexplore": [ + "6.0", + "7.0", + "8.0", + "9.0" + ], + "chrome": [ + "10.0", + "20.0" + ], + "firefox": [ + "10.0", + "15.0" + ], + "safari": [ + "5.1" + ], + "opera": [ + "12.0" + ] + } + }, + "repository": { + "type": "git", + "url": "git://github.com/ljharb/js-traverse.git" + }, + "homepage": "https://github.com/ljharb/js-traverse", + "keywords": [ + "traverse", + "walk", + "recursive", + "map", + "forEach", + "deep", + "clone" + ], + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "http://substack.net" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + }, + "license": "MIT", + "auto-changelog": { + "output": "CHANGELOG.md", + "template": "keepachangelog", + "unreleased": false, + "commitLimit": false, + "backfillLimit": false, + "hideCredit": true + }, + "publishConfig": { + "ignore": [ + ".github/workflows" + ] + } +} diff --git a/node_modules/traverse/test/circular.js b/node_modules/traverse/test/circular.js new file mode 100644 index 0000000..89743cd --- /dev/null +++ b/node_modules/traverse/test/circular.js @@ -0,0 +1,118 @@ +'use strict'; + +var test = require('tape'); +var traverse = require('../'); +var deepEqual = require('./lib/deep_equal'); +var util = require('util'); + +test('circular', function (t) { + t.plan(1); + + var obj = { x: 3 }; + obj.y = obj; + traverse(obj).forEach(function () { + if (this.path.join('') === 'y') { + t.equal( + util.inspect(this.circular.node), + util.inspect(obj) + ); + } + }); +}); + +test('deepCirc', function (t) { + t.plan(2); + var obj = { x: [1, 2, 3], y: [4, 5] }; + obj.y[2] = obj; + + traverse(obj).forEach(function () { + if (this.circular) { + t.deepEqual(this.circular.path, []); + t.deepEqual(this.path, ['y', '2']); + } + }); +}); + +test('doubleCirc', function (t) { + var obj = { x: [1, 2, 3], y: [4, 5] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + var circs = []; + traverse(obj).forEach(function (x) { + if (this.circular) { + circs.push({ circ: this.circular, self: this, node: x }); + } + }); + + t.deepEqual(circs[0].self.path, ['x', '3', '2']); + t.deepEqual(circs[0].circ.path, []); + + t.deepEqual(circs[1].self.path, ['y', '2']); + t.deepEqual(circs[1].circ.path, []); + + t.deepEqual(circs.length, 2); + t.end(); +}); + +test('circDubForEach', function (t) { + var obj = { x: [1, 2, 3], y: [4, 5] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + traverse(obj).forEach(function () { + if (this.circular) { this.update('...'); } + }); + + t.same(obj, { x: [1, 2, 3, [4, 5, '...']], y: [4, 5, '...'] }); + t.end(); +}); + +test('circDubMap', function (t) { + var obj = { x: [1, 2, 3], y: [4, 5] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + var c = traverse(obj).map(function () { + if (this.circular) { + this.update('...'); + } + }); + + t.same(c, { x: [1, 2, 3, [4, 5, '...']], y: [4, 5, '...'] }); + t.end(); +}); + +test('circClone', function (t) { + var obj = { x: [1, 2, 3], y: [4, 5] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + var clone = traverse.clone(obj); + t.ok(obj !== clone); + + t.ok(clone.y[2] === clone); + t.ok(clone.y[2] !== obj); + t.ok(clone.x[3][2] === clone); + t.ok(clone.x[3][2] !== obj); + t.same(clone.x.slice(0, 3), [1, 2, 3]); + t.same(clone.y.slice(0, 2), [4, 5]); + t.end(); +}); + +test('circMapScrub', function (t) { + var obj = { a: 1, b: 2 }; + obj.c = obj; + + var scrubbed = traverse(obj).map(function () { + if (this.circular) { this.remove(); } + }); + t.same( + Object.keys(scrubbed).sort(), + ['a', 'b'] + ); + t.ok(deepEqual(scrubbed, { a: 1, b: 2 })); + + t.equal(obj.c, obj); + t.end(); +}); diff --git a/node_modules/traverse/test/date.js b/node_modules/traverse/test/date.js new file mode 100644 index 0000000..2df5a5f --- /dev/null +++ b/node_modules/traverse/test/date.js @@ -0,0 +1,39 @@ +'use strict'; + +var test = require('tape'); +var traverse = require('../'); + +test('dateEach', function (t) { + var obj = { x: new Date(), y: 10, z: 5 }; + + var counts = {}; + + traverse(obj).forEach(function (node) { + var type = (node instanceof Date && 'Date') || typeof node; + counts[type] = (counts[type] || 0) + 1; + }); + + t.same(counts, { + object: 1, + Date: 1, + number: 2, + }); + t.end(); +}); + +test('dateMap', function (t) { + var obj = { x: new Date(), y: 10, z: 5 }; + + var res = traverse(obj).map(function (node) { + if (typeof node === 'number') { this.update(node + 100); } + }); + + t.ok(obj.x !== res.x); + t.same(res, { + x: obj.x, + y: 110, + z: 105, + }); + t.end(); +}); + diff --git a/node_modules/traverse/test/equal.js b/node_modules/traverse/test/equal.js new file mode 100644 index 0000000..3413143 --- /dev/null +++ b/node_modules/traverse/test/equal.js @@ -0,0 +1,238 @@ +'use strict'; + +var test = require('tape'); +var deepEqual = require('./lib/deep_equal'); + +test('deepDates', function (t) { + t.plan(2); + + t.ok( + deepEqual( + { d: new Date(), x: [1, 2, 3] }, + { d: new Date(), x: [1, 2, 3] } + ), + 'dates should be equal' + ); + + var d0 = new Date(); + setTimeout(function () { + t.ok( + !deepEqual( + { d: d0, x: [1, 2, 3] }, + { d: new Date(), x: [1, 2, 3] } + ), + 'microseconds should count in date equality' + ); + }, 5); +}); + +test('deepCircular', function (t) { + var a = [1]; + a.push(a); // a = [ 1, *a ] + + var b = [1]; + b.push(a); // b = [ 1, [ 1, *a ] ] + + t.ok( + !deepEqual(a, b), + 'circular ref mount points count towards equality' + ); + + var c = [1]; + c.push(c); // c = [ 1, *c ] + t.ok( + deepEqual(a, c), + 'circular refs are structurally the same here' + ); + + var d = [1]; + d.push(a); // c = [ 1, [ 1, *d ] ] + t.ok( + deepEqual(b, d), + 'non-root circular ref structural comparison' + ); + + t.end(); +}); + +test('deepInstances', function (t) { + t.ok( + !deepEqual([Object(false)], [false]), + 'boolean instances are not real booleans' + ); + + t.ok( + !deepEqual([Object('x')], ['x']), + 'string instances are not real strings' + ); + + t.ok( + !deepEqual([Object(4)], [4]), + 'number instances are not real numbers' + ); + + t.ok( + deepEqual([new RegExp('x')], [/x/]), + 'regexp instances are real regexps' + ); + + t.ok( + !deepEqual([new RegExp(/./)], [/../]), + 'these regexps aren\'t the same' + ); + + t.ok( + !deepEqual( + [function (x) { return x * 2; }], + [function (x) { return x * 2; }] + ), + 'functions with the same .toString() aren\'t necessarily the same' + ); + + function f(x) { return x * 2; } + t.ok( + deepEqual([f], [f]), + 'these functions are actually equal' + ); + + t.end(); +}); + +test('deepEqual', function (t) { + t.ok( + !deepEqual([1, 2, 3], { 0: 1, 1: 2, 2: 3 }), + 'arrays are not objects' + ); + t.end(); +}); + +test('falsy', function (t) { + t.ok( + !deepEqual([undefined], [null]), + 'null is not undefined!' + ); + + t.ok( + !deepEqual([null], [undefined]), + 'undefined is not null!' + ); + + t.ok( + !deepEqual( + { a: 1, b: 2, c: [3, undefined, 5] }, + { a: 1, b: 2, c: [3, null, 5] } + ), + 'undefined is not null, however deeply!' + ); + + t.ok( + !deepEqual( + { a: 1, b: 2, c: [3, undefined, 5] }, + { a: 1, b: 2, c: [3, null, 5] } + ), + 'null is not undefined, however deeply!' + ); + + t.ok( + !deepEqual( + { a: 1, b: 2, c: [3, undefined, 5] }, + { a: 1, b: 2, c: [3, null, 5] } + ), + 'null is not undefined, however deeply!' + ); + + t.end(); +}); + +test('deletedArrayEqual', function (t) { + var xs = [1, 2, 3, 4]; + delete xs[2]; + + var ys = Object.create(Array.prototype); + ys[0] = 1; + ys[1] = 2; + ys[3] = 4; + + t.ok( + deepEqual(xs, ys), + 'arrays with deleted elements are only equal to arrays with similarly deleted elements' + ); + + t.ok( + !deepEqual(xs, [1, 2, undefined, 4]), + 'deleted array elements cannot be undefined' + ); + + t.ok( + !deepEqual(xs, [1, 2, null, 4]), + 'deleted array elements cannot be null' + ); + + t.end(); +}); + +test('deletedObjectEqual', function (t) { + var obj = { a: 1, b: 2, c: 3 }; + delete obj.c; + + t.ok( + deepEqual(obj, { a: 1, b: 2 }), + 'deleted object elements should not show up' + ); + + t.ok( + !deepEqual(obj, { a: 1, b: 2, c: undefined }), + 'deleted object elements are not undefined' + ); + + t.ok( + !deepEqual(obj, { a: 1, b: 2, c: null }), + 'deleted object elements are not null' + ); + + t.end(); +}); + +test('emptyKeyEqual', function (t) { + t.ok(!deepEqual({ a: 1 }, { a: 1, '': 55 })); + + t.end(); +}); + +test('deepArguments', function (t) { + t.ok( + !deepEqual( + [4, 5, 6], + (function () { return arguments; }(4, 5, 6)) + ), + 'arguments are not arrays' + ); + + t.ok( + deepEqual( + (function () { return arguments; }(4, 5, 6)), + (function () { return arguments; }(4, 5, 6)) + ), + 'arguments should equal' + ); + + t.end(); +}); + +test('deepUn', function (t) { + t.ok(!deepEqual({ a: 1, b: 2 }, undefined)); + t.ok(!deepEqual({ a: 1, b: 2 }, {})); + t.ok(!deepEqual(undefined, { a: 1, b: 2 })); + t.ok(!deepEqual({}, { a: 1, b: 2 })); + t.ok(deepEqual(undefined, undefined)); + t.ok(deepEqual(null, null)); + t.ok(!deepEqual(undefined, null)); + + t.end(); +}); + +test('deepLevels', function (t) { + var xs = [1, 2, [3, 4, [5, 6]]]; + t.ok(!deepEqual(xs, [])); + t.end(); +}); diff --git a/node_modules/traverse/test/error.js b/node_modules/traverse/test/error.js new file mode 100644 index 0000000..8c4aca1 --- /dev/null +++ b/node_modules/traverse/test/error.js @@ -0,0 +1,13 @@ +'use strict'; + +var test = require('tape'); +var traverse = require('../'); + +test('traverse an Error', function (t) { + var obj = new Error('test'); + var results = traverse(obj).map(function () {}); + t.same(results, { message: 'test' }); + + t.end(); +}); + diff --git a/node_modules/traverse/test/has.js b/node_modules/traverse/test/has.js new file mode 100644 index 0000000..e29fb51 --- /dev/null +++ b/node_modules/traverse/test/has.js @@ -0,0 +1,17 @@ +'use strict'; + +var test = require('tape'); +var traverse = require('../'); + +test('has', function (t) { + var obj = { a: 2, b: [4, 5, { c: 6 }] }; + + t.equal(traverse(obj).has(['b', 2, 'c']), true); + t.equal(traverse(obj).has(['b', 2, 'c', 0]), false); + t.equal(traverse(obj).has(['b', 2, 'd']), false); + t.equal(traverse(obj).has([]), true); + t.equal(traverse(obj).has(['a']), true); + t.equal(traverse(obj).has(['a', 2]), false); + + t.end(); +}); diff --git a/node_modules/traverse/test/instance.js b/node_modules/traverse/test/instance.js new file mode 100644 index 0000000..b181b26 --- /dev/null +++ b/node_modules/traverse/test/instance.js @@ -0,0 +1,17 @@ +'use strict'; + +var test = require('tape'); +var traverse = require('../'); +var EventEmitter = require('events').EventEmitter; + +test('check instanceof on node elems', function (t) { + var counts = { emitter: 0 }; + + traverse([new EventEmitter(), 3, 4, { ev: new EventEmitter() }]) + .forEach(function (node) { + if (node instanceof EventEmitter) { counts.emitter += 1; } + }); + t.equal(counts.emitter, 2); + + t.end(); +}); diff --git a/node_modules/traverse/test/interface.js b/node_modules/traverse/test/interface.js new file mode 100644 index 0000000..02735b9 --- /dev/null +++ b/node_modules/traverse/test/interface.js @@ -0,0 +1,46 @@ +'use strict'; + +var test = require('tape'); +var traverse = require('../'); + +test('interface map', function (t) { + var obj = { a: [5, 6, 7], b: { c: [8] } }; + + t.same( + traverse.paths(obj) + .sort() + .map(function (path) { return path.join('/'); }) + .slice(1) + .join(' ') + , + 'a a/0 a/1 a/2 b b/c b/c/0' + ); + + t.same( + traverse.nodes(obj), + [ + { a: [5, 6, 7], b: { c: [8] } }, + [5, 6, 7], 5, 6, 7, + { c: [8] }, [8], 8, + ] + ); + + t.same( + traverse.map(obj, function (node) { + if (typeof node === 'number') { + return node + 1000; + } + if (Array.isArray(node)) { + return node.join(' '); + } + return void undefined; + }), + { a: '5 6 7', b: { c: '8' } } + ); + + var nodes = 0; + traverse.forEach(obj, function () { nodes += 1; }); + t.equal(nodes, 8); + + t.end(); +}); diff --git a/node_modules/traverse/test/json.js b/node_modules/traverse/test/json.js new file mode 100644 index 0000000..244a444 --- /dev/null +++ b/node_modules/traverse/test/json.js @@ -0,0 +1,55 @@ +'use strict'; + +var test = require('tape'); +var traverse = require('../'); + +test('json test', function (t) { + var id = 54; + var callbacks = {}; + var obj = { moo: function () {}, foo: [2, 3, 4, function () {}] }; + + var scrubbed = traverse(obj).map(function (x) { + if (typeof x === 'function') { + callbacks[id] = { id: id, f: x, path: this.path }; + this.update('[Function]'); + id += 1; + } + }); + + t.equal( + scrubbed.moo, + '[Function]', + 'obj.moo replaced with "[Function]"' + ); + + t.equal( + scrubbed.foo[3], + '[Function]', + 'obj.foo[3] replaced with "[Function]"' + ); + + t.same(scrubbed, { + moo: '[Function]', + foo: [2, 3, 4, '[Function]'], + }, 'Full JSON string matches'); + + t.same( + typeof obj.moo, + 'function', + 'Original obj.moo still a function' + ); + + t.same( + typeof obj.foo[3], + 'function', + 'Original obj.foo[3] still a function' + ); + + t.same(callbacks, { + 54: { id: 54, f: obj.moo, path: ['moo'] }, + 55: { id: 55, f: obj.foo[3], path: ['foo', '3'] }, + }, 'Check the generated callbacks list'); + + t.end(); +}); + diff --git a/node_modules/traverse/test/keys.js b/node_modules/traverse/test/keys.js new file mode 100644 index 0000000..6544eb9 --- /dev/null +++ b/node_modules/traverse/test/keys.js @@ -0,0 +1,33 @@ +'use strict'; + +var test = require('tape'); +var traverse = require('../'); + +test('sort test', function (t) { + var acc = []; + traverse({ + a: 30, + b: 22, + id: 9, + }).forEach(function (node) { + if (!Array.isArray(node) && typeof node === 'object') { + this.before(function (beforeNode) { + this.keys = Object.keys(beforeNode); + this.keys.sort(function (a, b) { + var aA = [a === 'id' ? 0 : 1, a]; + var bA = [b === 'id' ? 0 : 1, b]; + return aA < bA ? -1 : aA > bA ? 1 : 0; + }); + }); + } + if (this.isLeaf) { acc.push(node); } + }); + + t.equal( + acc.join(' '), + '9 30 22', + 'Traversal in a custom order' + ); + + t.end(); +}); diff --git a/node_modules/traverse/test/leaves.js b/node_modules/traverse/test/leaves.js new file mode 100644 index 0000000..d598499 --- /dev/null +++ b/node_modules/traverse/test/leaves.js @@ -0,0 +1,24 @@ +'use strict'; + +var test = require('tape'); +var traverse = require('../'); + +test('leaves test', function (t) { + var acc = []; + traverse({ + a: [1, 2, 3], + b: 4, + c: [5, 6], + d: { e: [7, 8], f: 9 }, + }).forEach(function (x) { + if (this.isLeaf) { acc.push(x); } + }); + + t.equal( + acc.join(' '), + '1 2 3 4 5 6 7 8 9', + 'Traversal in the right(?) order' + ); + + t.end(); +}); diff --git a/node_modules/traverse/test/lib/deep_equal.js b/node_modules/traverse/test/lib/deep_equal.js new file mode 100644 index 0000000..46d5af0 --- /dev/null +++ b/node_modules/traverse/test/lib/deep_equal.js @@ -0,0 +1,87 @@ +'use strict'; + +var traverse = require('../../'); + +function toS(o) { + return Object.prototype.toString.call(o); +} + +module.exports = function (a, b) { + if (arguments.length !== 2) { + throw new Error('deepEqual requires exactly two objects to compare against'); + } + + var equal = true; + function notEqual() { + equal = false; + // this.stop(); + return undefined; + } + + var node = b; + + traverse(a).forEach(function (y) { // eslint-disable-line consistent-return + + // if (node === undefined || node === null) return notEqual(); + + if (!this.isRoot) { + /* + if (!Object.hasOwnProperty.call(node, this.key)) { + return notEqual(); + } + */ + if (typeof node !== 'object') { return notEqual(); } + node = node[this.key]; + } + + var x = node; + + this.post(function () { + node = x; + }); + + if (this.circular) { + if (traverse(b).get(this.circular.path) !== x) { notEqual(); } + } else if (typeof x !== typeof y) { + notEqual(); + } else if (x === null || y === null || x === undefined || y === undefined) { + if (x !== y) { notEqual(); } + } else if (x.__proto__ !== y.__proto__) { + notEqual(); + } else if (x === y) { + // nop + } else if (typeof x === 'function') { + if (x instanceof RegExp) { + // both regexps on account of the __proto__ check + if (String(x) !== String(y)) { notEqual(); } + } else if (x !== y) { notEqual(); } + } else if (typeof x === 'object') { + if (toS(y) === '[object Arguments]' + || toS(x) === '[object Arguments]') { + if (toS(x) !== toS(y)) { + notEqual(); + } + } else if (toS(y) === '[object RegExp]' + || toS(x) === '[object RegExp]') { + if (!x || !y || x.toString() !== y.toString()) { notEqual(); } + } else if (x instanceof Date || y instanceof Date) { + if (!(x instanceof Date) || !(y instanceof Date) + || x.getTime() !== y.getTime()) { + notEqual(); + } + } else { + var kx = Object.keys(x); + var ky = Object.keys(y); + if (kx.length !== ky.length) { return notEqual(); } + for (var i = 0; i < kx.length; i++) { + var k = kx[i]; + if (!Object.hasOwnProperty.call(y, k)) { + notEqual(); + } + } + } + } + }); + + return equal; +}; diff --git a/node_modules/traverse/test/mutability.js b/node_modules/traverse/test/mutability.js new file mode 100644 index 0000000..dc5d6f4 --- /dev/null +++ b/node_modules/traverse/test/mutability.js @@ -0,0 +1,276 @@ +'use strict'; + +var test = require('tape'); +var assert = require('assert'); +var traverse = require('../'); +var deepEqual = require('./lib/deep_equal'); + +test('mutate', function (t) { + var obj = { a: 1, b: 2, c: [3, 4] }; + var res = traverse(obj).forEach(function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + t.same(obj, res); + t.same(obj, { a: 1, b: 20, c: [3, 40] }); + t.end(); +}); + +test('mutateT', function (t) { + var obj = { a: 1, b: 2, c: [3, 4] }; + var res = traverse.forEach(obj, function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + t.same(obj, res); + t.same(obj, { a: 1, b: 20, c: [3, 40] }); + t.end(); +}); + +test('map', function (t) { + var obj = { a: 1, b: 2, c: [3, 4] }; + var res = traverse(obj).map(function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + t.same(obj, { a: 1, b: 2, c: [3, 4] }); + t.same(res, { a: 1, b: 20, c: [3, 40] }); + t.end(); +}); + +test('mapT', function (t) { + var obj = { a: 1, b: 2, c: [3, 4] }; + var res = traverse.map(obj, function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + t.same(obj, { a: 1, b: 2, c: [3, 4] }); + t.same(res, { a: 1, b: 20, c: [3, 40] }); + t.end(); +}); + +test('clone', function (t) { + var obj = { a: 1, b: 2, c: [3, 4] }; + var res = traverse(obj).clone(); + t.same(obj, res); + t.ok(obj !== res); + obj.a += 1; + t.same(res.a, 1); + obj.c.push(5); + t.same(res.c, [3, 4]); + t.end(); +}); + +test('cloneT', function (t) { + var obj = { a: 1, b: 2, c: [3, 4] }; + var res = traverse.clone(obj); + t.same(obj, res); + t.ok(obj !== res); + obj.a += 1; + t.same(res.a, 1); + obj.c.push(5); + t.same(res.c, [3, 4]); + t.end(); +}); + +test('reduce', function (t) { + var obj = { a: 1, b: 2, c: [3, 4] }; + var res = traverse(obj).reduce(function (acc, x) { + if (this.isLeaf) { acc.push(x); } + return acc; + }, []); + t.same(obj, { a: 1, b: 2, c: [3, 4] }); + t.same(res, [1, 2, 3, 4]); + t.end(); +}); + +test('reduceInit', function (t) { + var obj = { a: 1, b: 2, c: [3, 4] }; + var res = traverse(obj).reduce(function (acc) { + if (this.isRoot) { assert.fail('got root'); } + return acc; + }); + t.same(obj, { a: 1, b: 2, c: [3, 4] }); + t.same(res, obj); + t.end(); +}); + +test('remove', function (t) { + var obj = { a: 1, b: 2, c: [3, 4] }; + traverse(obj).forEach(function (x) { + if (this.isLeaf && x % 2 === 0) { this.remove(); } + }); + + t.same(obj, { a: 1, c: [3] }); + t.end(); +}); + +test('removeNoStop', function (t) { + var obj = { a: 1, b: 2, c: { d: 3, e: 4 }, f: 5 }; + + var keys = []; + traverse(obj).forEach(function () { + keys.push(this.key); + if (this.key === 'c') { this.remove(); } + }); + + t.same(keys, [undefined, 'a', 'b', 'c', 'd', 'e', 'f']); + t.end(); +}); + +test('removeStop', function (t) { + var obj = { a: 1, b: 2, c: { d: 3, e: 4 }, f: 5 }; + + var keys = []; + traverse(obj).forEach(function () { + keys.push(this.key); + if (this.key === 'c') { this.remove(true); } + }); + + t.same(keys, [undefined, 'a', 'b', 'c', 'f']); + t.end(); +}); + +test('removeMap', function (t) { + var obj = { a: 1, b: 2, c: [3, 4] }; + var res = traverse(obj).map(function (x) { + if (this.isLeaf && x % 2 === 0) { this.remove(); } + }); + + t.same(obj, { a: 1, b: 2, c: [3, 4] }); + t.same(res, { a: 1, c: [3] }); + t.end(); +}); + +test('delete', function (t) { + var obj = { a: 1, b: 2, c: [3, 4] }; + traverse(obj).forEach(function (x) { + if (this.isLeaf && x % 2 === 0) { this.delete(); } + }); + + t.ok(!deepEqual(obj, { a: 1, c: [3, undefined] })); + + t.ok(deepEqual(obj, { a: 1, c: [3] })); + + t.ok(!deepEqual(obj, { a: 1, c: [3, null] })); + t.end(); +}); + +test('deleteNoStop', function (t) { + var obj = { a: 1, b: 2, c: { d: 3, e: 4 } }; + + var keys = []; + traverse(obj).forEach(function () { + keys.push(this.key); + if (this.key === 'c') { this.delete(); } + }); + + t.same(keys, [undefined, 'a', 'b', 'c', 'd', 'e']); + t.end(); +}); + +test('deleteStop', function (t) { + var obj = { a: 1, b: 2, c: { d: 3, e: 4 } }; + + var keys = []; + traverse(obj).forEach(function () { + keys.push(this.key); + if (this.key === 'c') { this.delete(true); } + }); + + t.same(keys, [undefined, 'a', 'b', 'c']); + t.end(); +}); + +test('deleteRedux', function (t) { + var obj = { a: 1, b: 2, c: [3, 4, 5] }; + traverse(obj).forEach(function (x) { + if (this.isLeaf && x % 2 === 0) { this.delete(); } + }); + + t.ok(!deepEqual(obj, { a: 1, c: [3, undefined, 5] })); + + t.ok(deepEqual(obj, { a: 1, c: [3,, 5] })); + + t.ok(!deepEqual(obj, { a: 1, c: [3, null, 5] })); + + t.ok(!deepEqual(obj, { a: 1, c: [3, 5] })); + + t.end(); +}); + +test('deleteMap', function (t) { + var obj = { a: 1, b: 2, c: [3, 4] }; + var res = traverse(obj).map(function (x) { + if (this.isLeaf && x % 2 === 0) { this.delete(); } + }); + + t.ok(deepEqual( + obj, + { a: 1, b: 2, c: [3, 4] } + )); + + var xs = [3, 4]; + delete xs[1]; + + t.ok(deepEqual(res, { a: 1, c: xs })); + + t.ok(deepEqual(res, { a: 1, c: [3,,] })); // eslint-disable-line comma-spacing + + t.ok(deepEqual(res, { a: 1, c: [3] })); + + t.end(); +}); + +test('deleteMapRedux', function (t) { + var obj = { a: 1, b: 2, c: [3, 4, 5] }; + var res = traverse(obj).map(function (x) { + if (this.isLeaf && x % 2 === 0) { this.delete(); } + }); + + t.ok(deepEqual( + obj, + { a: 1, b: 2, c: [3, 4, 5] } + )); + + var xs = [3, 4, 5]; + delete xs[1]; + + t.ok(deepEqual(res, { a: 1, c: xs })); + + t.ok(!deepEqual(res, { a: 1, c: [3, 5] })); + + t.ok(deepEqual(res, { a: 1, c: [3,, 5] })); + + t.end(); +}); + +test('objectToString', function (t) { + var obj = { a: 1, b: 2, c: [3, 4] }; + var res = traverse(obj).forEach(function (x) { + if (typeof x === 'object' && !this.isRoot) { + this.update(JSON.stringify(x)); + } + }); + t.same(obj, res); + t.same(obj, { a: 1, b: 2, c: '[3,4]' }); + t.end(); +}); + +test('stringToObject', function (t) { + var obj = { a: 1, b: 2, c: '[3,4]' }; + var res = traverse(obj).forEach(function (x) { + if (typeof x === 'string') { + this.update(JSON.parse(x)); + } else if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + t.deepEqual(obj, res); + t.deepEqual(obj, { a: 1, b: 20, c: [3, 40] }); + t.end(); +}); diff --git a/node_modules/traverse/test/negative.js b/node_modules/traverse/test/negative.js new file mode 100644 index 0000000..b3806c4 --- /dev/null +++ b/node_modules/traverse/test/negative.js @@ -0,0 +1,25 @@ +'use strict'; + +var traverse = require('../'); +var test = require('tape'); + +test('negative update test', function (t) { + var obj = [5, 6, -3, [7, 8, -2, 1], { f: 10, g: -13 }]; + var fixed = traverse.map(obj, function (x) { + if (x < 0) { this.update(x + 128); } + }); + + t.same( + fixed, + [5, 6, 125, [7, 8, 126, 1], { f: 10, g: 115 }], + 'Negative values += 128' + ); + + t.same( + obj, + [5, 6, -3, [7, 8, -2, 1], { f: 10, g: -13 }], + 'Original references not modified' + ); + + t.end(); +}); diff --git a/node_modules/traverse/test/obj.js b/node_modules/traverse/test/obj.js new file mode 100644 index 0000000..fa3daea --- /dev/null +++ b/node_modules/traverse/test/obj.js @@ -0,0 +1,13 @@ +'use strict'; + +var test = require('tape'); +var traverse = require('../'); + +test('traverse an object with nested functions', function (t) { + t.plan(1); + + function Cons(x) { + t.equal(x, 10); + } + traverse(new Cons(10)); +}); diff --git a/node_modules/traverse/test/siblings.js b/node_modules/traverse/test/siblings.js new file mode 100644 index 0000000..049632e --- /dev/null +++ b/node_modules/traverse/test/siblings.js @@ -0,0 +1,39 @@ +'use strict'; + +var test = require('tape'); +var traverse = require('../'); + +test('siblings', function (t) { + var obj = { a: 1, b: 2, c: [4, 5, 6] }; + + var res = traverse(obj).reduce(function (acc) { + /* eslint no-param-reassign: 0 */ + var p = '/' + this.path.join('/'); + if (this.parent) { + acc[p] = { + siblings: this.parent.keys, + key: this.key, + index: this.parent.keys.indexOf(this.key), + }; + } else { + acc[p] = { + siblings: [], + key: this.key, + index: -1, + }; + } + return acc; + }, {}); + + t.same(res, { + '/': { siblings: [], key: undefined, index: -1 }, + '/a': { siblings: ['a', 'b', 'c'], key: 'a', index: 0 }, + '/b': { siblings: ['a', 'b', 'c'], key: 'b', index: 1 }, + '/c': { siblings: ['a', 'b', 'c'], key: 'c', index: 2 }, + '/c/0': { siblings: ['0', '1', '2'], key: '0', index: 0 }, + '/c/1': { siblings: ['0', '1', '2'], key: '1', index: 1 }, + '/c/2': { siblings: ['0', '1', '2'], key: '2', index: 2 }, + }); + + t.end(); +}); diff --git a/node_modules/traverse/test/stop.js b/node_modules/traverse/test/stop.js new file mode 100644 index 0000000..86fc128 --- /dev/null +++ b/node_modules/traverse/test/stop.js @@ -0,0 +1,46 @@ +'use strict'; + +var test = require('tape'); +var traverse = require('../'); + +test('stop', function (t) { + var visits = 0; + traverse('abcdefghij'.split('')).forEach(function (node) { + if (typeof node === 'string') { + visits += 1; + if (node === 'e') { this.stop(); } + } + }); + + t.equal(visits, 5); + t.end(); +}); + +test('stopMap', function (t) { + var s = traverse('abcdefghij'.split('')).map(function (node) { + if (typeof node === 'string') { + if (node === 'e') { this.stop(); } + return node.toUpperCase(); + } + return void undefined; + }).join(''); + + t.equal(s, 'ABCDEfghij'); + t.end(); +}); + +test('stopReduce', function (t) { + var obj = { + a: [4, 5], + b: [6, [7, 8, 9]], + }; + var xs = traverse(obj).reduce(function (acc, node) { + if (this.isLeaf) { + if (node === 7) { this.stop(); } else { acc.push(node); } + } + return acc; + }, []); + + t.same(xs, [4, 5, 6]); + t.end(); +}); diff --git a/node_modules/traverse/test/stringify.js b/node_modules/traverse/test/stringify.js new file mode 100644 index 0000000..e7bf65d --- /dev/null +++ b/node_modules/traverse/test/stringify.js @@ -0,0 +1,35 @@ +'use strict'; + +var test = require('tape'); +var traverse = require('../'); + +test('stringify', function (t) { + var obj = [5, 6, -3, [7, 8, -2, 1], { f: 10, g: -13 }]; + + var s = ''; + traverse(obj).forEach(function (node) { + if (Array.isArray(node)) { + this.before(function () { s += '['; }); + this.post(function (child) { + if (!child.isLast) { s += ','; } + }); + this.after(function () { s += ']'; }); + } else if (typeof node === 'object') { + this.before(function () { s += '{'; }); + this.pre(function (x, key) { + s += '"' + key + '":'; + }); + this.post(function (child) { + if (!child.isLast) { s += ','; } + }); + this.after(function () { s += '}'; }); + } else if (typeof node === 'function') { + s += 'null'; + } else { + s += node.toString(); + } + }); + + t.equal(s, JSON.stringify(obj)); + t.end(); +}); diff --git a/node_modules/traverse/test/subexpr.js b/node_modules/traverse/test/subexpr.js new file mode 100644 index 0000000..6aeba05 --- /dev/null +++ b/node_modules/traverse/test/subexpr.js @@ -0,0 +1,41 @@ +'use strict'; + +var traverse = require('../'); +var test = require('tape'); + +test('subexpr', function (t) { + var obj = ['a', 4, 'b', 5, 'c', 6]; + var r = traverse(obj).map(function (x) { + if (typeof x === 'number') { + this.update([x - 0.1, x, x + 0.1], true); + } + }); + + t.same(obj, ['a', 4, 'b', 5, 'c', 6]); + t.same(r, [ + 'a', [3.9, 4, 4.1], + 'b', [4.9, 5, 5.1], + 'c', [5.9, 6, 6.1], + ]); + t.end(); +}); + +test('block', function (t) { + var obj = [[1], [2], [3]]; + var r = traverse(obj).map(function (x) { + if (Array.isArray(x) && !this.isRoot) { + if (x[0] === 5) { + this.block(); + } else { + this.update([[x[0] + 1]]); + } + } + }); + + t.same(r, [ + [[[[[5]]]]], + [[[[5]]]], + [[[5]]], + ]); + t.end(); +}); diff --git a/node_modules/traverse/test/super_deep.js b/node_modules/traverse/test/super_deep.js new file mode 100644 index 0000000..f7fd971 --- /dev/null +++ b/node_modules/traverse/test/super_deep.js @@ -0,0 +1,56 @@ +'use strict'; + +var test = require('tape'); +var deepEqual = require('./lib/deep_equal'); + +function make() { + var a = { self: 'a' }; + var b = { self: 'b' }; + var c = { self: 'c' }; + var d = { self: 'd' }; + var e = { self: 'e' }; + + a.a = a; + a.b = b; + a.c = c; + + b.a = a; + b.b = b; + b.c = c; + + c.a = a; + c.b = b; + c.c = c; + c.d = d; + + d.a = a; + d.b = b; + d.c = c; + d.d = d; + d.e = e; + + e.a = a; + e.b = b; + e.c = c; + e.d = d; + e.e = e; + + return a; +} + +test('super_deep', function (t) { + var a0 = make(); + var a1 = make(); + t.ok(deepEqual(a0, a1)); + + a0.c.d.moo = true; + t.ok(!deepEqual(a0, a1)); + + a1.c.d.moo = true; + t.ok(deepEqual(a0, a1)); + + // TODO: this one + // a0.c.a = a1; + // t.ok(!deepEqual(a0, a1)); + t.end(); +}); diff --git a/node_modules/uglify-js/.npmignore b/node_modules/uglify-js/.npmignore new file mode 100644 index 0000000..d97eaa0 --- /dev/null +++ b/node_modules/uglify-js/.npmignore @@ -0,0 +1,4 @@ +.DS_Store +.tmp*~ +*.local.* +.pinf-* \ No newline at end of file diff --git a/node_modules/uglify-js/README.html b/node_modules/uglify-js/README.html new file mode 100644 index 0000000..8f5223f --- /dev/null +++ b/node_modules/uglify-js/README.html @@ -0,0 +1,1026 @@ + + + + +UglifyJS -- a JavaScript parser/compressor/beautifier + + + + + + + + + + + + +
+ +

UglifyJS – a JavaScript parser/compressor/beautifier

+ + + + +
+

1 UglifyJS — a JavaScript parser/compressor/beautifier

+
+ + +

+This package implements a general-purpose JavaScript +parser/compressor/beautifier toolkit. It is developed on NodeJS, but it +should work on any JavaScript platform supporting the CommonJS module system +(and if your platform of choice doesn't support CommonJS, you can easily +implement it, or discard the exports.* lines from UglifyJS sources). +

+

+The tokenizer/parser generates an abstract syntax tree from JS code. You +can then traverse the AST to learn more about the code, or do various +manipulations on it. This part is implemented in parse-js.js and it's a +port to JavaScript of the excellent parse-js Common Lisp library from Marijn Haverbeke. +

+

+( See cl-uglify-js if you're looking for the Common Lisp version of +UglifyJS. ) +

+

+The second part of this package, implemented in process.js, inspects and +manipulates the AST generated by the parser to provide the following: +

+
    +
  • +ability to re-generate JavaScript code from the AST. Optionally +indented—you can use this if you want to “beautify” a program that has +been compressed, so that you can inspect the source. But you can also run +our code generator to print out an AST without any whitespace, so you +achieve compression as well. + +
  • +
  • +shorten variable names (usually to single characters). Our mangler will +analyze the code and generate proper variable names, depending on scope +and usage, and is smart enough to deal with globals defined elsewhere, or +with eval() calls or with{} statements. In short, if eval() or +with{} are used in some scope, then all variables in that scope and any +variables in the parent scopes will remain unmangled, and any references +to such variables remain unmangled as well. + +
  • +
  • +various small optimizations that may lead to faster code but certainly +lead to smaller code. Where possible, we do the following: + +
      +
    • +foo["bar"] ==> foo.bar + +
    • +
    • +remove block brackets {} + +
    • +
    • +join consecutive var declarations: +var a = 10; var b = 20; ==> var a=10,b=20; + +
    • +
    • +resolve simple constant expressions: 1 +2 * 3 ==> 7. We only do the +replacement if the result occupies less bytes; for example 1/3 would +translate to 0.333333333333, so in this case we don't replace it. + +
    • +
    • +consecutive statements in blocks are merged into a sequence; in many +cases, this leaves blocks with a single statement, so then we can remove +the block brackets. + +
    • +
    • +various optimizations for IF statements: + +
        +
      • +if (foo) bar(); else baz(); ==> foo?bar():baz(); +
      • +
      • +if (!foo) bar(); else baz(); ==> foo?baz():bar(); +
      • +
      • +if (foo) bar(); ==> foo&&bar(); +
      • +
      • +if (!foo) bar(); ==> foo||bar(); +
      • +
      • +if (foo) return bar(); else return baz(); ==> return foo?bar():baz(); +
      • +
      • +if (foo) return bar(); else something(); ==> {if(foo)return bar();something()} + +
      • +
      +
    • +
    • +remove some unreachable code and warn about it (code that follows a +return, throw, break or continue statement, except +function/variable declarations). + +
    • +
    • +act a limited version of a pre-processor (c.f. the pre-processor of +C/C++) to allow you to safely replace selected global symbols with +specified values. When combined with the optimisations above this can +make UglifyJS operate slightly more like a compilation process, in +that when certain symbols are replaced by constant values, entire code +blocks may be optimised away as unreachable. +
    • +
    +
  • +
+ + + +
+ +
+

1.1 Unsafe transformations

+
+ + +

+The following transformations can in theory break code, although they're +probably safe in most practical cases. To enable them you need to pass the +--unsafe flag. +

+ +
+ +
+

1.1.1 Calls involving the global Array constructor

+
+ + +

+The following transformations occur: +

+ + + +
new Array(1, 2, 3, 4)  => [1,2,3,4]
+Array(a, b, c)         => [a,b,c]
+new Array(5)           => Array(5)
+new Array(a)           => Array(a)
+
+ + + +

+These are all safe if the Array name isn't redefined. JavaScript does allow +one to globally redefine Array (and pretty much everything, in fact) but I +personally don't see why would anyone do that. +

+

+UglifyJS does handle the case where Array is redefined locally, or even +globally but with a function or var declaration. Therefore, in the +following cases UglifyJS doesn't touch calls or instantiations of Array: +

+ + + +
// case 1.  globally declared variable
+  var Array;
+  new Array(1, 2, 3);
+  Array(a, b);
+
+  // or (can be declared later)
+  new Array(1, 2, 3);
+  var Array;
+
+  // or (can be a function)
+  new Array(1, 2, 3);
+  function Array() { ... }
+
+// case 2.  declared in a function
+  (function(){
+    a = new Array(1, 2, 3);
+    b = Array(5, 6);
+    var Array;
+  })();
+
+  // or
+  (function(Array){
+    return Array(5, 6, 7);
+  })();
+
+  // or
+  (function(){
+    return new Array(1, 2, 3, 4);
+    function Array() { ... }
+  })();
+
+  // etc.
+
+ + + +
+ +
+ +
+

1.1.2 obj.toString() ==> obj+“”

+
+ + +
+
+ +
+ +
+

1.2 Install (NPM)

+
+ + +

+UglifyJS is now available through NPM — npm install uglify-js should do +the job. +

+
+ +
+ +
+

1.3 Install latest code from GitHub

+
+ + + + + +
## clone the repository
+mkdir -p /where/you/wanna/put/it
+cd /where/you/wanna/put/it
+git clone git://github.com/mishoo/UglifyJS.git
+
+## make the module available to Node
+mkdir -p ~/.node_libraries/
+cd ~/.node_libraries/
+ln -s /where/you/wanna/put/it/UglifyJS/uglify-js.js
+
+## and if you want the CLI script too:
+mkdir -p ~/bin
+cd ~/bin
+ln -s /where/you/wanna/put/it/UglifyJS/bin/uglifyjs
+  # (then add ~/bin to your $PATH if it's not there already)
+
+ + + +
+ +
+ +
+

1.4 Usage

+
+ + +

+There is a command-line tool that exposes the functionality of this library +for your shell-scripting needs: +

+ + + +
uglifyjs [ options... ] [ filename ]
+
+ + + +

+filename should be the last argument and should name the file from which +to read the JavaScript code. If you don't specify it, it will read code +from STDIN. +

+

+Supported options: +

+
    +
  • +-b or --beautify — output indented code; when passed, additional +options control the beautifier: + +
      +
    • +-i N or --indent N — indentation level (number of spaces) + +
    • +
    • +-q or --quote-keys — quote keys in literal objects (by default, +only keys that cannot be identifier names will be quotes). + +
    • +
    +
  • +
  • +--ascii — pass this argument to encode non-ASCII characters as +\uXXXX sequences. By default UglifyJS won't bother to do it and will +output Unicode characters instead. (the output is always encoded in UTF8, +but if you pass this option you'll only get ASCII). + +
  • +
  • +-nm or --no-mangle — don't mangle variable names + +
  • +
  • +-ns or --no-squeeze — don't call ast_squeeze() (which does various +optimizations that result in smaller, less readable code). + +
  • +
  • +-mt or --mangle-toplevel — mangle names in the toplevel scope too +(by default we don't do this). + +
  • +
  • +--no-seqs — when ast_squeeze() is called (thus, unless you pass +--no-squeeze) it will reduce consecutive statements in blocks into a +sequence. For example, "a = 10; b = 20; foo();" will be written as +"a=10,b=20,foo();". In various occasions, this allows us to discard the +block brackets (since the block becomes a single statement). This is ON +by default because it seems safe and saves a few hundred bytes on some +libs that I tested it on, but pass --no-seqs to disable it. + +
  • +
  • +--no-dead-code — by default, UglifyJS will remove code that is +obviously unreachable (code that follows a return, throw, break or +continue statement and is not a function/variable declaration). Pass +this option to disable this optimization. + +
  • +
  • +-nc or --no-copyright — by default, uglifyjs will keep the initial +comment tokens in the generated code (assumed to be copyright information +etc.). If you pass this it will discard it. + +
  • +
  • +-o filename or --output filename — put the result in filename. If +this isn't given, the result goes to standard output (or see next one). + +
  • +
  • +--overwrite — if the code is read from a file (not from STDIN) and you +pass --overwrite then the output will be written in the same file. + +
  • +
  • +--ast — pass this if you want to get the Abstract Syntax Tree instead +of JavaScript as output. Useful for debugging or learning more about the +internals. + +
  • +
  • +-v or --verbose — output some notes on STDERR (for now just how long +each operation takes). + +
  • +
  • +-d SYMBOL[=VALUE] or --define SYMBOL[=VALUE] — will replace +all instances of the specified symbol where used as an identifier +(except where symbol has properly declared by a var declaration or +use as function parameter or similar) with the specified value. This +argument may be specified multiple times to define multiple +symbols - if no value is specified the symbol will be replaced with +the value true, or you can specify a numeric value (such as +1024), a quoted string value (such as ="object"= or +='https://github.com'), or the name of another symbol or keyword (such as =null or document). +This allows you, for example, to assign meaningful names to key +constant values but discard the symbolic names in the uglified +version for brevity/efficiency, or when used wth care, allows +UglifyJS to operate as a form of conditional compilation +whereby defining appropriate values may, by dint of the constant +folding and dead code removal features above, remove entire +superfluous code blocks (e.g. completely remove instrumentation or +trace code for production use). +Where string values are being defined, the handling of quotes are +likely to be subject to the specifics of your command shell +environment, so you may need to experiment with quoting styles +depending on your platform, or you may find the option +--define-from-module more suitable for use. + +
  • +
  • +-define-from-module SOMEMODULE — will load the named module (as +per the NodeJS require() function) and iterate all the exported +properties of the module defining them as symbol names to be defined +(as if by the --define option) per the name of each property +(i.e. without the module name prefix) and given the value of the +property. This is a much easier way to handle and document groups of +symbols to be defined rather than a large number of --define +options. + +
  • +
  • +--unsafe — enable other additional optimizations that are known to be +unsafe in some contrived situations, but could still be generally useful. +For now only these: + +
      +
    • +foo.toString() ==> foo+"" +
    • +
    • +new Array(x,…) ==> [x,…] +
    • +
    • +new Array(x) ==> Array(x) + +
    • +
    +
  • +
  • +--max-line-len (default 32K characters) — add a newline after around +32K characters. I've seen both FF and Chrome croak when all the code was +on a single line of around 670K. Pass –max-line-len 0 to disable this +safety feature. + +
  • +
  • +--reserved-names — some libraries rely on certain names to be used, as +pointed out in issue #92 and #81, so this option allow you to exclude such +names from the mangler. For example, to keep names require and $super +intact you'd specify –reserved-names "require,$super". + +
  • +
  • +--inline-script – when you want to include the output literally in an +HTML <script> tag you can use this option to prevent </script from +showing up in the output. + +
  • +
  • +--lift-vars – when you pass this, UglifyJS will apply the following +transformations (see the notes in API, ast_lift_variables): + +
      +
    • +put all var declarations at the start of the scope +
    • +
    • +make sure a variable is declared only once +
    • +
    • +discard unused function arguments +
    • +
    • +discard unused inner (named) functions +
    • +
    • +finally, try to merge assignments into that one var declaration, if +possible. +
    • +
    +
  • +
+ + + +
+ +
+

1.4.1 API

+
+ + +

+To use the library from JavaScript, you'd do the following (example for +NodeJS): +

+ + + +
var jsp = require("uglify-js").parser;
+var pro = require("uglify-js").uglify;
+
+var orig_code = "... JS code here";
+var ast = jsp.parse(orig_code); // parse code and get the initial AST
+ast = pro.ast_mangle(ast); // get a new AST with mangled names
+ast = pro.ast_squeeze(ast); // get an AST with compression optimizations
+var final_code = pro.gen_code(ast); // compressed code here
+
+ + + +

+The above performs the full compression that is possible right now. As you +can see, there are a sequence of steps which you can apply. For example if +you want compressed output but for some reason you don't want to mangle +variable names, you would simply skip the line that calls +pro.ast_mangle(ast). +

+

+Some of these functions take optional arguments. Here's a description: +

+
    +
  • +jsp.parse(code, strict_semicolons) – parses JS code and returns an AST. +strict_semicolons is optional and defaults to false. If you pass +true then the parser will throw an error when it expects a semicolon and +it doesn't find it. For most JS code you don't want that, but it's useful +if you want to strictly sanitize your code. + +
  • +
  • +pro.ast_lift_variables(ast) – merge and move var declarations to the +scop of the scope; discard unused function arguments or variables; discard +unused (named) inner functions. It also tries to merge assignments +following the var declaration into it. + +

    +If your code is very hand-optimized concerning var declarations, this +lifting variable declarations might actually increase size. For me it +helps out. On jQuery it adds 865 bytes (243 after gzip). YMMV. Also +note that (since it's not enabled by default) this operation isn't yet +heavily tested (please report if you find issues!). +

    +

    +Note that although it might increase the image size (on jQuery it gains +865 bytes, 243 after gzip) it's technically more correct: in certain +situations, dead code removal might drop variable declarations, which +would not happen if the variables are lifted in advance. +

    +

    +Here's an example of what it does: +

    +
  • +
+ + + + +
function f(a, b, c, d, e) {
+    var q;
+    var w;
+    w = 10;
+    q = 20;
+    for (var i = 1; i < 10; ++i) {
+        var boo = foo(a);
+    }
+    for (var i = 0; i < 1; ++i) {
+        var boo = bar(c);
+    }
+    function foo(){ ... }
+    function bar(){ ... }
+    function baz(){ ... }
+}
+
+// transforms into ==>
+
+function f(a, b, c) {
+    var i, boo, w = 10, q = 20;
+    for (i = 1; i < 10; ++i) {
+        boo = foo(a);
+    }
+    for (i = 0; i < 1; ++i) {
+        boo = bar(c);
+    }
+    function foo() { ... }
+    function bar() { ... }
+}
+
+ + + +
    +
  • +pro.ast_mangle(ast, options) – generates a new AST containing mangled +(compressed) variable and function names. It supports the following +options: + +
      +
    • +toplevel – mangle toplevel names (by default we don't touch them). +
    • +
    • +except – an array of names to exclude from compression. +
    • +
    • +defines – an object with properties named after symbols to +replace (see the --define option for the script) and the values +representing the AST replacement value. + +
    • +
    +
  • +
  • +pro.ast_squeeze(ast, options) – employs further optimizations designed +to reduce the size of the code that gen_code would generate from the +AST. Returns a new AST. options can be a hash; the supported options +are: + +
      +
    • +make_seqs (default true) which will cause consecutive statements in a +block to be merged using the "sequence" (comma) operator + +
    • +
    • +dead_code (default true) which will remove unreachable code. + +
    • +
    +
  • +
  • +pro.gen_code(ast, options) – generates JS code from the AST. By +default it's minified, but using the options argument you can get nicely +formatted output. options is, well, optional :-) and if you pass it it +must be an object and supports the following properties (below you can see +the default values): + +
      +
    • +beautify: false – pass true if you want indented output +
    • +
    • +indent_start: 0 (only applies when beautify is true) – initial +indentation in spaces +
    • +
    • +indent_level: 4 (only applies when beautify is true) -- +indentation level, in spaces (pass an even number) +
    • +
    • +quote_keys: false – if you pass true it will quote all keys in +literal objects +
    • +
    • +space_colon: false (only applies when beautify is true) – wether +to put a space before the colon in object literals +
    • +
    • +ascii_only: false – pass true if you want to encode non-ASCII +characters as \uXXXX. +
    • +
    • +inline_script: false – pass true to escape occurrences of +</script in strings +
    • +
    +
  • +
+ + +
+ +
+ +
+

1.4.2 Beautifier shortcoming – no more comments

+
+ + +

+The beautifier can be used as a general purpose indentation tool. It's +useful when you want to make a minified file readable. One limitation, +though, is that it discards all comments, so you don't really want to use it +to reformat your code, unless you don't have, or don't care about, comments. +

+

+In fact it's not the beautifier who discards comments — they are dumped at +the parsing stage, when we build the initial AST. Comments don't really +make sense in the AST, and while we could add nodes for them, it would be +inconvenient because we'd have to add special rules to ignore them at all +the processing stages. +

+
+ +
+ +
+

1.4.3 Use as a code pre-processor

+
+ + +

+The --define option can be used, particularly when combined with the +constant folding logic, as a form of pre-processor to enable or remove +particular constructions, such as might be used for instrumenting +development code, or to produce variations aimed at a specific +platform. +

+

+The code below illustrates the way this can be done, and how the +symbol replacement is performed. +

+ + + +
CLAUSE1: if (typeof DEVMODE === 'undefined') {
+    DEVMODE = true;
+}
+
+CLAUSE2: function init() {
+    if (DEVMODE) {
+        console.log("init() called");
+    }
+    ....
+    DEVMODE &amp;&amp; console.log("init() complete");
+}
+
+CLAUSE3: function reportDeviceStatus(device) {
+    var DEVMODE = device.mode, DEVNAME = device.name;
+    if (DEVMODE === 'open') {
+        ....
+    }
+}
+
+ + + +

+When the above code is normally executed, the undeclared global +variable DEVMODE will be assigned the value true (see CLAUSE1) +and so the init() function (CLAUSE2) will write messages to the +console log when executed, but in CLAUSE3 a locally declared +variable will mask access to the DEVMODE global symbol. +

+

+If the above code is processed by UglifyJS with an argument of +--define DEVMODE=false then UglifyJS will replace DEVMODE with the +boolean constant value false within CLAUSE1 and CLAUSE2, but it +will leave CLAUSE3 as it stands because there DEVMODE resolves to +a validly declared variable. +

+

+And more so, the constant-folding features of UglifyJS will recognise +that the if condition of CLAUSE1 is thus always false, and so will +remove the test and body of CLAUSE1 altogether (including the +otherwise slightly problematical statement false = true; which it +will have formed by replacing DEVMODE in the body). Similarly, +within CLAUSE2 both calls to console.log() will be removed +altogether. +

+

+In this way you can mimic, to a limited degree, the functionality of +the C/C++ pre-processor to enable or completely remove blocks +depending on how certain symbols are defined - perhaps using UglifyJS +to generate different versions of source aimed at different +environments +

+

+It is recommmended (but not made mandatory) that symbols designed for +this purpose are given names consisting of UPPER_CASE_LETTERS to +distinguish them from other (normal) symbols and avoid the sort of +clash that CLAUSE3 above illustrates. +

+
+
+ +
+ +
+

1.5 Compression – how good is it?

+
+ + +

+Here are updated statistics. (I also updated my Google Closure and YUI +installations). +

+

+We're still a lot better than YUI in terms of compression, though slightly +slower. We're still a lot faster than Closure, and compression after gzip +is comparable. +

+ + ++ + + + + + + + + + +
FileUglifyJSUglifyJS+gzipClosureClosure+gzipYUIYUI+gzip
jquery-1.6.2.js91001 (0:01.59)3189690678 (0:07.40)31979101527 (0:01.82)34646
paper.js142023 (0:01.65)43334134301 (0:07.42)42495173383 (0:01.58)48785
prototype.js88544 (0:01.09)2668086955 (0:06.97)2632692130 (0:00.79)28624
thelib-full.js (DynarchLIB)251939 (0:02.55)72535249911 (0:09.05)72696258869 (0:01.94)76584
+ + +
+ +
+ +
+

1.6 Bugs?

+
+ + +

+Unfortunately, for the time being there is no automated test suite. But I +ran the compressor manually on non-trivial code, and then I tested that the +generated code works as expected. A few hundred times. +

+

+DynarchLIB was started in times when there was no good JS minifier. +Therefore I was quite religious about trying to write short code manually, +and as such DL contains a lot of syntactic hacks1 such as “foo == bar ? a += 10 : b = 20”, though the more readable version would clearly be to use +“if/else”. +

+

+Since the parser/compressor runs fine on DL and jQuery, I'm quite confident +that it's solid enough for production use. If you can identify any bugs, +I'd love to hear about them (use the Google Group or email me directly). +

+
+ +
+ +
+

1.7 Links

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

1.8 License

+
+ + +

+UglifyJS is released under the BSD license: +

+ + + +
Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>
+Based on parse-js (http://marijn.haverbeke.nl/parse-js/).
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+    * Redistributions of source code must retain the above
+      copyright notice, this list of conditions and the following
+      disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials
+      provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+ + + + +
+
+
+
+

Footnotes:

+
+

1 I even reported a few bugs and suggested some fixes in the original +parse-js library, and Marijn pushed fixes literally in minutes. +

+
+
+
+

Author: Mihai Bazon +

+

Date: 2011-08-29 19:17:55 EEST

+

HTML generated by org-mode 7.01trans in emacs 23

+
+
+ + diff --git a/node_modules/uglify-js/README.org b/node_modules/uglify-js/README.org new file mode 100644 index 0000000..50c9c27 --- /dev/null +++ b/node_modules/uglify-js/README.org @@ -0,0 +1,571 @@ +#+TITLE: UglifyJS -- a JavaScript parser/compressor/beautifier +#+KEYWORDS: javascript, js, parser, compiler, compressor, mangle, minify, minifier +#+DESCRIPTION: a JavaScript parser/compressor/beautifier in JavaScript +#+STYLE: +#+AUTHOR: Mihai Bazon +#+EMAIL: mihai.bazon@gmail.com + +* UglifyJS --- a JavaScript parser/compressor/beautifier + +This package implements a general-purpose JavaScript +parser/compressor/beautifier toolkit. It is developed on [[http://nodejs.org/][NodeJS]], but it +should work on any JavaScript platform supporting the CommonJS module system +(and if your platform of choice doesn't support CommonJS, you can easily +implement it, or discard the =exports.*= lines from UglifyJS sources). + +The tokenizer/parser generates an abstract syntax tree from JS code. You +can then traverse the AST to learn more about the code, or do various +manipulations on it. This part is implemented in [[../lib/parse-js.js][parse-js.js]] and it's a +port to JavaScript of the excellent [[http://marijn.haverbeke.nl/parse-js/][parse-js]] Common Lisp library from [[http://marijn.haverbeke.nl/][Marijn +Haverbeke]]. + +( See [[http://github.com/mishoo/cl-uglify-js][cl-uglify-js]] if you're looking for the Common Lisp version of +UglifyJS. ) + +The second part of this package, implemented in [[../lib/process.js][process.js]], inspects and +manipulates the AST generated by the parser to provide the following: + +- ability to re-generate JavaScript code from the AST. Optionally + indented---you can use this if you want to “beautify” a program that has + been compressed, so that you can inspect the source. But you can also run + our code generator to print out an AST without any whitespace, so you + achieve compression as well. + +- shorten variable names (usually to single characters). Our mangler will + analyze the code and generate proper variable names, depending on scope + and usage, and is smart enough to deal with globals defined elsewhere, or + with =eval()= calls or =with{}= statements. In short, if =eval()= or + =with{}= are used in some scope, then all variables in that scope and any + variables in the parent scopes will remain unmangled, and any references + to such variables remain unmangled as well. + +- various small optimizations that may lead to faster code but certainly + lead to smaller code. Where possible, we do the following: + + - foo["bar"] ==> foo.bar + + - remove block brackets ={}= + + - join consecutive var declarations: + var a = 10; var b = 20; ==> var a=10,b=20; + + - resolve simple constant expressions: 1 +2 * 3 ==> 7. We only do the + replacement if the result occupies less bytes; for example 1/3 would + translate to 0.333333333333, so in this case we don't replace it. + + - consecutive statements in blocks are merged into a sequence; in many + cases, this leaves blocks with a single statement, so then we can remove + the block brackets. + + - various optimizations for IF statements: + + - if (foo) bar(); else baz(); ==> foo?bar():baz(); + - if (!foo) bar(); else baz(); ==> foo?baz():bar(); + - if (foo) bar(); ==> foo&&bar(); + - if (!foo) bar(); ==> foo||bar(); + - if (foo) return bar(); else return baz(); ==> return foo?bar():baz(); + - if (foo) return bar(); else something(); ==> {if(foo)return bar();something()} + + - remove some unreachable code and warn about it (code that follows a + =return=, =throw=, =break= or =continue= statement, except + function/variable declarations). + + - act a limited version of a pre-processor (c.f. the pre-processor of + C/C++) to allow you to safely replace selected global symbols with + specified values. When combined with the optimisations above this can + make UglifyJS operate slightly more like a compilation process, in + that when certain symbols are replaced by constant values, entire code + blocks may be optimised away as unreachable. + +** <> + +The following transformations can in theory break code, although they're +probably safe in most practical cases. To enable them you need to pass the +=--unsafe= flag. + +*** Calls involving the global Array constructor + +The following transformations occur: + +#+BEGIN_SRC js +new Array(1, 2, 3, 4) => [1,2,3,4] +Array(a, b, c) => [a,b,c] +new Array(5) => Array(5) +new Array(a) => Array(a) +#+END_SRC + +These are all safe if the Array name isn't redefined. JavaScript does allow +one to globally redefine Array (and pretty much everything, in fact) but I +personally don't see why would anyone do that. + +UglifyJS does handle the case where Array is redefined locally, or even +globally but with a =function= or =var= declaration. Therefore, in the +following cases UglifyJS *doesn't touch* calls or instantiations of Array: + +#+BEGIN_SRC js +// case 1. globally declared variable + var Array; + new Array(1, 2, 3); + Array(a, b); + + // or (can be declared later) + new Array(1, 2, 3); + var Array; + + // or (can be a function) + new Array(1, 2, 3); + function Array() { ... } + +// case 2. declared in a function + (function(){ + a = new Array(1, 2, 3); + b = Array(5, 6); + var Array; + })(); + + // or + (function(Array){ + return Array(5, 6, 7); + })(); + + // or + (function(){ + return new Array(1, 2, 3, 4); + function Array() { ... } + })(); + + // etc. +#+END_SRC + +*** =obj.toString()= ==> =obj+“”= + +** Install (NPM) + +UglifyJS is now available through NPM --- =npm install uglify-js= should do +the job. + +** Install latest code from GitHub + +#+BEGIN_SRC sh +## clone the repository +mkdir -p /where/you/wanna/put/it +cd /where/you/wanna/put/it +git clone git://github.com/mishoo/UglifyJS.git + +## make the module available to Node +mkdir -p ~/.node_libraries/ +cd ~/.node_libraries/ +ln -s /where/you/wanna/put/it/UglifyJS/uglify-js.js + +## and if you want the CLI script too: +mkdir -p ~/bin +cd ~/bin +ln -s /where/you/wanna/put/it/UglifyJS/bin/uglifyjs + # (then add ~/bin to your $PATH if it's not there already) +#+END_SRC + +** Usage + +There is a command-line tool that exposes the functionality of this library +for your shell-scripting needs: + +#+BEGIN_SRC sh +uglifyjs [ options... ] [ filename ] +#+END_SRC + +=filename= should be the last argument and should name the file from which +to read the JavaScript code. If you don't specify it, it will read code +from STDIN. + +Supported options: + +- =-b= or =--beautify= --- output indented code; when passed, additional + options control the beautifier: + + - =-i N= or =--indent N= --- indentation level (number of spaces) + + - =-q= or =--quote-keys= --- quote keys in literal objects (by default, + only keys that cannot be identifier names will be quotes). + +- =--ascii= --- pass this argument to encode non-ASCII characters as + =\uXXXX= sequences. By default UglifyJS won't bother to do it and will + output Unicode characters instead. (the output is always encoded in UTF8, + but if you pass this option you'll only get ASCII). + +- =-nm= or =--no-mangle= --- don't mangle variable names + +- =-ns= or =--no-squeeze= --- don't call =ast_squeeze()= (which does various + optimizations that result in smaller, less readable code). + +- =-mt= or =--mangle-toplevel= --- mangle names in the toplevel scope too + (by default we don't do this). + +- =--no-seqs= --- when =ast_squeeze()= is called (thus, unless you pass + =--no-squeeze=) it will reduce consecutive statements in blocks into a + sequence. For example, "a = 10; b = 20; foo();" will be written as + "a=10,b=20,foo();". In various occasions, this allows us to discard the + block brackets (since the block becomes a single statement). This is ON + by default because it seems safe and saves a few hundred bytes on some + libs that I tested it on, but pass =--no-seqs= to disable it. + +- =--no-dead-code= --- by default, UglifyJS will remove code that is + obviously unreachable (code that follows a =return=, =throw=, =break= or + =continue= statement and is not a function/variable declaration). Pass + this option to disable this optimization. + +- =-nc= or =--no-copyright= --- by default, =uglifyjs= will keep the initial + comment tokens in the generated code (assumed to be copyright information + etc.). If you pass this it will discard it. + +- =-o filename= or =--output filename= --- put the result in =filename=. If + this isn't given, the result goes to standard output (or see next one). + +- =--overwrite= --- if the code is read from a file (not from STDIN) and you + pass =--overwrite= then the output will be written in the same file. + +- =--ast= --- pass this if you want to get the Abstract Syntax Tree instead + of JavaScript as output. Useful for debugging or learning more about the + internals. + +- =-v= or =--verbose= --- output some notes on STDERR (for now just how long + each operation takes). + +- =-d SYMBOL[=VALUE]= or =--define SYMBOL[=VALUE]= --- will replace + all instances of the specified symbol where used as an identifier + (except where symbol has properly declared by a var declaration or + use as function parameter or similar) with the specified value. This + argument may be specified multiple times to define multiple + symbols - if no value is specified the symbol will be replaced with + the value =true=, or you can specify a numeric value (such as + =1024=), a quoted string value (such as ="object"= or + ='https://github.com'=), or the name of another symbol or keyword + (such as =null= or =document=). + This allows you, for example, to assign meaningful names to key + constant values but discard the symbolic names in the uglified + version for brevity/efficiency, or when used wth care, allows + UglifyJS to operate as a form of *conditional compilation* + whereby defining appropriate values may, by dint of the constant + folding and dead code removal features above, remove entire + superfluous code blocks (e.g. completely remove instrumentation or + trace code for production use). + Where string values are being defined, the handling of quotes are + likely to be subject to the specifics of your command shell + environment, so you may need to experiment with quoting styles + depending on your platform, or you may find the option + =--define-from-module= more suitable for use. + +- =-define-from-module SOMEMODULE= --- will load the named module (as + per the NodeJS =require()= function) and iterate all the exported + properties of the module defining them as symbol names to be defined + (as if by the =--define= option) per the name of each property + (i.e. without the module name prefix) and given the value of the + property. This is a much easier way to handle and document groups of + symbols to be defined rather than a large number of =--define= + options. + +- =--unsafe= --- enable other additional optimizations that are known to be + unsafe in some contrived situations, but could still be generally useful. + For now only these: + + - foo.toString() ==> foo+"" + - new Array(x,...) ==> [x,...] + - new Array(x) ==> Array(x) + +- =--max-line-len= (default 32K characters) --- add a newline after around + 32K characters. I've seen both FF and Chrome croak when all the code was + on a single line of around 670K. Pass --max-line-len 0 to disable this + safety feature. + +- =--reserved-names= --- some libraries rely on certain names to be used, as + pointed out in issue #92 and #81, so this option allow you to exclude such + names from the mangler. For example, to keep names =require= and =$super= + intact you'd specify --reserved-names "require,$super". + +- =--inline-script= -- when you want to include the output literally in an + HTML = + + + + diff --git a/websockets.js b/websockets.js new file mode 100644 index 0000000..205f065 --- /dev/null +++ b/websockets.js @@ -0,0 +1,16 @@ + +async function go() { + const LNSocket = await lnsocket_init() + const ln = LNSocket() + + ln.genkey() + //const their_init = await ln.connect_and_init("03f3c108ccd536b8526841f0a5c58212bb9e6584a1eb493080e7c1cc34f82dad71", "cln.jb55.com:443") + await ln.connect_and_init("03f3c108ccd536b8526841f0a5c58212bb9e6584a1eb493080e7c1cc34f82dad71", "ws://24.84.152.187:8324") + + const rune = "APaeUhcGPAMQwgV1Kn-hRRs5Bi4-D1nrfsHfCoTLl749MTAmbWV0aG9kPWdldGluZm8=" + const res = await ln.rpc({ method: "getinfo", rune }) + + document.body.innerHTML = `
${JSON.stringify(res.result, undefined, 2)}
` +} + +go()

6wT0bWetngiPbZd;T@`Qx^P-;Hkt&j5kAJvQ=n_w6X8RHeK;u8bJX;k&?JIu6|@C zwLvCgoPnB({X_=hFss%ze3%up(l#$sw*z=St>xqDEjmX^L4Rw3i8IW@TktL{QB8`5 zbfThqXQ#Opz)62YKB=(jefjLshLjKfO*DN!N@VSbN=nHJrFO{9CK4Zp9)ib?@kQ~f zUJLFEBPNXT6kZFrC8iyA+|USq50k^tt3G;~CL+u@*0*>UGrzcY)M^!`cxaPClXF-a z)L9j~>p!yqFgE9T#1E2Hk3r;NFi2`(wH_iNw?PO(L$6bE-;T01BoqHhdbX4_~ z6-JZjIS@2piV|53eEKo8`Re@|cEbmmaI@Y{)}2ce6_Myvz}o!*L^b;fx?v2m`F<_J zf>WiV?Lz5H);_jhOPFkICen&?ujzO?dzthj5ouuLCHk&@sUZ0xt9`dp0J0I38*hPB zQX}%6@d~G@Hw-Jd4w+S2pqLxe>k>u?XSJXaS2oHJULBh+UWXyQ#yOaw^v0h+ zI%V=(KB@l2=~ZP=Hib9mHak?3v2GK5YN1t~IZkZ=Ay6Ojz$UUh30Q;m{eTuK8r)vv z$vL84V^cn12e$=t1@Aia0?p2~rB0{0o#g~laeTs%p1dgjtQ1;Lm2qn^v!c%cw3yZ{ z&x_^gfg+L30V}5+OCo!`7}mBYH<^UT)r!ii$YmNj-4!?F?1e`QF=dTIEX$Cc-oB?T z{6?~>(Jnqk6&TXc+fWa=AVI+k6}7K+i^5a1?(?USaROSP6DK*UQdHg@aHG@tg+FRl zs6@`qt3yO(BYtlf{gRkTL0>-VVfbknHDb1P&;!Y>qLma&x>%}U%R^kWcu|%S>c_J2$zkEz&o7L4M%NovD!A@?)^vo zRSGAVkSis$+ze99#*m`x;|vFbPVWh?%q^0H@bA(=Lg$L!X}1MlX~?=TAEdIB%_2A& zRsjT~pgfZ#DuDuU+m6PXZ52$(?fMJ;3U5?nXijyoOajD|F=6bqLr%yLC78U@Qf5U{ zQXqJHLI6Z=FpjJCY^6O8YdRVrnehu#@h!g1uqp{`j)__z8)r#})QO*Hqha4WR4v>K zeoxK6N}4X^fqN;#Fq7dZqjnap=DVy|T8a$JwqQ-Oox!5|fFn=^VgKnwC4`BWvbimO z#j|^1d6A*o1s5NR*9s^HZgD0ODY`8QVAD`UxACPNzP<%I=F8aNTV@;!r9=_m*MaKj z_mljkCm=k>ILRSVLHkNaYW{b4B-rSlCuR{Xd*H1mI6;b!7>-ZXXD}Z+Dv9_X!OIMqOQ!U_@8SkE-rSNNEl@H86-k`L}Ie8Ts9(Zol9bvm*~Zp z{ov!_)-PD8hH2iCCltlrAm8$oxEn=IO|T`-%169N&7Ys=bQP2{Ke;N;I($P!;fFx% zs7opV$0*^2J`{*Ax58?A)%igNT$s#^vtJ(h5{KqI?|JQMUB{b%cpy3zGUEgZ#ge53 zUE?$h;fnvrT_;;gawvn#p3;ak5+{3szfw%zZV{pxF=(4QSoo=N^p-;eNqG%qc7+Jg)BjG#Y!rO-3ULstfv%s z#WOF|&(ieVM{0G*`Q|ecZ6H*1^MSdf_%hZ*>M-PHfmtrGn3g;9cf6bX+1vAKZQ6JY zH9Z$~xMHksq(Or5xEh3IPjE78$!0m0IO4sDJ>z@!MJ((l>6>AGYK`Q?o?WxrSY&0A zf5=qpg|7xaf`(huthG6FbTXKp-<6oXbo68%^y6kDe~Vi~ zfWLd!%38JGLCw+~jJnuH+nMK(#ij3ac;0()hIM0Ho15*OP*wFq6+FT^!cy398tzTC1e1QA*+$%eLLXjD1oM zVNd%lG?#is;)CLg3ZZL420ShI8tT}|kDfDWv0bO($V#uA9T@us9>+MZ*sk|?=ewR_J78L2yXCWBJ{EFNx| zLv&;@;n-g3PaZNzc5blc)5Wql$e!b>0zv&epNUqx&Oy`+MvC9eCS|@wo_Z42Dz{XO zApu1vIBh7roZYz+Z5>-L^1?v;sT)m4j@B|j5%HcXg5U+uB3+eyZAP@Uw`|MK(Z7KW z3}c`M2Zz_wos8uf2;8g5q}g0T^;&p_(hpV*-8EF>zREASYctI-qR@hoTCdp6IcZ3K z0<=aK;&<%czPR6J`aRG2uAHCQSB@T-0zX(bv9Q8AFF7V3Uk+37Y&W}ko<)%R^k z|G#g`;R9OII-HtvHzO>%X)%U|_yGuP>Ff25AjJhVD9ULP0-0Qp2eZ-3-<``6f=k2e z$IvkM2On?^(|)Bpx}P|5GP{Ym@FU0AMlTA`#x@*v3=fu4)oOPbV+827l6N9b9^u&+ zAc6ToyrT#dYg;s`W>Vi-9+1Pl|7qNGtF^)w!=Ju5{m9rU{siOciBNIq5oichG3unA zi}GS+lR}7vQvgH`_`{%%GcU@svDex*)p|Km&B1PRM4swf^t8*Qc(Vm%%#HEgnM%$` z=N~(gj`_S1G;&pfVPXjkUhU;K!dMvxwzP_l`rR}-f$neT)V{HuA^4Sc%dmdk6a9`+ zAAjc$3e@|_6hI|kQxT?isPOy0K-Y|=^7Y@Bm{%iArG!3z_SO*)ncd|gp{{EqMO`Xn zNSxx;QRga}^zMb~yH99{Co@yYJk|@GzrWj}|4(Fa?x>3JauM_D%^Aq&L=3NlfN7N3 zE)nM8v~g{bgq;Y~72mTBDSrGRjRy-&RYol-SEvL)bJKexmY z?7`RN<#axJmF1r%X`Vne+>=9o_a=h5^Q)CxK^SuYq(5LZ{g=m#zU&Riwl-vmh+e|F zw=+v;o9ZL7!!hB|6L0OkYd!>qSL{v8Do!U0-ekl{zk3~lP*n&z0BhFUDp2CkpJbd* zFJl`(nqp!hA=Ml;tkM76EI#*F$FLxvZBjrXr2F8bz~z1tH@CIVW}2r%U`sv9RR5|Q zs!Lb{`(C@(xl2(zAlT23+{2BX%iicm3R~V60_|id@tY{T5x4=^o9&tTXNG~j8OKpB zkz-!*I>6m~#{z}=DSxClmweHAE^|X79j9*m7~I2|rjk%~?2-nC&GuCn2T^TI`p)1&n3c=mW;;C^8=2=KMDMWJEYa=8C>f zYwm{HQr~Mtd}**)!Jq8a8r6aPN92LG7rPcO0-vijS8SqZixf9yf?@^Hb5wjUCn+v8 z_`=lq5Q?MEtRCzvGfr(<-IPVGUaT@jHLet85Ct<>zHB)|5GiO5tR%_L1TlUupCy4? zw5k*aMdAR#NL9wcd$I57p%)w=4I{2di%tfHtDtL1t37%1Lx4n>rj%@5Tu?@?9%!L= zMm4j;iF7hfd8a~jxPC)K{)@L+y8kDH2`ZFbvq!5EW`&nB_w^spB2>&_O8-8Uz&=`x zZQJdb;&N=hn%WOk%^g>B9Poml%v?sY(SvHKhg)G>bcfk3fT_{x47s+kHCl#qdMuyp z?BCv|SPhHJ>5O&eHU|N?+umV$s?PP}?y|AN-ze1m!%chOf#H|Sn1CLs`EIC3W~Ex@ zSt{a~$C9I&e^#`DtF>=Q24QL%2=t6OA`T&w$|Ktl8>4~vMbe^|5cAkLja~6s)5H7g z$f<>Qoi=n$PuzD~mC>D@18ov%#vZErS}A7Ua3*Nm+R#sVU9^halrf5&frSqQWbuo0 zg!M~F#&IT6qJ&~g(tG1K-BU`vNHQaj)IN$9sb#;CGNTLxWY6|EeHRq>kB`rLO($}t zCl;D?Z|w)cZu6#+0+JEcx>R?DWZv^cqAHtHzoi6wJxo%=XAdj6i0u)tl&+a1%eF5s zjE`pIphd-Y$*y*B*K?I4`S?{{_Ufg5F;Q1Kr0b&21>Bxo{!KO2IALYxXUwql$Z_y~ zY;3#KG^0X5q(tzy#5Wg*%a6U`LtQx9Gg4*ud;>y>K*qc2u=wIYFx&c9Fep@{Y0(@Waz41(&zyy%8||7lqnoH9#Ec_up~?@th7DtGP_z zE!|cza~NN1QQ9hw+R_LUi>msyoaXdv3gh&rJ5e5JlpL#jkm{4*i>Km!EDcFCDfF_$ zD*fn7xHWajoPCUV1yaW!+t0`!){>xntryW60XFFj84V98O%fseriaSjyd!Q3(u}I7 zB_~zWtQxYjEwI1+$m|yi@(Jgd@8}D|^plDVfQpV&0#8R`_))}&$k&4%$Gq$h{Lhon zj5fXP=+q_li|=Ae-V$69m|ZM%tY>;ndR()2ZB9D(}j$VCKX3<%?G;aGZ>UN2K*8{ z&78voLZFY753$d(>)|NOYNgSUKt)-_f!^8&eaA=QfYRNs6mR0bP~?lq33=}y0LyZX z$i^_*>7|f*lFRW(x_^4PXE@nVzPbAa5;g42jYMhe<*I zfqtdfccY)T!u3`hWb~}wBe2rL1z=L}BrG<;%*bnVtF0?(Yl#7ueDV8w_UJ!E3svSp zAr58cjNYmq1$qMKsX2eGWE;&YB3vWFKQ2Q~kSaLJM{RmRpFu=}x@#P=tj@_WrwK;+ z2bcy@D5$|P7h%e|8iGh+<=;%i2ky(+XO=P?Z#V;*(1u|z2%JgLxPW1C?_YrBarEW5 z`I*@60NH}k>{Slos}nCI`nrAsO-3a{q<0B}!^VcZ@aA9cb>`p}f&Fn709qP{N9IyK zix6MU91FHi2U1s6`2K=tcPxMCutg2l9YuSBHvpF-tty#jylQ!gL1yx6Bcl zsTrZWdm>y;f7~N)H-*`%%*tjNwvOja;E6fpk|o*YkBq)?O3yy?Xc_61Zr-9rAEv5} z3GO>y50TME*o_0G#Dm13B8FRQP~|eV!{F_ftedB@HGSv|<5M)TJ~0T;pSEV?qnzFS z>v$8GiAX@E%%ylg;vDqjyIXVEE6 zfq|#HOXgiZJ84SC!3}}wh!rY}@*M#>H;(V(*QQSmaR;-rzf)NTC&4YWnaTV<%citw zXJ5k6ki5VeBjgsD!>%z&n>I{2NTK2?%24)K6^)4Goq~9}eKZe4m`&m}mjauV($gOj zthfwA{H1a+>&UHY$l$~oL3-L!4F3aOo2n288It8u&JK#l?-g(8>+^O6gB!!sdby{y z@{q~u1A%Z4jbF5WN{f$zv7p|~pRjf%*Tf-Oc&QL!c)`JSE*;PUb45GyE(Oxhx7H2P zeoAN{R2?+sQmYllwQ;PMrz&_}QsJ~TMb63eg$9OsFxB!Kf>rL>YYvC#?&Zk+GPT~a z8N{8=JvQ31GaLm8rr>yk6JVk+d^DT_9u--z>4Sz%NKj#~m6wN_$K6>0zE{Wg6fDSD zlCv?~o}bs0RPJ6nSE~-#;?jfVmJ}e%Frj(PzHWlqsS`l@C$GrVj=~TwxY!ArP_LhI zwI2e@$U6kF4`_*2)tskz&&4&p1Sm;*NVK}3uk!}V?99k6-*?W!j6x7%4a*WLE|}JGAS?Ia zYeT9UQEOEEuL}^qCb*3eh*{(2SIL${wZdvGMe1utXCG?aX6B{%fgL-)#SP55* ztHVwg1OjGEErnM{B*A6V=`50g2i0;3bk()l?oJk58-!N4?Yh72hxt)@#dIzE97I1( z5o2l)+|rd#-(zvP+cn+pRwlGMtIXE~v(@iPb?PA(AYyj3NkW#}GQgss=jtrz4PB9n zz6HWKu%|2?`{B!McX!@807r$*>j8gv%It%@^ z8rjADHh=rt`poJ+N3rr|fVWpznHIU9JB9d`GpBE?CLa*meN?WI1F0;gssR~;QC{L5 zV^9W)4Bt{uaGL7IKSDw9kwlwv&OGYeesx?HiNx;*r;;rCbZ-Zx-3j=(_hW5A$y;J; z(2!ajz?6hxYq>odUH%sCz%a(Gk3 zMndbcit_Mf}`7pRY6lqDsE(?*gH*GnnhdlBVE-agv3l#$9W1ldnK@(_d|BuPjNMQ+xmnj*n`yX2eKgeXHt75w-_ z6{Wcg%KZL*v41F_R}iWTqSkdgX0R}>1<~o!E)l_*W6nl^0q%(IY9L+KQ~PrnyVZ-t z;^h9Wt)+7UPY2XC|F4(-l&xPCL=F2cZ9{K(0`a{c8?kKd#6FVEbQI2tAoc+jk~1GG^Sd5D)+gYaBhYSDcnAt=JI&iVhUU{1 z9m0qPyiC@8aB)P;bZhPca?t%jZDAyMqt&zcQwwP)p2~23IwCyJA9gXoL(A27`x0!G zsmWqN`-8cT>;LdnrcGtxBi-7O({>FyqGJ<(_E&T5I+>ZUvtV>MDWU;BiI(Y^(Fv_;wS9 zrF#8vp>3A(eKq{+WL?1j%eO4#1Yb3?bQ#r*Kmlz zx|pUHPvE2&iY|k?h;gg7)8iLsO=Hw1^wzdbN~;=Hm1+4h_KHlE3awJtFonbkr=aq0 z8keL^rlHW9lbjS$$6q?nRk6(C`^>3n1Sam+9;6;<+n2~lnOqewP0wVC|#ke=txpm5+xukd>Lwy zIJ`$nLDa9yz2@E`J(@f^Sq7?^&)=dty>cZtWJ={eP=c(S;0dX+t+|l}J0o8|kPuU~ zTOuYVw1p->B$QqLHv=DYiBfh>E9@;|o61!Z5_1!x@ubOmnRrt3KT(T+Okzm6^~tOh z@5Gch1^{~53pw)Cu3(4#ZkPGj7s2YtsIOYs#?$<1qKXFU@;4hIss~d{X(_C%bnaxL zIev>l+RD@zrM%94kKc!FVXvB8*OQH#6*G}_+IJ-oFX@sM{)VwcJMxkrjgQa* z7siWJH?Bq1iYxu0rRU_7vX)Bh2)l}ayPN}zk9vweWK$ZZ`c;j*DGCshFCr#mi?(6$ z(xG|j&dv#VdA+e)C!-q^2NwbtN~+?0m*xN4sv>8KARJCo1GfL-eF87pHxShxw?O6< z4DiNj&ug4=(_mFGmJg1%8U!5YH6cED9oDw)4r{UqvcSP)M3>?UQIbPtk)(gEavyk1 ztxCtMghy@YiPeg8npLd@VJ7EKiiafV!&5?eVt1=t<7IsneiQX0Ni_ytBeT)SLNw$cGsUdqTPm}XHs@|bZ3nG|vddwgW?ld37+Hsy&VXG!dk!0{ zIL^XhtY5FMyu}bcTEGGW$rMi(s@e}H1l@6wVa@`oI-wp=-5$2zpIxA=NG;T)88MPC zmoobjsHIs<(tBoMg}@oQAOe*MvQj;sr5H`arV-U_P0^#B+#)RNbnZ5GB_{0S_qAS0 zUtyru+Xzp!>XJH}i=-arW;e~54;BM?P}2gVq68XZpkyDT$J#fMmdq9O*p*NO$B?VRb&VE6V*}H-@`DJHB_r_vB@E^|l{Ri!QBApy zAqpKNfH2t*df;Z#>y1#8%nr;o_2uk)C%W>V7m-%8ES&H5~scv(W&czMClY6VJTp>>~=1=$|IXoL2T-QjAgrhjYgox2=0t7OH{lo8S+ba#(@Axz76KwL zndkiuSa!W6<(ige8fca5?wlx0xNCLTutZo(L<6^NGaZfmQx3IstNkN;NORl7WQc#8 z&1DsQ)x-A6sT$+iu1BZ2&P#C)L+=O}wdocnJ2(W(Bll%z=wN3+EAKm?vKMslM_h37 zN>QaAs;a%T=FobQ?BZ5RLAmUL_zkpBtf583NS$z)WIwch$T;r~U#|pl-(Ng={QcTt zn#0+bJP^vduxd@fNi@Zd1rp_ zElkH*d@@#&#_{-jn+$jVpl>-W%IO#-OKoV!F#A_b+vLzh&M;2+& z?tC+26UE`MVHzvg>8IU4JxMbacey}H`{YG6{ggiG@pwe_$yub9gQ7lO zZo)LmTsQ)z3j}SQ)UBf*ElDbVj%MA5wZw=gO`LrKIXn5+f_8Q;QMCEB0`_T?oWorK zy{ZJl3B>7AAwr|g!}W6~YE~_1GpBZYPzJ!jMKISJgb&DBcoMVwc1`qO)86L*v$qB` zEO#1S1;fzISeDTc;Xu`xkCC$$b1gb|>?vYLn~m(k2lTn}_pC+n4#u~}Jb2|39#*I0 zwc&3?5Y1U10+LhW=B=h_0?O8Q9`vt#CUyPKMavZ>tTVY8W@<3l-XGpf3BJ-NIQS`A zNQt#Zp3G6AQ4kHX&*^J}EDi*Pj$(||hv(r)4h(Z8Lo@=g*_y-@Vn8qPO~Dyz>;fb& z|Dh8{wi!q1t_^tivo^(V+72RYQXjrp)+Z%cc@v@m2P4gq2A(fr2M~-fQ|&kEwv3nQ zg4vC#nexPt7;V07tI22r=+~yy#n< zinG*8Vu_cIT-3Z*j!3on>1g6yUgVuOJ{VY2D0j62!P)t)$QwZ2L!*DMjoa$Th%lx#+oc{G0A>j~)dt2dna4D`$@lw2grZ4tKHr zsUK}nF8WC=Ww}9*QnAt74~%FGFc6E+rld#Ax-5NM_ixn&mzWzMghMD8aET=3Lx!E- z#a0N(EZ2RN{M#;Xi4lK4#eg7I_McCT3XTu~_ab`d4j8;^5f}yZt9a-T&h_}PA4a?B zs(k7!mZ{dHc`eanr+6}(7i12?fYWJy1? ztfnk6J1KjBO8DMD6}r@@=msLpG=>0r$Fv5 zI6(qIxc=8ymuUh)6%3O^Q~!EaNL3ru~`7)U1$KZUlHVl~auLAjQbN}wK0jjD%0-iSi8%YiQ5sVwR*ELc|&E{Msq!XcQ z!F5_RzaD&UR^{?}mAa6lu2H`?XvMV~3lk@kiH-Vi;F&3liV|_Ex&D+DNIaSOAsu<0 zMSm9|*{|ED`H<*0Cs@^`oTeB#2o*aw*H8l8Z|UeB%&jt8^#dnv57U4?%s;-5fRm!P z4o8jvdv;W9)f{i~S&vAZ0`ZQ^qIej6tc`~|O+b$`Eao06dDh*0=uqn-G=X^(;4#($ zM)~M$q~@)t4r!W5C5f*_{LUPo5Fj@2Vv5_xBsQ#iX-VqOtX!Y(D}#+6?K*`QsUX*=QEZ1JC7n-LEPA& zbi=h*kg3ZSSbMANyrD}M>zrSlKCRipNkSJ(#30AV)AQBFO6%!R?Sq<(`_*@IZBDrp z?o={o@Xs*dCulITGnKF-U&6|shn99wA5Nul720%(ZB2vuq+G(E$|htHuymwJE`Wze zX;7#KZ*U!P5_&k6Xz)R$UNiyOB)Cjkq%-u$2gt}fSFQD(&8?xS zD`X55038H$6|qgq<8FZf@Enw=<V4H6t^)0d*a(-&0fE_ZAs-01_!wLqnp76$3v&!9%PJ`OKO{@WXX#3?BzH1e8Jj}F=Q zhY#CB6E}^9>GLw@T03RT0Mqb*sZIk)vu$>vw(NYlHbtLS72l~1>DeRXXs*MIqgsds zU*CJ zat=p!FoOa<;1Nf$*b4qfzVuOBeHyJw+tQZG{Dec`Vm!BL-d*xD4%j?(;L}mE?#l2i?9nn{-;>&k)!Lbb5w{?-U544(+ za`DzlmE=~SRAE&siX#abDi-uKZxK>jM44BKF?jQh$($1R+t#@*e`xrW;~6eOn2-4n zD$1>~?-rSSs8EEk79W@6?m3h7CC@1bcVyj|*j*@)F)cXtirFdhIr$~67rZc8Z=lE? z7E{4h`f(xGrDyfEVDhTKYiD6I;j1JfzP8u??|n+x;&K^SAmC z(&Z&IA5aU{6V<-m3I7rmlyXJSMx-d-a(rfWsmHbbNk><*Lw=RJ^SKjrB_oRi&YnNU z>>wvIM?TjUggv1SBaoH<0m=0~bzqf!?(7gE%%19gGG`Igl|MI@k_FoqzT( z6{Ou~wu}7V7j|kx}l$Iz>8Z2&u1Hro-C# zAG`e8o;S2kNngRwoQIMU`LQfnFLx~&z5^A5r(vT-lI5+G-MreHV1uJM83?$*;z`nK z0;Um_6P_(!%}xr+EuO^3l_dPZS{C6onCNqy~nez z;?#Rhe}rHM=>$Y7+i<>do*;n;w=MixbyoPb1^WgZ!lQk80-uafM}oEYxK%njZghO{V8lO**~ zCymTzYQ$D33M{@jd7Q}BjfDbLh0#G_<&>7(q%7Ub^M9(fuRd+z1(Wuj=={QCFOM~y z)0%E|^AODgtdalGw=;bnE0P8%c8aS*=vTrYXotJux&hhV(5kdxxbFS2(X)sp)GU*% zH^r~0pwB2h)Wp;d6kTva636G(>9j|;2Xb9>_e3<#u|;@(z#n?gT9+;=7~#1^%1NxMLyzS!wB1-cwN2cM3{D0&c7 zCKQzr+Ihq+w#|As>Z!1p5Rm^`<(sCdD0ci)9xVI0y;hi9Gt{S1vEoHSzpY`1O#EZx z@a+r>lDJIGp$B!xojGUaZ=V2OQ1*}^ZMaj1KbfW}M#7=CTMmX$(e$jNwwUPFvC5YU z7DM3w2-9n&wBe)vLW1g&8vT;NX;y>!0?u)jQx^b zG=c}Z3v3J^{SbkKXM3@8i1S?2c%#4d{K{~+SMzPY?{_u+6!2~3(nSBu=ep|EEmk*} z5sF&re$#nGx``o)&PK?^=MeP~*Xu;kPHKQ6Xq5`PtHD|1`p4BL&e-Xwq_w0 z@$d!rUSQv@FFVkl(gr*LHfMZ`#;RvS%*$ghXW%l#`dt9df@7LBQGKrtXmVZO!FK&E zrixiR^2`-xfjSrgwZ2xQ^tJCuK8~W)(!Pkma<)#|5XZiwHiZ`LriyegiAd_kTvlTM zs3=%N!0T0R0%?wUtD%k;iSW33&zKc?-##W{lvi}a15(AZOLoj5r~oiFBmp}apF322 zI?EXQCSz|S;;hyGZ))^s^WFPD)fs)z#*JKXA#(jzvvt&ckukTK{!8y;zR5Mg6LP!( zHG}n^MJ1z(R7{%_-(x33?|+Vk7Z5rzpYUxlLZ{(_MCbKBoCCEM)^^-l<<5+Bsm4Ev zIn;`z(rdu~wTtYwM99+PL-Is{!Dc}QN?URMf9q-~36$Y6i20}HZJl0HwnN_UVwm?i zgdsJcAB$}1O4*zx;UYRH;S6feF4p0z1?;hIjYaLM4L{`7E_$Q-c}Ffobh5-3#2JbS zIO~D{^*`XZ317A)zbCVGeFiWeGILL$#k9`FSmdP3ISM0XhrZ1{0+Xuk@3jL+~qV$_v` z#k~egkt<63bLmF9gB{~-mKO`tE00Tgug#8IeP-{D9hA}+Ub@Z2BcDw6t`D$jVVAET zZQfYs#a^so2An3D;dQ3#GzJQnJtrw*Z zIlQq$0IhB2&2N1fB-w5_FNdd&yzBjj8}GXcz?XZ>sfo*i($$Rz7&yG9Sb{y~vF zN$_S8do7We<&=hfCq!K==AK(tWA+R|!+9FKe7%e|WGRDGywoJQvrDiWIq;WZ@G@G_ z-h234&{h!JLFp-(139XoK=zMo{Pk27m7y*nMz{iJYB96mL(pd19H^h5O^4r(2z zx{Y9JOHP%AUpt123hJl41_85t5CevJPm~28zbG#{yCNRL^RD>4&!+SiGEqpsKcB_B z0c1q!q{3KHh#p#tx=8b2r76Xd3nW;nHl#zjLTOL=T5?x|vx`-JB^RyE>?w~{m*<-x`?SjkfdolT-fKwJ_=Ap0(UAj7I4my5QtR0rFp*CtJ@;kzg~$ z)|JrM)pJGhA7r;1Hy?ke@6`o|?=;vH+<7G{eMn-o(AxGg-&PRhkejV69K++}1=2t% zn0gdSSpK z)BiIN*GM-|VZJxaZxPj{K4m2jm|w5PX07^NawrOH-7#QqaN|8OPL|_Iv5*FDf;1%> zygLaCqZ^3L^Jlt=O$es-teEXIWX~$vGeO8cp~J{p*r`V>y4^-HS2)WTv-%zi5KKu4 zgRAn=t6j;7sgI^Y@~M>*ENhP5f9W8?GT@8qDQ(#bnJv}&7|TUsZd(IiOh?PfZ9>Yt zp5~`;t5JKcTj2zv9iiTX{HAV?SAuJj^NCw(d<{FtDl#kjBvr!3_VIUGR|gBOYrpnH zxJDInl_bV;jUQlZ5y-vP(cRe#!a%<)g6$J8H&YveMml9Ih&0~>Al{~YN4MvIPo5z0 zP7FW@BgUN{&>8Qnq1q#4KT8j7x5i;N4cl4M(~yLyfO$`S+&Ht1|! zp7F6+qb~9bLmR6cSn`&dV+aS47|>0w<}GS=>G{)O3|JTif`$Cc@1mwUOh1X+YFsZ6!A^ru9dD20$bGAnz}04 zmdA3n7Nq*snJZ?}-%rOAsUVIPzcR{VIGkBWm4?^@^~*zh;B*SdiAz%Y#`!=nIa7~n z{-fE9kdYGW5=rOr5p4$DU<&7`2cUC^6b*YxCRI@OSSXtvJTf#?HtJPVWMN0iU}2!f zxFqlc6wF$DxeOu4hR@)lc_?>a7-Uj1FK`Q}`y}b~^9S1?a_N-Ho8&-bz}Z&Lq4N(H zX$)RCMmJG5s!m!3Z2Hg%Lom!|7bz}q2{K|J^P>|1Qu5chDiMgYmte z>6~T6+=a&V>3a>0`@u}Li|_kjFtCXhn8J>TVa)J_Ooi_AdT1;o)eG)<{vMfTA$hfv zK3p`Q(?h$at-6#%kDYg#QFZ{2emDL^zh6EbRpa9mtS6!BbOt z56GO?B0azcqng^Nn_A>AdacY@j-x=ZWUFcUJ@>I(*+zn1V4|^ImK_$Cont zUI-%CIj@rm)$?Pto$xOmZvwpgPSSt`tNHG7oc{{~IlGZXvUl&g4BLvORN+i*Qv_+S zN5&kXr9dc&_R!`(&0qL(zr$u$>mJl@;J9z^#(P8am;PRmp5;tzi0Jj%SL563W>!Lk zA}=p|m~`?Ch{Kj8)K8+kW81Eia#}Cr!|G72~tT(l1$puDOy@Onh|L3SM z%-agE1z#H=x+Zy47Tyl2K7{&d-1Zv-g5*m)oSJHzb}q3uxF>CwNl`zez>|Z|P>bt` zz>9z)KM7_aladXpnG{<9%SeAFJ!whPV$Q=JjY2cI0WI|ei$Q8{*au^d`hb}2<5gMu zakWhtqlGlzy2dfM+&6`~@3_p=wy%q0;>cgN#M0lW$M$en%E=@eHBa#ttan-|90T%>>Nw! zwz1(xcfi5eae#MO8xEQZlVZc1$WiE>KpZKHSdX1wiw|`|Eg4Ym+XiV6|lY3 zWzVQgEaega+*@;cvppVdE=N$(FT}iHWI?BufENsT-mRe|JHncLE17a`cVNz*brsdE z-kKcX%%_Zg!?~d&h)*8`v~4u$s;$vSX_g9Z#fbE`#mZQ?zaChrX^B1lc#a8gJ@~*5 zz$~u6y`E{$L*)W0ry4V4Gx}-a99*c_RD3UF^eh>HtLGKzByi3jDQj8Xj^XK2n(I)F z;-|k|LnzJ_J2oRi=m(1|EU6xhLRj!pr?Zj4e%AZ5TjRMVh|JU!(mQo-7)UniH08^h zoDLnJ=P7ia6Ai{kUz#oyE=OAIRmID|&J zZGQ{$9Ds`mF4UIg*V45ThnxfB&1$HJLxih{OHwPySVZ%zL1r4bvgJ4PVPX?BF+7eE z-%klDnQ5H7jJ5Ibh>t(-9h~itiSYG-BtCMEl)=w%wGjMT?uY`L_Vnow@iyO1y7RNfmjVmPNm9y(7dfQkEl+NKdO2={**J z`KLIX9C@=_Mqt;0&IN|tct%vLk@Pn-@dbY!*6?cpPoPqQo^tYfHKPPZB&$m0?)Bd9 zVxA80=V^FPlC9gw$IC`kH>S_$$O^Ti23u7a=Ij`a@Yrr(Mg|v>(bt`zXD@IC>MT^5 zgL5PXgWKy@36UcmsYXzXE%}-e>Cu3{0*>-2HFZPB)7Y3x9b?88;w6WHBeC`10Mm?uD!|FyX`A#&sLTJSRlsF!Q0o{5er<9#t;bwwaGC#mLo3E^KLl{V zcj5bwP8|lI+Y+|GtGlvt5|E`PQ-q;XJ=N+%CE2x*9+&Hp;E;@FDh21JN=%=>BAn zNE~QO9~tgI+_~;kAq6nbRLv4&D~S3;JjK4#s0#Y%b3e1>u9Y%{|rNtoQk}{yntec~0sc|K0qak#>|` z?5Z8pyggHmPw60Oj|YOG>kzL5kT1kj_K2=bMK&4QV?xGI0!a-0jSM`zmR2BcVLsZF zDYCT+?UGgFf23EL7ogboKH*A*pOl%9ElT58>e4CFR8pG&ms>6mIjgpWmDwO1<7Q;~ z>W@XgBFXVhfPO0Qp$eJ6Ycun}xNw$pe6MrE`X-DjXEjl`E_R{;?z7qyPr~}8XO90v zA$~j0Fa77y^K5ZR>}=43`t2gPSum>t`Lwt1w2@yYXv|p9K)|12VvELbe2F1O`T$iL z7~yW8tF-({bvu2CJrG9dMk0-nrE&&fzYFh^e&d=V;oO6XDFcPlk;S z{65^Qp@q|%QszihPLgN$+@#*YV*OJ&^1pA{4U4P92VLay)}#iv==_RGpeWU99UzO2 z<|jXhp8)gK8o7CC?whPF#bjQnTZ*m6#=c zu||BV?fEqj%ynP=p3jZ|Jj&Aaay49w3~dB$KzAse7jh44x!yGVj}p7-JOHV#cBY{Y zAWWV+cf~zA1P)D`j;9;jlQ-*Z;8aqkkS+?>(pj@$)3!-6U^1cXYMm{^B~O=|waNwU zZI!M^ss#f)*nr?*0l_(o9rY!;*#xuP-JEPF4`G0l)Kf9+r6E*j79q0}&7PeFp!LY|X?y z2|;wg)@i|SB&TIJGeZuKR@9w+C!=UeTF1HlDK1C3dNuBB39o8 z68(>DSg>S>G)Cn05=?W(Zv6=y`Tq#S4>j9$<1@)+TZ$Qx4r!4g-8T$ZEi#9TZr>v# zm2z9H?kSy3;`^TH7i=;0y55#&V%`1AJn3jhu=HVo!>qe;9Qp;;cgnB2nNSX`L1QIp z@Lp4p^pxDyIdTt}_I#R;T}<#zG8|e09r&0%zz}_MhUws!P`uiJkAF+VhNb?(e`)2C#{&DVQtn}rC zKpo6=W@d0`OyL)XjLuqPnQ@8 zs)sVNtG{o_I3P?P9h+m;tc$3Ga_F2j{zkweaG>f`h=2Ez7VQ*ihv2-0zx|~5u22w- zXUjK#qm<){LIh|QpW#1FE6RI`dHBo-P1=}nq3^DiWzk*`C4W(Di>L?4gg3|nb{v;t zm4FxEPFMvFJH&$ZH4Sl*?yIvzxjMrWCO>}x^`xosz@b0$mjqS0j%?Uak^nbZf7b?Y z|4l7&2d<=W%;9{H8@$O8*bN78WS%4dq~o1v3tb5W^nj}_Gqli4Iu7e2c5Gk%k$%R79T`S zqrwh`W$UL@I=-;EA7~`~1ogN1W@S-J==+^XtbI?WJW2t%nt*oT?)oi;CDu1A)tLh6 zH^ym!wM|w{8ocp05afSgZ8BfBAUbHod*)TInL!1Gpf#xup=O1mV z2rydDqqDdX3p+27MW+RVL1C4NlI|jmX_T)+NDDS8HKsJr$mea#YX|G5NeKqb*;DlZ zxyVkk1;oL)9yJP?u`2779x9=Nb69fZ8fEIh8!BUaE%?d86COE`n0{orodB~23AnerKD9)m2)z9_Md+>1K9#n|4{zyRc?7S%_)@fgUD*Y*!x&mzvH?L%&F=`Qje2wo2%6V3aqh&FL zpq=gQ%dP{z;VA%A(G%nsRrJxJm_SXeJdtIasO^ITdJPc?2HREDRJ`&q^J0Uuw0sg; z6Hy?A{2e@B*&L`Hs^GOUkk!l3=K0((iGdRVJ1$xJr7`;U^+)<)-j>$6uF`WH z570Z{BjCKd`6Alcna{D{`{pWN1nB%gqK~rhu0i4VrBTAVb5K`P$PpGCyx6N84jSHn z`w>Ivy|do+l}1}KE^~KORCs?eitgBiET2|bca$LBMPTG1Ikl)3F7Az7h?yDM{fi;; z&hvnTxq)~H`1cbF6@yRDCkq?ITIQ`pan<76Sm4OdUa3qDjr~J}L-!6`nuO0{Hr6fl zqOX>4C)=?pu{+beH?^F$TGVBJWktPDp74a0erlGjCi%PAsJn!T9!7u*&vqC$oVXCg z{GEjGyOpz`!$6ouV$15X!D2|vO#HpvsZ3?ZvK>op=7pq!+1ohD_}e5_nffGrh0D0A zU4-z~P`+2#b0LnJPp{K2(h6$Fj}Dh&%0kCRAYHtS@0`Dlk3}Gu@>Zb?4(DYB&2+pJ#H68k_KOEqZE%!2Unui!w^}5A$GXZPz@(t=pUpb_4JPx^-SJeHjxla=hTtL zG^pJem&#Lcebirt26tuY*I(xeqEqQr%0pJtpY7RZrx9<+t6Nr3k<~>Q_LfwB(5yEQ zcVRxnAA)kXlKGgQdLfIq+Tem?0^>U}%1XCT)g>IyxaSk=B+u~%h>E~;PeKGwkx5B`Vc-)O6GnI5$miNFsLH|5Z*kapDF%U_~!u2*3m%4=S-6k-@5 zoKCi=zs}v5muJ}U<}a^j7sM6O=70=HqzOJ{ECoaZCx|34*6@jVCq2 zz|nglEBM{RzUCt^L{1O8Y+>B*dN4)C*Qgj0niA**zZLAQ)3Z4w*YIc7&`r*j8j_lt z9vk&KQaUp~Q2c)#*j6<58=>hF{F7oLS*jd6;`wsd2Z%}Oh`mD_o4++&tnX6)7MX=5 z;8CnzN5v=mCd@^}!HMe23`iXPl-Y*uJJEU*#OO7G8CCB>sx60VT4cC#ET*WVW_)QK zeNp_QUclQ&?&3r&oo^pfjaUR#*RLwV_~cbWDB1Ea2iw#faApaZ>ON9%nLWpwbR-Vv zul}0&UEv7GP{fp`9{IEBy{M9#6QQ`Lm;xUpm(}k9gTI22h{mrd_p4cFhl6u#kO(Y( zGkGV>w#<>X7hMBPVR16v?cUeruy_RLLkrqvZ&3l_xE%1H*23GEEnQQ5u7FWUSd)fX zhe!~>G-ab}mgPMi1AA2kjnK4#VZ;)yiwWAcJIE>)F-NAr3h-7foYMnAD#&TuK;&=oKp~V#%+MQdSEi6~5H#7n|`90Ap5DEXO~A`?zHy zQocBH$gMZk7v|&eYXe{#TCHcUX9pF^%oEOU-#B5Lyu*to+CkvGIzI=&%AKHpfut0= zFfZ5+eXN($E&yvtzSH2o14VbOi45x9C3#WaDZwSaj%PjLk=Sc*CmJOa@-f2Se?Z>#LgSjo(P++3*x%!Fdy0?erRWH`*u*GaA0tWOAfm3(llx~XA z8YjO3-^LH;JB17x+r#MF(o4A)OwX3FcsbbyMp9lWory72*f-d%C+VSZ_l?Z#Xi z;+b0tp7duw&Ne(Oj_}+zSR5AMBC7wR7X`JG@{&5s({vWwbv21Iy6RT#C=1oD)wz^*d*&h_~VUrkpk3*g?!Rx<%r$Y#SvTN3HUUoy$By^QD>;Z%yewzuFi zpM(=FcqxD%?+5y@IW)m`o^N{w>YJWu>EG>SH-XBSdD}I)C!1;em=!TT2%V ztR@X$H2*4B&RMH*vc@UB-wi5Jr|>hed~qr}C4z6>z1I1ID?PeSy9m)vABIcjl3W-r zm|5v-6|!vVht7S~3EC$bF%+-7pzz2ulTmKgam#Or&9_yL%WoN3%#Jfk4(70t_n?x$ zlZ%SGE%Z=*oiQY|z)QgqFoKFY>jUz7%7;&(}%CZj?jEqW<|0V$wdz1PWH z&A9~+&go_3vFfxMsknTmnj;rU0~e!`e@Yf=@6tSLwShRkbm2_L+mv&@>NUFJG#S1> zWnoWkP0Cl#*6RC=f6UImY_*#6$eRV>^Cq*CDFO4Qu7P{eEM)KcP zXQ%@UmwL!H1w05NcxKOp{%@mc4_CRd@-G9fg+6p|?rooo~#I_**m-zz+uFqpg;6XmU;9(Aw@7KDIWygL9m2V4C$?Cv-&j}91+m!4vb+B z@>CKY{tjYl`tw4%cwOdriQ1R z%#MazwL!O&v)~^x@!mF2HdR{ATbaaR*Av?r?^6Zr5CE=omKcGU!_4mqHbA{7@K&rD z=NVlG>|yqveR>#}Cgs?o$uKhCnVj`c{B>Iu3G$nd?7OCb`+ zc2`MuW=E2plMnFhO8s+!O~BS^I-dIe<5R5wvc6iVEmp+SCt-5c;gK z4V)xeTzkIYnB4Th3*pQ-3(sd8@NF0hXdZPJ34l&Jw^caIkeDyt%(!Mqd*5e8d1McX z8+jG2?F6;*M-NBqG?yabTd(_=K(|0SR97mO4v{J{zxE0e`kmF@?0n~U(wqHWo~i5# zZCR1vsxkv4WK^NDv)8|;TX2p+OXSmu(*}^WSz7vNazG*<4Hdi$1l>ay+h}5pkBS?CTFWN z75S|8m}Lls)EY!+%RI*dn0MJR7KBjnLTW18-+X<(11R}$b9RH3fN$j)5U^@Iqu1kd zx!LW39jP$mhP8@fSy>;`&HvN_6Q6q8EM~*rryoKxS{Sg>onhQu>WebbKRpo+IMfo= zk$;U*h5MK%AM?Rpt7HNG(%^(OacbCM{yZ#iA=c<=*P|06D>C5CFTa{RfAi0-oL2*sW#kSb8)0bL$j3DYvwx>FCp0}Uo&p4mPr zq2U5`qN-O8soVs2pj_wnmkyDOSsyt=QX&+IJ=RRu$Abq6TlY4DVO!rrC7NyKf8gfD zklD@`5loy2jpuomA=>K6-=D|x5>$u-Qh$O1C-hWWD zdOpAsD~RUdDbF{_s9^8%VJx9{z4Z<{R;(r@`G{*6Yb{2rK$Zu)X$bRP*a!*S+_WGk zt9}f}#Gu;TOKqU0(0%q@Yj$a4T*YP1H-X-bh z(mnT7NsFvU%PlGNLLv#T!$2NGZZ73TNvOoFixm}nY7Trd*`gqIdpW@F=0yX z+aL}BX2Vc)4|n@lv}zp^G^=cFf}sts;>&3t;0C_z?1xIbaf{^`Lz2NSth>55$5GLn zI`K8C?p+LSdWuoQ;N*|&?4k5jY*c7d+vsTQ=xJ-Z-v>EMgR*$B{gR$OLa)^3MEAGd z$5~nj=SRs;18*anZ2D{7MDp=)R#;g|u{#VD?eNP7V@iTxt&QN{RBHioy*~2nErQQ` zGY!3ME$}Q(xqh>l#)xah#r=3YOQ$aRTs0jmw|yXZsC92$F0s}U;A3aH5ck+*r;^M` z-pYW@M>d#BMCM*vS%|4ZvytJDM1X?fV0gx^!$O;0b&q<9#6GK6J(N^H-L`{=7RKA- zGL}tA=$DZA(HMg(4&0Z$-;1SUeV?Z6aNI*NW&sNoTZea`g?TnU0y&iJUW)@x6USO zccr7VPK4|@v+DIHOwoGRj91h_1+dyVCAUXF1hN7~%B zAse(*g^0&d?4zK}6!Z^3`I>xe>)+OTd->5WWTT}yR1UlF9!=))PcoDpSS1@qS!jM5 z699|O+h~-Z=9->Hv0E2qD|Yq%5STGr9P)y?uDn?IAP{_&0A9-6kLWQv2}i$d5a)tk zF7D++OFbtlT~3{T!fRxDv5S#e8<|-Hjd~RVHt8u0Ti4g0{X;YR^*V1QcxujlcpGw9 zEIIK?fpSPg;HoHgvZ5|xARZ;#0?1Z8&4J#=a+2QDD+IPLHb5?^nqy0ItkQ;(X~26y zr0pT}W@B-|F#}oKcqAl=;?W46w_xK3NR#gZKjI`qs56}zTp4iJ!m?OcM}KGzb}xRX z=TIg*`1iK=eyN#Y*6(oGYk6PZh5tL%cK1oowz3@7zX`|~+H;Hi-y*(X$;5ia2kBz2 z{s!M4Tp$eW5>fP<5F8K;TmB47q?&>MP14B<4WgT~umOc#kaG5Kl56tq-`8%NBN?kS zr#aRUxn+>auL zORKCThPmJ0=Ydln(i7Vtfa}Xd7k}>QJkUko{iGi*JL5pi!OrOYn@P!XH@ng6pnekk zrvAWN0TB$&FRcZ6pzTU?6W?AE5YIinlOQFfc?o!Z*0JWDEXss#g-L?F%s@Fg4DH%f z_y~-EE(Dv(g|^RfXr1;=y(^2t*eJ~IYYAp1GhKty$oaBk+qn2i$@-22XVs;Dr$;Sy(z+5!9}l~rS4G-EGivTqOUFF}^j zEpHRspuj@a`0PHvxF9Q(Q-+n$+LP93hS%_8JYpf*?-Qg~Vmk)6_uPD-t+fO{KM`CS zGuB6v*+M8}{DwBIN9)P`t8#Fg{(>);h<}*A4onjbzfIS0RtVgCooU0YKz^DdT?!;3`XGF8x46cb z;i>yJgAYChdx~oH2ytA{DtIAFrw)zfu3wpT`0LBAd~aXp_%O9BoD4FP`t?@ft_}EGgp^8LG>S%Wo9=pxHI&=( zKKC`oWd=~!qY1QyI!$6R==ft8(!6bsE@Av*RhjAi#m#3YY85)H+w&#Uz&{ocY`i+e zkloJ924sFploDQlqH>>VAck=D1^?xuh?vlOjY$52*cLAj%_io&K9=l-o#3rr@P)lo z7^OA_jA#R=^(GaVO*t!&fy$44C1HqnZysOlqxeO`fmckgA)FF;IJSiE^#|@g+KxSppkG2G-INY>?_l}=*#4ay{FBJqBo*=7IF)}s zabDhtrT%EYP&abGUs$MoZu@19J{HLHOiLE^Ft`H~E9Z@Sb+#r@@eLut)rds#@_%b+ z7ZM0NNOoB<#Ma%{4f-8LveP7hAbq31E~E@?jWu1q!F$6oj{U$KTI@v8tJ{;P6j*}% zB`2WYXo4HtC?b}}+d^Mux!5F4;wMx+Ew`HK%%!=64{9Qq-x(F%EQg%q)o=SYfe_G6 zSyYeW1)|~G?K#g}N1>lDJ(sy{Ef%esmIo5(IYJ?DRm5<-gmPl?PHG20dFU(s7Hh4k>41X-qLtX< zL+lYMia-buTqinO4`}Ac#XUJWoC`*JLjDE_G-v3vppepcy6O4|dx@K;ytGj|>~i$B zqvxau<+({Ke(r{D=fFr&x2DOJ%V~8sPA=p*Kcnx7Ku>qXMkiV;g71h37&-`k8O`k9nlHEnFigqIZr3$7ugIo{#~)wL+bg-N;_8N@7(aat8Qn*K)f zn`1-7GPWxim3E{`Dp|jr^9{~RROT=E>BMGZ*-JZkyU_yedEW=NMRbm4CGI)qBX6iU zo202K{-CMeUxM87=v@=Vv1^^KeOIGef(rbRMVS6g2_;&<6TlhVBi|`}p`l!ET;B|g z09!G=GnFEiNXW*?@%ucKk1)0b`N!i`dPbrQ9YDL;$SkXCDs~GdJ!6C1TW^G@X`uxm zs@M;FB3T#&_BN=jA9;aBCuyR4HtM$1_rMU3+eM36a7K*e4VL# zdTB?hPv>9*h4_YP*l1PgbPfL7GU&6HdYo)3?FeTFT96wE!hIK#ItXv?K(TzgE zi)+O_ZxY3#;5Y7s&+*;lmP+WsYMYq+q~E~oa_2Lx0>N|{@ET>WyJGA=mmk+j3(p$n zJSDkjaDdpSj2D>4^7*Tz(*`qSC*`D4;YY<3WW>Mr5!+Wm&6tqrIw>waAmlXaim`9h zxvvqP=tgZ}6Up8%jbxhl+CpEE{Yjj^mMxOksKkz^h((&B!XVWn50ucV2E%N#%;M1G zOUWo>%Iqz>fl!>ui&wv^Sc&}31MB2FU5hcUf*H2kY^T>WL3oB)h9fVS1<7DvoKQ@2 z5S6l9e&XRa3Vq($3Xk$`GwvKcEE2AmQ5VNomd&-IOLa*1B~p9k^DBdoND3j4euCVS z61|_}sYKUED_qJSIaM+xv@L1!jATG zce?hs>0wya%>a1Ju-#)IkM6(@MK9H=Jh9l;si*oFhZ4Ir_zz((De&u zm+|QdFkATdi$Fwvy(t6V;wso7(Q{sJ82#AW>^{fN1b7vI(xjr-!%?TsseCcUcht`dj9jAWCJ?bXibG<fdcrpO7VJEjkQ;NaV35U^abDey~|o_S^eY z2oz{CXdhQ~LQA;Xn$$tFCh`QMmB(c3(ycaee2PgGfoP~tB=tS8e z5;ZOwmlw5hjx8nClh;gJi6&j5L%J3ksUhA6k*e2$2`=$tnyr&VDA}=*+zf{BSb)+- za5{q2A=aGkz|Z-udZndG@}$p1KeZi@O5HuGn$^u8-5tcxfTp(EVD1IAaomw56qVZf zNP$vxO4f5q1WF0YJ^0kJ80g{S@z4972h`X>KPou49rK6$PbvP&!R9=X_Sgzb&71g1 zyIQ3(lPcGpp39h9u8zGz4YnDrnK_Q(*N>s8!t(tai8@E^>{0pDqo3A_ASfjgBaZ9dR0^%*Qf>Tnz72GPkc7f@Jw=0%@r2?ddFZT6Hyv-md4=Q;Y-^%Z=8pS_{#iX z8G@PO8k+ByhKCJttBOuPx?Hw5K8<$(T;D(6jANIc?n2|t>ns6Hp`1T1L77O`Y%{>0 zpUUqZRrkZ~N%eG1w>&O14X1v!nl9lVReh8QYX#xbP20~!kMfek%lXktSK|vwkZ}X6 z8%_+Ox}?&Dtmi0ts7t`8hqMvHgKV!*m|BA{M^#=nSfZtNf2)5ypnT+&j|#9rJZfSo zDpi(+&_=&GYXhe|3Kt2pJsAW=6dn7?LIjmK*1D0>DTIWI<;%N2-XZLfcM%1nWVo0c z1YJ@BJRPy@;xIiY#uqP#83w*4pp+?{<;P?hcte^cF3^?I5v`Aei z?-cZBk|}X|7d51NZAZfGR`>IFJku?aMjItcO7(PO~FS5rdRq^5`UF~N8BMf z@#uRl8G9oS-pQK;j}+kgzS~Y>T$oeIipJskZ8q3&0IeS9P9)6^8$|Zn15?wYH!)GNni!Xc=lGSVK^WLY0Cq~}X*m6d-6wQ~%WM96kJqT| zxN?!M5e!ec7S4TGtYwwf=9kB{cdr)#7DqOlL5_wXk{L->m{aZ$eg%H40N3+6Kz4UE zAwpu|gZVa8e}YzX=v>E-Ov*_AQ1HYoSti!oC*Xep_Fgn%O#iC)WS{!}!u2Fi_poZ^ zCWQ|{6a?^)7lh}KpJD^_-2v&OX6E@H{DQ>(ZBOWTR)WuiFo1{mA>s!vz5)vg{9 z9#*75E#z=N`X<6ZV+y7#657IZe>gNVgwg&>_=_Mf;7P~Oo>gQmXBR8hk^(dr!JRMV zzQ8C@I~1|h%jl-FjXmoXUi@xA^?#(EsS1^d#le2X*0(=ceTV~Y*{v%#Y{n>?EsYJh zVWx!_tN83gVL2IUSg8r}PdSxHrIP9-t9;g5sJ_d)z6b-4Z%DOsrjm=j0SNX3;#^V$ zFVmFAvIdmA{g60ryY6Nv&Wj2|C@J&?N_nSnCO){sk*-)PU2T5x5@-6MqH1M1B+Dhc zzBVG{Y?_|r(lH(iLwIqbak*DXJ&Zq|X*D%825w8V`ewFI>oHkS%fw}sD#b)3U&i-S zM04Q1%RvtnD2BuAqU$umMvdd3w4aeq=Zp+-VE`7PI&t9NaD|4=26{MO(+Wtut^|W zGzyp`DUy0mt|wF??OGALZ5-@e*=zS-I@m-PPMWb;T|w1{3Gz{}NLtjKq;0#>stkbZ zM`trtc&gI5Z(ijA4t+6&70qB)jsf zV$p*uwc8{RfcPYr*r93NNBW_&-+}3rRWSn4OlK`I-mo(1L6{){ViFS#`?pN1Voy(l z;x$K@=#jrCA^$AWXj$32{5cGp5~)*W(Z$&PMG+1+5pE16XWn;pB`@eT(uMjF%`<=e$J%JPAt0m^In>wAf0!TWU~_Y$9&xf6vR^Z&!D8>nG- z6_*`v-kL3+auy_)l?TM#;MKJY#>*+-zd^lf5MH2b57r^G(TW*~#?l8@Vl5D(OJS`O zDl+dbg2j7rac`q84AcrlA~y-i2cWWeK3jM?v(-h*wj=GUxn>4CYWq0prl`}v*soxY zt7MY&BhSj{OEP@!5TNfOrTbFXV-prgzO(BTOya<~9#y|GlI?Ig5PTzf0{wBxVeN>h5>vfiEDV*fyM?wwO)q z^1`sQ6}a{86~T6Wde$MG%nd*_@fi}iJ_cFW2 zntQ2~V!4B4j@FSE*r$t;oZC7YCh)|2R?z<| z;-RWqbJWH>{7Jjkq%rG6&Xf|6DG@S6C|-84huiRf9G%d+AGkHZFv))?+KI2=_2Ck0 zr~qXLmE_z#3SoQv)hdEq2w*1P@y|5#sc{?&|4)1Mh*cj5T)pKE!ZvtwyPq8Tup$7N zdT*>s4?Bsi(ojRXt<@)%*<&C@3@qbap zS)_(1dMm^!YjWaj4@;8HsF%`JS@&Hb4SNkel>+tT9>nK%YqivOvcKP?UFMngBZ$SD zM@z+{<{en7g_Ckzua|c@dvH8gDwZ^$toL|z3N=O#@h)@!XI{Vw(UmdCA-z0A;*s6< zg-f7dqI-LM+tPe~BXidlZ0N3$I8Sfr<&9frwF+0>IJqtkfiUlVk{6KN(Vq0N8#hV4 zZK-4OHliOyGdaWbd=1hJbyK3w?7;xQk9^Jlh~*n?EtHli^H%q|K2 z*jNAPXnWR&a;6H8(Aq!1Al5+&^I&s&5tI}GR{l6gtcg7x47oY0Y^wjOAZ18krt(g} zk82KC7!gaclLgWy$2*tDqbaWmg%pW6v$4~$SN=zZhkfaJ1|w%90`bpCPYnz0D+?9D z=5(qU1cJRLkk(@m!C5t#)m_TQTC)!O z0P1Irc~tvCE1aajy9auYio?th6Ex*9+=at5n%g6w|dw>&peLO zO?nV8W#ZyZi?Hyj+f2%-7sRBXwX*l*ZW=q^4QMFb;E5)^e>7{_6L_W=<>gPJ;tYFq z)#>1TNB8bk4ur^-GFc?SL}Owg@m1Ev4jM`A7J?i3{uit3zwp2!bp!TsseUc~dfVn? zwuTq5SmrJ|UOvzXbN!x|>A1M=C_@S`%7)bEIrO_>SB!(9qp-zzxftfRt!1lw~HJOlQnk&7J_ z>+qXdP_06mB+I(r8f8@xlAG7qmczg32+62Ml$xhGDU+bQ6G@!b=(~opG4UMo6O4D9 z640bslf~wxxc@}inPRD<0r6Up?+=-;RvSiM(mR$CG31l1Yg-l+g~c~z7{E#{dm>Zl zX!gMLxAPUvsbvhEk|ZtLG5%y#r23MowAJUR4afiGh=zL5!d)E%iw~|_4z^EMEIu@6 z?QzAja{KZbx9uWjMt0Ipp*d|Imp!0QKCjS>+pPjy=j}%8 zjNXvQhYSPl!7?rWNdxEkjupUgs~WdrJ>lGGBf{6>l*vB(p?oR zL2}>Y7x&_BlOz}df(%F+<%#@CwHqkLND>~g{ zqOf@liNjovz`heYH*AE(-|G)yeQ`qN{jbDbN}PI3rprxa z4x7zWYMC(Bg}{7?;u0$I0Dfa)DJ5x#Td|vG2KyRV&yq;sLQ?!GY*s^xgpMmo2i+W) zq(G4AG;~W((v1Ksf)7bq+^6lNP-)i)ASP?M;G@AZAi8r zmWPW$O<7dh$Uf;hgC#?V>~#^>{!+RkjW)q4>ObB9f=9FO>K-cXLWg6jUc3>4tL!fe zPsi%*DT&UQe-Y4rG~kzp<{%PI^XV4tP(bGhHO)j7!Sg&SO)+Q92@LXZ+^xQxOU;fv zwhR5DF|z{WKso3X<`>}rN)q#|Hr2RjSw^Ysd1R#e&14q`la3<_ZF zUEMprcH%#?ySn?y-K#TV8m+jh<>?~bZullj$#Rx?FJej7B-0F`W%tCkVBK&#ifHx3 z7Tb~uwvILwldLe!hp_B3@oq5b{y3{$nC*rA`ifXO=a7{>ZOm@30D8(mSc10U z2kgd!3`GS=dFN%KXaEu)H+?a_+2_GSRDDy8so!OPbe;B&B+1@xn5xtp@bBWCvnib3 z7k%72&yf+2lgTHfZa2VQz;SCe%Mq3}5h?|Lm^>L!01bP%^77sd$tBDI!~BRgOUdy| zu?sKr^O<5M>HrdgB2Y&*}K`J93jC#3MPKf*e@Lv=oh#@U~sZ|TLesP6W3iilO_B~GRR`$_R$=q8K#hHvX$co)Tun{QV#*eAl=cHdK49`wS=^ zQpxeOy{`p{w!qE*VvTn(NP0T{7a|XIKw)cbK&+Y{#Jmr~#uwBOZ~9jnPvGXdiI_%20z@ zojgm{hh#a4>pqxdF7Pn&oi3wLrR>eCFct|W(9S%5DMX%gW1~rM?mm2xf6hn=#@?ya z)ItsWBwKczw?M*0^%b5_zxlBj95;vSE--<2PSGY2qFLB4jX+iznan!QYV-|B(fYUA zT;I`dQfeHUewuU6rxR=52amS9FhceBU`VqVSm~p@n%w-(Ihy{cgzra1<{zk0xS?H^ zN|jWXgiz<&69FI$=$N{V6ZekE_@7%JN&WqWA0N7e&c~W9eUu;F>*Gl*=5m{1ynmbXy=BYSS4?#Kx`3!+v@ILxeP>m6io-hW{Ibf(Q zpz(zI>N1^5c! zJ_3|6_PPQ{!|CeAFU*M~NH|+58`Ly;8o^z91!wVwxAPDz8IDkf5*GaH;qIj*)ff(xS7jsDenGXOW!+frOTf3nk-QrUV~aLclEW>M{<%APV!k?wI?Ufc{QhimHMCo$ zb8fsx)M+w^NJYot2^> zuBvy5n7wNYu+gX&X6DH4F9)&g#s0sTI1(bzhiNHBi97wvYM!{b-2~rqi^eoS+;f>u zi=IO|IYbB4<`Q+h3?x(=%0ovzwMs+^8C&-UysbJwS6<@y&9%nFKBas|9*pH-Um(MEhJk_lMI)$y~#Ys6jNjK`YTT$ zEMXG4fkXziABWf4sq2G@aK&Uer|G)Xe&Og#4xehbE@y+%h;oM5Te{IOvt8o*i6%g~pEL45_II+ktN3|kT(G?D91|u0>?cuWdoky!m zFYZbo6pMfJA=U}gzpmO#VmW9-mMSTPeM%7vP3rp=jw}fyawgqF8n~7&xO0<%=FSS& zIhc zZLqC70J}KK{YR+y0pb*9?(|MBd9*DmK8sd->i^-T<=Jk~r;C$OCmq>9Oj;oAKG;d* z%*$bwvov$Btv^E$(p>lHtStKf;6>isxjj5c@@Z~@RiAO%Gvo~FAS52Z0^_fDZ6&!u z6*Qa7h6@5CACAj4%K%bA_Ljo&?8p2mmPG|=g^4S-yJL*zuA3xao{JOQC03N4CK>7r zH@hr&0v!4F4k@|8TB!B}h1e#*xZZ{{D^*j0yQlS*<#z;jB+x&)*yFJKliVZpMs&-~ zgBiwfuX4F*;^-MVoZlp8?7z}=6P=7mQG@Uu^EYYI76*3%HWKnZmw_;rcKa3f4WTFm zD?Xu_F`nLZ(~yq5S*M&yMo!cJ{%A@0?a`>LZVZ8dd2$I~jwstU3+|*x^SwBD%#nok zvNkDMqYhZMbx2~=ma1s$m_-a#2im8FE>#0&Q~pIuWmwW1jhT_lt{n@Wa#kQ)S?@#p z;Dyfrb8|s4+1KZ#0VM@a;76r_jUk`lbXhC3Xgg1>t*&MOg46joMfP?E3~RWMMg=@5 zIuM?`KIjkl^L$tLl&FYw=1z&W;3v4k5P7s`Nmm{IZJ%DLzC zm5Z|-mlBdeU}u~@K}^!+(!$-7=%hs?Ow8xd&98KIng=^5NZp-KkLIkp&YghbJ@YGJ z0CYex$q}PO8EO0bk&%)O2Py;-M6Z0r&`sMpXpf{T4cQ}sEWZuMjL)`NF5*X?X(?0? z2BP6l*_+=`yP2+P@KYY5_UIXex9Fis2S!`PL|2IguxiEVK?YmO1&fryh#iQQ@!?Ip zF2%chNs8LW|LdVIQTiZ=SG@c%jv>|mBg&G7zgBdNY_}$sms4s^!mM{$> zXZG8Vl6GqltlMY#zv6wEk2@#jZaT{&|MLK8BlO%|2_qPN>W2d~1d|?94aj__6Guj| zNg%id4A}Luw`KW!fitm_=JkkNnAokXcoXq#_Kx7`#(8!Vw#-Z>9qcXw;se`0jXM3n z)wL04YKh`lt%kepifeagjT`ggy$e6aqL|^g27`@5vI7P2n|7AE0VJL({8Yu(_oPhJ z(|7M1Hs9z~a;rHGEM-|H@4iv)K;#&Fv+$4op{p48#*P%f_&;Ao6e!kEf6CR?tCckR z*BL9Yx2!SQa6-GvE#g3_S*2aYMPLQhJ_KCNLKnxepoYsh;W*)fVV>C0IY9+3M!m?9Y~Pf7~(xZ$|>D*%710kW*4Cv&Xt zlnPBMhDKxx>Q-n*AVU9J&JNppy{_2TXc3*n7RUiZ(QRQchHMTryaCN!761B4c4_JQ z?3Qk1Fb>S~SK`~i%cOlFT&I7WAQSN;p4{f!YIH#9WY>M*Jm!}t|4s}(Cku{+9mLz{ zDe$q9F?#%p*2tj2MB47V zOHAfO%#@>ohD9?qkzW8A4ZD!R;sp8ZLbB33a-Tui zLOKo@6{X3f7NnjSaVs)ggLe|SsP*MSv4n0c6E+dh4GO4J+TJ9KUvPDg|8RHuwxbRmZ`@AuSD_0lcjZ{v29ONb4 zqd#*X_?zbrVM_Z0zON@we!w5sNW6dxBA!Wn`J3WA#&4J1n_%(D5(yy>!%YNm%Xg(1 zRs3+whGixVa*OUeTEEt%m`_Iq4|B2QZyXW_6^n-%a%S65k^LyN@eC;`y|ueAOCGC{ z3{(vm!ApFNo0#GSVg&W34-x^+BB4!7f~T{wVMI@LHUq4wA76W?0@R0zY$(z=8!#v) zu{zS#Qsl?ue)TQeBggr8{F^P!I_@3!C;i{MVZ_#G+s@p!>N_}4MpCTw(U)VLvz^Ks z`qjvFDggItJq@VAF=JF7)bo z^-FZ^vM=$M>3ev_L!w3sel22NIQ+YW#pPn)oFs7)7Nu~Or49mu%Tm^>G?w{!H^U5G zpOaK+XU!i4P8E6T`cI4$Q^rkv4~O+V@0BQ;l!EUp&&&$J^xMFr?puafIAr_r<*bS?R zr}lz)-BS%(lpp)JOZ${=M9Q;Ux3FbvL71%D_zknG+qps&!IR>aObL>u4c94|2gfmD z#(@8Sl!`xS#-ZL-l_tYHs->uIs96)S&(^5i)qD*!QwyEypqtJ4b@p^M zw+<||6nr)6wdw1v$ZVJoG`Bt2YS8XYN`i@P0s4lI^s))R53PlBY0NI^;OAi#h`t^^ z&Hkrw0ybWUkW{gfVY4Z~djxVWUCC}#R_;K+OUTrFgTwedL7n`674bbnYV1_GQxScU zPKngK6;Ass(TciJ)tWRXbDkEdJ6(=?v`d$itXZUVjJupxp_|2kzmO-du!(z`q!&u_HE#|_AbQjiGKr2{ zISnfl*pR7C5LqeNq=5Tg2aevn?fz%1YT{AI$=&9)^m)zs0{c?XFMobUyfz;1qL(=o zL6V3ziAd$OjRaSKHm)v$bkZAbF))4I5JMS@D@~xLy;4xU(wKvc(IYrfTcF7pV~&!<|M)SdIa6rrs>0+PZj$b(vB>S zQm6JV>$^jlk0nKThA;eu3Xawban9IGk^^Wcp4xr=^{W`Pzb|B;{!M-!F-psMQw77} zvg}r4cByXk=+8@(#!J-DtJbB1*GJDlN>nn} zFU2GopwACd%GfG?Oiu>*B+F?Lb%Hot3aB0y-JlU_s@D&bt*@B}-ka+j zKfX^@I(qe})7D=^dTbJ2eOW>9is+ts@GC15Bd3XbF}zgvpl4ukh{2q*u4?B9VXa7; zw_(y5LU!0z@|!yW*r&i(Z-43;a&j4}_H}KTBL@!II*`!OW**&15Xj~saG+1F0+Hw< z#QyoLxzWb?Px0P0U+kh6s<&%AXAb!_pQkao<;35l7_&iR6PGUBve?vQVRMZCm`hyF zrF!MOcehP~+j#D4)myp-ub&NQQEaB{|MrREl2v*n1&u9GxY;;Z2Jw0z42k<|bg!3s zCQ>EBHOocv>R=tVY`3HJ1UwH|W?S^;Y8fSYyM=hCRfR4h%=4lU83Qke(umz5sA%V-r2O`syUdwp9~cX*d^nCtl0a7sL8~P6$m(6(Pp} z0iPQOVYI7A!wQu5`_-^`GpDdqP;JH3YN>o4h`Me!aY?J@GVCQvLp3fgSU;P2Y~}O; zYt)`)v%l5Ytkxr(h@Krl*kz-e#UrM>MSq56+_;t}E{$IF3Sv`3(ExPmKx514s1PvI zWLtVYblAwBk>UJJ^2%y6*YSomSGSLq;Ldaz+PcVH>quz1m5MNqpR$Jv^JlkCCfD5M zQ>r7v+VEZeeQL831658?!$maZ<+J?-mM5rB?s2wW$nwTL$P3t6{-oRli&DHE`ur;+;g(FRr+59Khd84&#z?p6m- z5K$rEFg;NuokOMNQgP&qIIu#k zu|M!mOKOU)ATWHyQ zvu4M8Cy1Kg6^Wi6Q+0|}&jU3Jt!w+#Im>uhe&BqtwOQo54BN+FEe z{(}Uv1&kceZIAC<*1Nfa%0FYcIM(;x3HyR2Nd2iv)5kEbVMn3v2-+UZG`nFN+NyCV zmxH6;4FjkOz4UFJZO2v=in^W=<;~!-Od+p;fZ3LhfQgwLK0?xcw>$Sar1}%^faB9A zc$k{ZW1z`n3ZuRy(sZ)h0OafvG4Ovu({Ar9P`@rRMImS6r>qc{_Z68djkOL6PY!y! zvnX~AFA+lJ97O0kkmWS-&;8d)C^yAzjoOt|ro?PLm~GekBdww9oND4q;0G~}%M-;L z@t$f96H(T4zT*Bz86h~R?~3REb?zPwCAuN~*gHms?HaKK<29{uM||1T27GX~=ef1S zGteHOPITe`^Y$R9!~>21)H*8~Tv$rp!3y*}(+709d`g-9(Kq8_Pi)BkW`2q0V#c~2o zfA{EN>Q#o3&bJ#Fk8oPZEx<8g(T~>iTX2A%-O(ZK{zPy<*+O!W;;CRSYpbZSb%E@` z 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 y5Zgc0K$Aj02HCIu{RDjv_GgO$9nVs2O#V> z697eMC5BqW#KZt_bS4}M`u|`3M*so9T~H?wy47L~s__Wky#E0R_dfy@p|R&T4n6=J zoCSwMhxZov4?y_;ai9pTZ0sD+!|i!K^74T{i;9U$0KgSc_6IoVZ9`da^N9czM5rJ^ z + +#include "config.h" +#include "cursor.h" + +/** + * BSWAP_16 - reverse bytes in a constant uint16_t value. + * @val: constant value whose bytes to swap. + * + * Designed to be usable in constant-requiring initializers. + * + * Example: + * struct mystruct { + * char buf[BSWAP_16(0x1234)]; + * }; + */ +#define BSWAP_16(val) \ + ((((uint16_t)(val) & 0x00ff) << 8) \ + | (((uint16_t)(val) & 0xff00) >> 8)) + +/** + * BSWAP_32 - reverse bytes in a constant uint32_t value. + * @val: constant value whose bytes to swap. + * + * Designed to be usable in constant-requiring initializers. + * + * Example: + * struct mystruct { + * char buf[BSWAP_32(0xff000000)]; + * }; + */ +#define BSWAP_32(val) \ + ((((uint32_t)(val) & 0x000000ff) << 24) \ + | (((uint32_t)(val) & 0x0000ff00) << 8) \ + | (((uint32_t)(val) & 0x00ff0000) >> 8) \ + | (((uint32_t)(val) & 0xff000000) >> 24)) + +/** + * BSWAP_64 - reverse bytes in a constant uint64_t value. + * @val: constantvalue whose bytes to swap. + * + * Designed to be usable in constant-requiring initializers. + * + * Example: + * struct mystruct { + * char buf[BSWAP_64(0xff00000000000000ULL)]; + * }; + */ +#define BSWAP_64(val) \ + ((((uint64_t)(val) & 0x00000000000000ffULL) << 56) \ + | (((uint64_t)(val) & 0x000000000000ff00ULL) << 40) \ + | (((uint64_t)(val) & 0x0000000000ff0000ULL) << 24) \ + | (((uint64_t)(val) & 0x00000000ff000000ULL) << 8) \ + | (((uint64_t)(val) & 0x000000ff00000000ULL) >> 8) \ + | (((uint64_t)(val) & 0x0000ff0000000000ULL) >> 24) \ + | (((uint64_t)(val) & 0x00ff000000000000ULL) >> 40) \ + | (((uint64_t)(val) & 0xff00000000000000ULL) >> 56)) + +#if HAVE_BYTESWAP_H +#include +#else +/** + * bswap_16 - reverse bytes in a uint16_t value. + * @val: value whose bytes to swap. + * + * Example: + * // Output contains "1024 is 4 as two bytes reversed" + * printf("1024 is %u as two bytes reversed\n", bswap_16(1024)); + */ +static inline uint16_t bswap_16(uint16_t val) +{ + return BSWAP_16(val); +} + +/** + * bswap_32 - reverse bytes in a uint32_t value. + * @val: value whose bytes to swap. + * + * Example: + * // Output contains "1024 is 262144 as four bytes reversed" + * printf("1024 is %u as four bytes reversed\n", bswap_32(1024)); + */ +static inline uint32_t bswap_32(uint32_t val) +{ + return BSWAP_32(val); +} +#endif /* !HAVE_BYTESWAP_H */ + +#if !HAVE_BSWAP_64 +/** + * bswap_64 - reverse bytes in a uint64_t value. + * @val: value whose bytes to swap. + * + * Example: + * // Output contains "1024 is 1125899906842624 as eight bytes reversed" + * printf("1024 is %llu as eight bytes reversed\n", + * (unsigned long long)bswap_64(1024)); + */ +static inline uint64_t bswap_64(uint64_t val) +{ + return BSWAP_64(val); +} +#endif + +/* Needed for Glibc like endiness check */ +#define __LITTLE_ENDIAN 1234 +#define __BIG_ENDIAN 4321 + +/* Sanity check the defines. We don't handle weird endianness. */ +#if !HAVE_LITTLE_ENDIAN && !HAVE_BIG_ENDIAN +#error "Unknown endian" +#elif HAVE_LITTLE_ENDIAN && HAVE_BIG_ENDIAN +#error "Can't compile for both big and little endian." +#elif HAVE_LITTLE_ENDIAN +#ifndef __BYTE_ORDER +#define __BYTE_ORDER __LITTLE_ENDIAN +#elif __BYTE_ORDER != __LITTLE_ENDIAN +#error "__BYTE_ORDER already defined, but not equal to __LITTLE_ENDIAN" +#endif +#elif HAVE_BIG_ENDIAN +#ifndef __BYTE_ORDER +#define __BYTE_ORDER __BIG_ENDIAN +#elif __BYTE_ORDER != __BIG_ENDIAN +#error "__BYTE_ORDER already defined, but not equal to __BIG_ENDIAN" +#endif +#endif + + +#ifdef __CHECKER__ +/* sparse needs forcing to remove bitwise attribute from ccan/short_types */ +#define ENDIAN_CAST __attribute__((force)) +#define ENDIAN_TYPE __attribute__((bitwise)) +#else +#define ENDIAN_CAST +#define ENDIAN_TYPE +#endif + +typedef uint64_t ENDIAN_TYPE leint64_t; +typedef uint64_t ENDIAN_TYPE beint64_t; +typedef uint32_t ENDIAN_TYPE leint32_t; +typedef uint32_t ENDIAN_TYPE beint32_t; +typedef uint16_t ENDIAN_TYPE leint16_t; +typedef uint16_t ENDIAN_TYPE beint16_t; + +#if HAVE_LITTLE_ENDIAN +/** + * CPU_TO_LE64 - convert a constant uint64_t value to little-endian + * @native: constant to convert + */ +#define CPU_TO_LE64(native) ((ENDIAN_CAST leint64_t)(native)) + +/** + * CPU_TO_LE32 - convert a constant uint32_t value to little-endian + * @native: constant to convert + */ +#define CPU_TO_LE32(native) ((ENDIAN_CAST leint32_t)(native)) + +/** + * CPU_TO_LE16 - convert a constant uint16_t value to little-endian + * @native: constant to convert + */ +#define CPU_TO_LE16(native) ((ENDIAN_CAST leint16_t)(native)) + +/** + * LE64_TO_CPU - convert a little-endian uint64_t constant + * @le_val: little-endian constant to convert + */ +#define LE64_TO_CPU(le_val) ((ENDIAN_CAST uint64_t)(le_val)) + +/** + * LE32_TO_CPU - convert a little-endian uint32_t constant + * @le_val: little-endian constant to convert + */ +#define LE32_TO_CPU(le_val) ((ENDIAN_CAST uint32_t)(le_val)) + +/** + * LE16_TO_CPU - convert a little-endian uint16_t constant + * @le_val: little-endian constant to convert + */ +#define LE16_TO_CPU(le_val) ((ENDIAN_CAST uint16_t)(le_val)) + +#else /* ... HAVE_BIG_ENDIAN */ +#define CPU_TO_LE64(native) ((ENDIAN_CAST leint64_t)BSWAP_64(native)) +#define CPU_TO_LE32(native) ((ENDIAN_CAST leint32_t)BSWAP_32(native)) +#define CPU_TO_LE16(native) ((ENDIAN_CAST leint16_t)BSWAP_16(native)) +#define LE64_TO_CPU(le_val) BSWAP_64((ENDIAN_CAST uint64_t)le_val) +#define LE32_TO_CPU(le_val) BSWAP_32((ENDIAN_CAST uint32_t)le_val) +#define LE16_TO_CPU(le_val) BSWAP_16((ENDIAN_CAST uint16_t)le_val) +#endif /* HAVE_BIG_ENDIAN */ + +#if HAVE_BIG_ENDIAN +/** + * CPU_TO_BE64 - convert a constant uint64_t value to big-endian + * @native: constant to convert + */ +#define CPU_TO_BE64(native) ((ENDIAN_CAST beint64_t)(native)) + +/** + * CPU_TO_BE32 - convert a constant uint32_t value to big-endian + * @native: constant to convert + */ +#define CPU_TO_BE32(native) ((ENDIAN_CAST beint32_t)(native)) + +/** + * CPU_TO_BE16 - convert a constant uint16_t value to big-endian + * @native: constant to convert + */ +#define CPU_TO_BE16(native) ((ENDIAN_CAST beint16_t)(native)) + +/** + * BE64_TO_CPU - convert a big-endian uint64_t constant + * @le_val: big-endian constant to convert + */ +#define BE64_TO_CPU(le_val) ((ENDIAN_CAST uint64_t)(le_val)) + +/** + * BE32_TO_CPU - convert a big-endian uint32_t constant + * @le_val: big-endian constant to convert + */ +#define BE32_TO_CPU(le_val) ((ENDIAN_CAST uint32_t)(le_val)) + +/** + * BE16_TO_CPU - convert a big-endian uint16_t constant + * @le_val: big-endian constant to convert + */ +#define BE16_TO_CPU(le_val) ((ENDIAN_CAST uint16_t)(le_val)) + +#else /* ... HAVE_LITTLE_ENDIAN */ +#define CPU_TO_BE64(native) ((ENDIAN_CAST beint64_t)BSWAP_64(native)) +#define CPU_TO_BE32(native) ((ENDIAN_CAST beint32_t)BSWAP_32(native)) +#define CPU_TO_BE16(native) ((ENDIAN_CAST beint16_t)BSWAP_16(native)) +#define BE64_TO_CPU(le_val) BSWAP_64((ENDIAN_CAST uint64_t)le_val) +#define BE32_TO_CPU(le_val) BSWAP_32((ENDIAN_CAST uint32_t)le_val) +#define BE16_TO_CPU(le_val) BSWAP_16((ENDIAN_CAST uint16_t)le_val) +#endif /* HAVE_LITTE_ENDIAN */ + + +/** + * cpu_to_le64 - convert a uint64_t value to little-endian + * @native: value to convert + */ +static inline leint64_t cpu_to_le64(uint64_t native) +{ + return CPU_TO_LE64(native); +} + +/** + * cpu_to_le32 - convert a uint32_t value to little-endian + * @native: value to convert + */ +static inline leint32_t cpu_to_le32(uint32_t native) +{ + return CPU_TO_LE32(native); +} + +/** + * cpu_to_le16 - convert a uint16_t value to little-endian + * @native: value to convert + */ +static inline leint16_t cpu_to_le16(uint16_t native) +{ + return CPU_TO_LE16(native); +} + +/** + * le64_to_cpu - convert a little-endian uint64_t value + * @le_val: little-endian value to convert + */ +static inline uint64_t le64_to_cpu(leint64_t le_val) +{ + return LE64_TO_CPU(le_val); +} + +/** + * le32_to_cpu - convert a little-endian uint32_t value + * @le_val: little-endian value to convert + */ +static inline uint32_t le32_to_cpu(leint32_t le_val) +{ + return LE32_TO_CPU(le_val); +} + +/** + * le16_to_cpu - convert a little-endian uint16_t value + * @le_val: little-endian value to convert + */ +static inline uint16_t le16_to_cpu(leint16_t le_val) +{ + return LE16_TO_CPU(le_val); +} + +/** + * cpu_to_be64 - convert a uint64_t value to big endian. + * @native: value to convert + */ +static inline beint64_t cpu_to_be64(uint64_t native) +{ + return CPU_TO_BE64(native); +} + +/** + * cpu_to_be32 - convert a uint32_t value to big endian. + * @native: value to convert + */ +static inline beint32_t cpu_to_be32(uint32_t native) +{ + return CPU_TO_BE32(native); +} + +/** + * cpu_to_be16 - convert a uint16_t value to big endian. + * @native: value to convert + */ +static inline beint16_t cpu_to_be16(uint16_t native) +{ + return CPU_TO_BE16(native); +} + +/** + * be64_to_cpu - convert a big-endian uint64_t value + * @be_val: big-endian value to convert + */ +static inline uint64_t be64_to_cpu(beint64_t be_val) +{ + return BE64_TO_CPU(be_val); +} + +/** + * be32_to_cpu - convert a big-endian uint32_t value + * @be_val: big-endian value to convert + */ +static inline uint32_t be32_to_cpu(beint32_t be_val) +{ + return BE32_TO_CPU(be_val); +} + +/** + * be16_to_cpu - convert a big-endian uint16_t value + * @be_val: big-endian value to convert + */ +static inline uint16_t be16_to_cpu(beint16_t be_val) +{ + return BE16_TO_CPU(be_val); +} + +/** + * be64/be32/be16 - 64/32/16 bit big-endian representation. + */ +typedef beint64_t be64; +typedef beint32_t be32; +typedef beint16_t be16; + +/** + * le64/le32/le16 - 64/32/16 bit little-endian representation. + */ +typedef leint64_t le64; +typedef leint32_t le32; +typedef leint16_t le16; + +static inline int cursor_push_u16(struct cursor *cursor, u16 i) +{ + be16 v = cpu_to_be16(i); + return cursor_push(cursor, &v, sizeof(v)); +} + +static inline int cursor_pull_u16(struct cursor *cursor, u16 *i) +{ + be16 ret; + if (!cursor_pull(cursor, (u8*)&ret, sizeof(ret))) + return 0; + *i = be16_to_cpu(ret); + return 1; +} + +static inline int cursor_push_u64(struct cursor *cur, u64 v) +{ + be64 l = cpu_to_be64(v); + return cursor_push(cur, (u8*)&l, sizeof(l)); +} + + +#endif /* CCAN_ENDIAN_H */ diff --git a/node_modules/lnsocket/error.c b/node_modules/lnsocket/error.c new file mode 100644 index 0000000..a8451a7 --- /dev/null +++ b/node_modules/lnsocket/error.c @@ -0,0 +1,49 @@ + +#include "error.h" + +#include +#include + +int note_error_(struct errors *errs_, const char *fmt, ...) +{ + static char buf[512]; + struct error err; + struct cursor *errs; + va_list ap; + + errs = &errs_->cur; + + if (errs_->enabled == 0) + return 0; + + va_start(ap, fmt); + vsprintf(buf, fmt, ap); + va_end(ap); + + err.msg = buf; + + if (!cursor_push_error(errs, &err)) { + fprintf(stderr, "arena OOM when recording error, "); + fprintf(stderr, "errs->p at %ld, remaining %ld, strlen %ld\n", + errs->p - errs->start, errs->end - errs->p, strlen(buf)); + } + + return 0; +} + +void print_error_backtrace(struct errors *errors) +{ + struct cursor errs; + struct error err; + + copy_cursor(&errors->cur, &errs); + errs.p = errs.start; + + while (errs.p < errors->cur.p) { + if (!cursor_pull_error(&errs, &err)) { + fprintf(stderr, "backtrace: couldn't pull error\n"); + return; + } + fprintf(stderr, "%s\n", err.msg); + } +} diff --git a/node_modules/lnsocket/error.h b/node_modules/lnsocket/error.h new file mode 100644 index 0000000..656548b --- /dev/null +++ b/node_modules/lnsocket/error.h @@ -0,0 +1,32 @@ + +#ifndef LNSOCKET_ERROR_H +#define LNSOCKET_ERROR_H + +#include "cursor.h" + +struct error { + const char *msg; +}; + +struct errors { + struct cursor cur; + int enabled; +}; + +#define note_error(errs, fmt, ...) note_error_(errs, "%s:%s:%d: " fmt, __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__) + +static inline int cursor_push_error(struct cursor *cur, struct error *err) +{ + return cursor_push_c_str(cur, err->msg); +} + +static inline int cursor_pull_error(struct cursor *cur, struct error *err) +{ + return cursor_pull_c_str(cur, &err->msg); +} + +int note_error_(struct errors *errs, const char *fmt, ...); + +void print_error_backtrace(struct errors *errors); + +#endif /* LNSOCKET_ERROR_H */ diff --git a/node_modules/lnsocket/examples/README.md b/node_modules/lnsocket/examples/README.md new file mode 100644 index 0000000..65aa733 --- /dev/null +++ b/node_modules/lnsocket/examples/README.md @@ -0,0 +1,7 @@ + +# Examples + +## nodejs + + $ npm install + $ node node.js diff --git a/node_modules/lnsocket/examples/node.js b/node_modules/lnsocket/examples/node.js new file mode 100644 index 0000000..dd64596 --- /dev/null +++ b/node_modules/lnsocket/examples/node.js @@ -0,0 +1,24 @@ +const LNSocket = require('lnsocket') + +async function go() { + const ln = await LNSocket() + + ln.genkey() + await ln.connect_and_init("03f3c108ccd536b8526841f0a5c58212bb9e6584a1eb493080e7c1cc34f82dad71", "24.84.152.187") + + const rune = "b3Xsg2AS2cknHYa6H94so7FAVQVdnRSP6Pv-1WOQEBc9NCZtZXRob2Q9b2ZmZXItc3VtbWFyeQ==" + const summary = await ln.rpc({ + rune, + method: "offer-summary", + params: { + offerid: "22db2cbdb2d6e1f4d727d099e2ea987c05212d6b4af56d92497e093b82360db7", + limit: 10 + } + }) + + ln.destroy() + console.log(summary.result) + return summary.result +} + +go() diff --git a/node_modules/lnsocket/examples/package.json b/node_modules/lnsocket/examples/package.json new file mode 100644 index 0000000..06fa952 --- /dev/null +++ b/node_modules/lnsocket/examples/package.json @@ -0,0 +1,18 @@ +{ + "name": "examples", + "description": "lnsocket examples", + "version": "0.1.0", + "repository": { + "url": "https://github.com/jb55/examples" + }, + "main": "node.js", + "scripts": { + "test": "tap test/*.js" + }, + "dependencies": { + "lnsocket": "^0.2.0" + }, + "devDependencies": { + "tap": "~0.2.5" + } +} diff --git a/node_modules/lnsocket/examples/websockets.html b/node_modules/lnsocket/examples/websockets.html new file mode 100644 index 0000000..9e44f98 --- /dev/null +++ b/node_modules/lnsocket/examples/websockets.html @@ -0,0 +1,16 @@ + + + + + + + + Hello World + + +