From 9bd88d5622abee3702e45d4238522cf6e4bc718d Mon Sep 17 00:00:00 2001 From: Gus Ortiz Date: Wed, 7 Jan 2015 21:05:32 -0600 Subject: [PATCH 1/4] Create mongo storage with the same methods as json rest and localstorage --- argon/storage/mongodb.js | 90 + node_modules/mongodb/.gitmodules | 0 node_modules/mongodb/.travis.yml | 5 + node_modules/mongodb/CONTRIBUTING.md | 23 + node_modules/mongodb/LICENSE | 201 + node_modules/mongodb/Makefile | 28 + node_modules/mongodb/Readme.md | 418 ++ node_modules/mongodb/index.js | 1 + node_modules/mongodb/lib/mongodb/admin.js | 340 ++ .../mongodb/lib/mongodb/aggregation_cursor.js | 187 + .../mongodb/lib/mongodb/auth/mongodb_cr.js | 81 + .../lib/mongodb/auth/mongodb_gssapi.js | 172 + .../mongodb/lib/mongodb/auth/mongodb_plain.js | 79 + .../mongodb/lib/mongodb/auth/mongodb_scram.js | 250 + .../mongodb/lib/mongodb/auth/mongodb_sspi.js | 156 + .../mongodb/lib/mongodb/auth/mongodb_x509.js | 68 + .../mongodb/lib/mongodb/collection.js | 676 +++ .../lib/mongodb/collection/aggregation.js | 318 ++ .../lib/mongodb/collection/batch/common.js | 439 ++ .../lib/mongodb/collection/batch/ordered.js | 530 ++ .../lib/mongodb/collection/batch/unordered.js | 576 ++ .../lib/mongodb/collection/commands.js | 139 + .../mongodb/lib/mongodb/collection/core.js | 800 +++ .../mongodb/lib/mongodb/collection/geo.js | 78 + .../mongodb/lib/mongodb/collection/index.js | 72 + .../mongodb/lib/mongodb/collection/query.js | 218 + .../mongodb/lib/mongodb/collection/shared.js | 120 + .../mongodb/lib/mongodb/command_cursor.js | 362 ++ .../lib/mongodb/commands/base_command.js | 29 + .../lib/mongodb/commands/db_command.js | 101 + .../lib/mongodb/commands/delete_command.js | 129 + .../lib/mongodb/commands/get_more_command.js | 88 + .../lib/mongodb/commands/insert_command.js | 161 + .../mongodb/commands/kill_cursor_command.js | 98 + .../lib/mongodb/commands/query_command.js | 296 + .../lib/mongodb/commands/update_command.js | 189 + .../mongodb/lib/mongodb/connection/base.js | 515 ++ .../lib/mongodb/connection/connection.js | 563 ++ .../lib/mongodb/connection/connection_pool.js | 305 ++ .../mongodb/connection/connection_utils.js | 23 + .../mongodb/lib/mongodb/connection/mongos.js | 578 ++ .../lib/mongodb/connection/read_preference.js | 67 + .../lib/mongodb/connection/repl_set/ha.js | 448 ++ .../mongodb/connection/repl_set/options.js | 126 + .../mongodb/connection/repl_set/repl_set.js | 830 +++ .../connection/repl_set/repl_set_state.js | 74 + .../repl_set/strategies/ping_strategy.js | 366 ++ .../strategies/statistics_strategy.js | 93 + .../mongodb/lib/mongodb/connection/server.js | 945 ++++ .../mongodb/connection/server_capabilities.js | 48 + .../lib/mongodb/connection/url_parser.js | 265 + node_modules/mongodb/lib/mongodb/cursor.js | 1038 ++++ .../mongodb/lib/mongodb/cursorstream.js | 167 + node_modules/mongodb/lib/mongodb/db.js | 2179 ++++++++ .../mongodb/lib/mongodb/gridfs/chunk.js | 232 + .../mongodb/lib/mongodb/gridfs/grid.js | 104 + .../mongodb/lib/mongodb/gridfs/gridstore.js | 1570 ++++++ .../mongodb/lib/mongodb/gridfs/readstream.js | 206 + node_modules/mongodb/lib/mongodb/index.js | 62 + .../mongodb/lib/mongodb/mongo_client.js | 482 ++ .../lib/mongodb/responses/mongo_reply.js | 83 + node_modules/mongodb/lib/mongodb/scope.js | 86 + node_modules/mongodb/lib/mongodb/utils.js | 286 + .../mongodb/node_modules/bson/.travis.yml | 4 + .../mongodb/node_modules/bson/LICENSE | 201 + .../mongodb/node_modules/bson/Makefile | 19 + .../mongodb/node_modules/bson/README.md | 45 + .../mongodb/node_modules/bson/binding.gyp | 18 + .../node_modules/bson/browser_build/bson.js | 4843 +++++++++++++++++ .../bson/browser_build/package.json | 8 + .../mongodb/node_modules/bson/build/Makefile | 350 ++ .../build/Release/.deps/Release/bson.node.d | 1 + .../Release/obj.target/bson/ext/bson.o.d | 26 + .../node_modules/bson/build/Release/bson.node | Bin 0 -> 58484 bytes .../bson/build/Release/linker.lock | 0 .../build/Release/obj.target/bson/ext/bson.o | Bin 0 -> 336876 bytes .../node_modules/bson/build/binding.Makefile | 6 + .../node_modules/bson/build/bson.target.mk | 154 + .../node_modules/bson/build/config.gypi | 119 + .../node_modules/bson/build/gyp-mac-tool | 512 ++ .../node_modules/bson/build_browser.js | 7 + .../mongodb/node_modules/bson/builderror.log | 4 + .../mongodb/node_modules/bson/ext/Makefile | 28 + .../mongodb/node_modules/bson/ext/bson.cc | 1072 ++++ .../mongodb/node_modules/bson/ext/bson.h | 278 + .../mongodb/node_modules/bson/ext/index.js | 40 + .../bson/ext/win32/ia32/bson.node | Bin 0 -> 113664 bytes .../node_modules/bson/ext/win32/x64/bson.node | Bin 0 -> 130560 bytes .../mongodb/node_modules/bson/ext/wscript | 39 + .../node_modules/bson/lib/bson/binary.js | 343 ++ .../bson/lib/bson/binary_parser.js | 385 ++ .../node_modules/bson/lib/bson/bson.js | 1573 ++++++ .../node_modules/bson/lib/bson/bson_new.js | 776 +++ .../node_modules/bson/lib/bson/code.js | 24 + .../node_modules/bson/lib/bson/db_ref.js | 31 + .../node_modules/bson/lib/bson/double.js | 33 + .../bson/lib/bson/float_parser.js | 121 + .../node_modules/bson/lib/bson/index.js | 74 + .../node_modules/bson/lib/bson/long.js | 854 +++ .../node_modules/bson/lib/bson/max_key.js | 13 + .../node_modules/bson/lib/bson/min_key.js | 13 + .../node_modules/bson/lib/bson/objectid.js | 266 + .../node_modules/bson/lib/bson/symbol.js | 48 + .../node_modules/bson/lib/bson/timestamp.js | 853 +++ .../node_modules/bson/node_modules/nan/.dntrc | 30 + .../bson/node_modules/nan/CHANGELOG.md | 200 + .../bson/node_modules/nan/LICENSE | 46 + .../bson/node_modules/nan/README.md | 1054 ++++ .../bson/node_modules/nan/appveyor.yml | 32 + .../bson/node_modules/nan/include_dirs.js | 1 + .../node_modules/bson/node_modules/nan/nan.h | 2331 ++++++++ .../bson/node_modules/nan/package.json | 79 + .../mongodb/node_modules/bson/package.json | 76 + .../mongodb/node_modules/bson/tools/gleak.js | 21 + .../bson/tools/jasmine-1.1.0/MIT.LICENSE | 20 + .../bson/tools/jasmine-1.1.0/jasmine-html.js | 190 + .../bson/tools/jasmine-1.1.0/jasmine.css | 166 + .../bson/tools/jasmine-1.1.0/jasmine.js | 2476 +++++++++ .../tools/jasmine-1.1.0/jasmine_favicon.png | Bin 0 -> 905 bytes .../mongodb/node_modules/kerberos/LICENSE | 201 + .../mongodb/node_modules/kerberos/README.md | 4 + .../mongodb/node_modules/kerberos/binding.gyp | 43 + .../node_modules/kerberos/build/Makefile | 350 ++ .../obj.target/kerberos/lib/kerberos.o.d.raw | 15 + .../kerberos/build/binding.Makefile | 6 + .../node_modules/kerberos/build/config.gypi | 119 + .../node_modules/kerberos/build/gyp-mac-tool | 512 ++ .../kerberos/build/kerberos.target.mk | 172 + .../node_modules/kerberos/builderror.log | 23 + .../mongodb/node_modules/kerberos/index.js | 6 + .../kerberos/lib/auth_processes/mongodb.js | 281 + .../node_modules/kerberos/lib/base64.c | 134 + .../node_modules/kerberos/lib/base64.h | 22 + .../node_modules/kerberos/lib/kerberos.cc | 591 ++ .../node_modules/kerberos/lib/kerberos.h | 49 + .../node_modules/kerberos/lib/kerberos.js | 91 + .../kerberos/lib/kerberos_context.cc | 76 + .../kerberos/lib/kerberos_context.h | 48 + .../node_modules/kerberos/lib/kerberosgss.c | 693 +++ .../node_modules/kerberos/lib/kerberosgss.h | 70 + .../mongodb/node_modules/kerberos/lib/sspi.js | 15 + .../node_modules/kerberos/lib/win32/base64.c | 121 + .../node_modules/kerberos/lib/win32/base64.h | 18 + .../kerberos/lib/win32/kerberos.cc | 53 + .../kerberos/lib/win32/kerberos.h | 60 + .../kerberos/lib/win32/kerberos_sspi.c | 244 + .../kerberos/lib/win32/kerberos_sspi.h | 106 + .../node_modules/kerberos/lib/win32/worker.cc | 7 + .../node_modules/kerberos/lib/win32/worker.h | 38 + .../lib/win32/wrappers/security_buffer.cc | 106 + .../lib/win32/wrappers/security_buffer.h | 47 + .../lib/win32/wrappers/security_buffer.js | 12 + .../wrappers/security_buffer_descriptor.cc | 185 + .../wrappers/security_buffer_descriptor.h | 45 + .../wrappers/security_buffer_descriptor.js | 3 + .../lib/win32/wrappers/security_context.cc | 871 +++ .../lib/win32/wrappers/security_context.h | 72 + .../lib/win32/wrappers/security_context.js | 3 + .../win32/wrappers/security_credentials.cc | 351 ++ .../lib/win32/wrappers/security_credentials.h | 67 + .../win32/wrappers/security_credentials.js | 22 + .../node_modules/kerberos/lib/worker.cc | 7 + .../node_modules/kerberos/lib/worker.h | 38 + .../kerberos/node_modules/nan/.dntrc | 30 + .../kerberos/node_modules/nan/CHANGELOG.md | 200 + .../kerberos/node_modules/nan/LICENSE | 46 + .../kerberos/node_modules/nan/README.md | 1054 ++++ .../kerberos/node_modules/nan/appveyor.yml | 32 + .../kerberos/node_modules/nan/include_dirs.js | 1 + .../kerberos/node_modules/nan/nan.h | 2331 ++++++++ .../kerberos/node_modules/nan/package.json | 79 + .../node_modules/kerberos/package.json | 55 + .../kerberos/test/kerberos_tests.js | 34 + .../kerberos/test/kerberos_win32_test.js | 19 + .../win32/security_buffer_descriptor_tests.js | 41 + .../test/win32/security_buffer_tests.js | 22 + .../test/win32/security_credentials_tests.js | 55 + .../node_modules/readable-stream/.npmignore | 5 + .../node_modules/readable-stream/LICENSE | 18 + .../node_modules/readable-stream/README.md | 15 + .../node_modules/readable-stream/duplex.js | 1 + .../readable-stream/lib/_stream_duplex.js | 89 + .../lib/_stream_passthrough.js | 46 + .../readable-stream/lib/_stream_readable.js | 982 ++++ .../readable-stream/lib/_stream_transform.js | 210 + .../readable-stream/lib/_stream_writable.js | 386 ++ .../node_modules/core-util-is/README.md | 3 + .../node_modules/core-util-is/float.patch | 604 ++ .../node_modules/core-util-is/lib/util.js | 107 + .../node_modules/core-util-is/package.json | 54 + .../node_modules/core-util-is/util.js | 106 + .../node_modules/inherits/LICENSE | 16 + .../node_modules/inherits/README.md | 42 + .../node_modules/inherits/inherits.js | 1 + .../node_modules/inherits/inherits_browser.js | 23 + .../node_modules/inherits/package.json | 51 + .../node_modules/inherits/test.js | 25 + .../node_modules/isarray/README.md | 54 + .../node_modules/isarray/build/build.js | 209 + .../node_modules/isarray/component.json | 19 + .../node_modules/isarray/index.js | 3 + .../node_modules/isarray/package.json | 54 + .../node_modules/string_decoder/.npmignore | 2 + .../node_modules/string_decoder/LICENSE | 20 + .../node_modules/string_decoder/README.md | 7 + .../node_modules/string_decoder/index.js | 221 + .../node_modules/string_decoder/package.json | 54 + .../node_modules/readable-stream/package.json | 70 + .../readable-stream/passthrough.js | 1 + .../node_modules/readable-stream/readable.js | 8 + .../node_modules/readable-stream/transform.js | 1 + .../node_modules/readable-stream/writable.js | 1 + node_modules/mongodb/package.json | 252 + node_modules/neon/.npmignore | 1 + node_modules/neon/CHANGELOG.markdown | 22 + node_modules/neon/README.markdown | 76 + node_modules/neon/neon.js | 234 + node_modules/neon/package.json | 55 + node_modules/neon/stdlib/bubbling_support.js | 32 + node_modules/neon/stdlib/custom_event.js | 37 + .../neon/stdlib/custom_event_support.js | 180 + node_modules/neon/stdlib/index.js | 7 + node_modules/neon/stdlib/node_support.js | 123 + node_modules/neon/test/neon_browser.html | 11 + .../neon/test/neon_stdlib_browser.html | 15 + node_modules/neon/test/neon_stdlib_test.js | 84 + node_modules/neon/test/neon_test.js | 64 + node_modules/tellurium/CHANGELOG.md | 5 + node_modules/tellurium/README.md | 242 + node_modules/tellurium/build/tellurium-min.js | 1 + node_modules/tellurium/package.json | 44 + .../tellurium/reporters/firebug_reporter.js | 102 + node_modules/tellurium/spec/basic.js | 210 + node_modules/tellurium/spec/browser.html | 20 + node_modules/tellurium/tellurium.js | 901 +++ spec/spec/argon/storage/mongodb.js | 76 + 236 files changed, 55460 insertions(+) create mode 100644 argon/storage/mongodb.js create mode 100644 node_modules/mongodb/.gitmodules create mode 100644 node_modules/mongodb/.travis.yml create mode 100644 node_modules/mongodb/CONTRIBUTING.md create mode 100644 node_modules/mongodb/LICENSE create mode 100644 node_modules/mongodb/Makefile create mode 100644 node_modules/mongodb/Readme.md create mode 100755 node_modules/mongodb/index.js create mode 100644 node_modules/mongodb/lib/mongodb/admin.js create mode 100644 node_modules/mongodb/lib/mongodb/aggregation_cursor.js create mode 100644 node_modules/mongodb/lib/mongodb/auth/mongodb_cr.js create mode 100644 node_modules/mongodb/lib/mongodb/auth/mongodb_gssapi.js create mode 100644 node_modules/mongodb/lib/mongodb/auth/mongodb_plain.js create mode 100644 node_modules/mongodb/lib/mongodb/auth/mongodb_scram.js create mode 100644 node_modules/mongodb/lib/mongodb/auth/mongodb_sspi.js create mode 100644 node_modules/mongodb/lib/mongodb/auth/mongodb_x509.js create mode 100644 node_modules/mongodb/lib/mongodb/collection.js create mode 100644 node_modules/mongodb/lib/mongodb/collection/aggregation.js create mode 100644 node_modules/mongodb/lib/mongodb/collection/batch/common.js create mode 100644 node_modules/mongodb/lib/mongodb/collection/batch/ordered.js create mode 100644 node_modules/mongodb/lib/mongodb/collection/batch/unordered.js create mode 100644 node_modules/mongodb/lib/mongodb/collection/commands.js create mode 100644 node_modules/mongodb/lib/mongodb/collection/core.js create mode 100644 node_modules/mongodb/lib/mongodb/collection/geo.js create mode 100644 node_modules/mongodb/lib/mongodb/collection/index.js create mode 100644 node_modules/mongodb/lib/mongodb/collection/query.js create mode 100644 node_modules/mongodb/lib/mongodb/collection/shared.js create mode 100644 node_modules/mongodb/lib/mongodb/command_cursor.js create mode 100644 node_modules/mongodb/lib/mongodb/commands/base_command.js create mode 100644 node_modules/mongodb/lib/mongodb/commands/db_command.js create mode 100644 node_modules/mongodb/lib/mongodb/commands/delete_command.js create mode 100644 node_modules/mongodb/lib/mongodb/commands/get_more_command.js create mode 100644 node_modules/mongodb/lib/mongodb/commands/insert_command.js create mode 100644 node_modules/mongodb/lib/mongodb/commands/kill_cursor_command.js create mode 100644 node_modules/mongodb/lib/mongodb/commands/query_command.js create mode 100644 node_modules/mongodb/lib/mongodb/commands/update_command.js create mode 100644 node_modules/mongodb/lib/mongodb/connection/base.js create mode 100644 node_modules/mongodb/lib/mongodb/connection/connection.js create mode 100644 node_modules/mongodb/lib/mongodb/connection/connection_pool.js create mode 100644 node_modules/mongodb/lib/mongodb/connection/connection_utils.js create mode 100644 node_modules/mongodb/lib/mongodb/connection/mongos.js create mode 100644 node_modules/mongodb/lib/mongodb/connection/read_preference.js create mode 100644 node_modules/mongodb/lib/mongodb/connection/repl_set/ha.js create mode 100644 node_modules/mongodb/lib/mongodb/connection/repl_set/options.js create mode 100644 node_modules/mongodb/lib/mongodb/connection/repl_set/repl_set.js create mode 100644 node_modules/mongodb/lib/mongodb/connection/repl_set/repl_set_state.js create mode 100644 node_modules/mongodb/lib/mongodb/connection/repl_set/strategies/ping_strategy.js create mode 100644 node_modules/mongodb/lib/mongodb/connection/repl_set/strategies/statistics_strategy.js create mode 100644 node_modules/mongodb/lib/mongodb/connection/server.js create mode 100644 node_modules/mongodb/lib/mongodb/connection/server_capabilities.js create mode 100644 node_modules/mongodb/lib/mongodb/connection/url_parser.js create mode 100644 node_modules/mongodb/lib/mongodb/cursor.js create mode 100644 node_modules/mongodb/lib/mongodb/cursorstream.js create mode 100644 node_modules/mongodb/lib/mongodb/db.js create mode 100644 node_modules/mongodb/lib/mongodb/gridfs/chunk.js create mode 100644 node_modules/mongodb/lib/mongodb/gridfs/grid.js create mode 100644 node_modules/mongodb/lib/mongodb/gridfs/gridstore.js create mode 100644 node_modules/mongodb/lib/mongodb/gridfs/readstream.js create mode 100644 node_modules/mongodb/lib/mongodb/index.js create mode 100644 node_modules/mongodb/lib/mongodb/mongo_client.js create mode 100644 node_modules/mongodb/lib/mongodb/responses/mongo_reply.js create mode 100644 node_modules/mongodb/lib/mongodb/scope.js create mode 100644 node_modules/mongodb/lib/mongodb/utils.js create mode 100644 node_modules/mongodb/node_modules/bson/.travis.yml create mode 100644 node_modules/mongodb/node_modules/bson/LICENSE create mode 100644 node_modules/mongodb/node_modules/bson/Makefile create mode 100644 node_modules/mongodb/node_modules/bson/README.md create mode 100644 node_modules/mongodb/node_modules/bson/binding.gyp create mode 100644 node_modules/mongodb/node_modules/bson/browser_build/bson.js create mode 100644 node_modules/mongodb/node_modules/bson/browser_build/package.json create mode 100644 node_modules/mongodb/node_modules/bson/build/Makefile create mode 100644 node_modules/mongodb/node_modules/bson/build/Release/.deps/Release/bson.node.d create mode 100644 node_modules/mongodb/node_modules/bson/build/Release/.deps/Release/obj.target/bson/ext/bson.o.d create mode 100755 node_modules/mongodb/node_modules/bson/build/Release/bson.node create mode 100644 node_modules/mongodb/node_modules/bson/build/Release/linker.lock create mode 100644 node_modules/mongodb/node_modules/bson/build/Release/obj.target/bson/ext/bson.o create mode 100644 node_modules/mongodb/node_modules/bson/build/binding.Makefile create mode 100644 node_modules/mongodb/node_modules/bson/build/bson.target.mk create mode 100644 node_modules/mongodb/node_modules/bson/build/config.gypi create mode 100755 node_modules/mongodb/node_modules/bson/build/gyp-mac-tool create mode 100644 node_modules/mongodb/node_modules/bson/build_browser.js create mode 100644 node_modules/mongodb/node_modules/bson/builderror.log create mode 100644 node_modules/mongodb/node_modules/bson/ext/Makefile create mode 100644 node_modules/mongodb/node_modules/bson/ext/bson.cc create mode 100644 node_modules/mongodb/node_modules/bson/ext/bson.h create mode 100644 node_modules/mongodb/node_modules/bson/ext/index.js create mode 100644 node_modules/mongodb/node_modules/bson/ext/win32/ia32/bson.node create mode 100644 node_modules/mongodb/node_modules/bson/ext/win32/x64/bson.node create mode 100644 node_modules/mongodb/node_modules/bson/ext/wscript create mode 100644 node_modules/mongodb/node_modules/bson/lib/bson/binary.js create mode 100644 node_modules/mongodb/node_modules/bson/lib/bson/binary_parser.js create mode 100644 node_modules/mongodb/node_modules/bson/lib/bson/bson.js create mode 100644 node_modules/mongodb/node_modules/bson/lib/bson/bson_new.js create mode 100644 node_modules/mongodb/node_modules/bson/lib/bson/code.js create mode 100644 node_modules/mongodb/node_modules/bson/lib/bson/db_ref.js create mode 100644 node_modules/mongodb/node_modules/bson/lib/bson/double.js create mode 100644 node_modules/mongodb/node_modules/bson/lib/bson/float_parser.js create mode 100644 node_modules/mongodb/node_modules/bson/lib/bson/index.js create mode 100644 node_modules/mongodb/node_modules/bson/lib/bson/long.js create mode 100644 node_modules/mongodb/node_modules/bson/lib/bson/max_key.js create mode 100644 node_modules/mongodb/node_modules/bson/lib/bson/min_key.js create mode 100644 node_modules/mongodb/node_modules/bson/lib/bson/objectid.js create mode 100644 node_modules/mongodb/node_modules/bson/lib/bson/symbol.js create mode 100644 node_modules/mongodb/node_modules/bson/lib/bson/timestamp.js create mode 100644 node_modules/mongodb/node_modules/bson/node_modules/nan/.dntrc create mode 100644 node_modules/mongodb/node_modules/bson/node_modules/nan/CHANGELOG.md create mode 100644 node_modules/mongodb/node_modules/bson/node_modules/nan/LICENSE create mode 100644 node_modules/mongodb/node_modules/bson/node_modules/nan/README.md create mode 100644 node_modules/mongodb/node_modules/bson/node_modules/nan/appveyor.yml create mode 100644 node_modules/mongodb/node_modules/bson/node_modules/nan/include_dirs.js create mode 100644 node_modules/mongodb/node_modules/bson/node_modules/nan/nan.h create mode 100644 node_modules/mongodb/node_modules/bson/node_modules/nan/package.json create mode 100644 node_modules/mongodb/node_modules/bson/package.json create mode 100644 node_modules/mongodb/node_modules/bson/tools/gleak.js create mode 100644 node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/MIT.LICENSE create mode 100644 node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine-html.js create mode 100644 node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine.css create mode 100644 node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine.js create mode 100644 node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine_favicon.png create mode 100644 node_modules/mongodb/node_modules/kerberos/LICENSE create mode 100644 node_modules/mongodb/node_modules/kerberos/README.md create mode 100644 node_modules/mongodb/node_modules/kerberos/binding.gyp create mode 100644 node_modules/mongodb/node_modules/kerberos/build/Makefile create mode 100644 node_modules/mongodb/node_modules/kerberos/build/Release/.deps/Release/obj.target/kerberos/lib/kerberos.o.d.raw create mode 100644 node_modules/mongodb/node_modules/kerberos/build/binding.Makefile create mode 100644 node_modules/mongodb/node_modules/kerberos/build/config.gypi create mode 100755 node_modules/mongodb/node_modules/kerberos/build/gyp-mac-tool create mode 100644 node_modules/mongodb/node_modules/kerberos/build/kerberos.target.mk create mode 100644 node_modules/mongodb/node_modules/kerberos/builderror.log create mode 100644 node_modules/mongodb/node_modules/kerberos/index.js create mode 100644 node_modules/mongodb/node_modules/kerberos/lib/auth_processes/mongodb.js create mode 100644 node_modules/mongodb/node_modules/kerberos/lib/base64.c create mode 100644 node_modules/mongodb/node_modules/kerberos/lib/base64.h create mode 100644 node_modules/mongodb/node_modules/kerberos/lib/kerberos.cc create mode 100644 node_modules/mongodb/node_modules/kerberos/lib/kerberos.h create mode 100644 node_modules/mongodb/node_modules/kerberos/lib/kerberos.js create mode 100644 node_modules/mongodb/node_modules/kerberos/lib/kerberos_context.cc create mode 100644 node_modules/mongodb/node_modules/kerberos/lib/kerberos_context.h create mode 100644 node_modules/mongodb/node_modules/kerberos/lib/kerberosgss.c create mode 100644 node_modules/mongodb/node_modules/kerberos/lib/kerberosgss.h create mode 100644 node_modules/mongodb/node_modules/kerberos/lib/sspi.js create mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/base64.c create mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/base64.h create mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos.cc create mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos.h create mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos_sspi.c create mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos_sspi.h create mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/worker.cc create mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/worker.h create mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.cc create mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.h create mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.js create mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.cc create mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.h create mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.js create mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.cc create mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.h create mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.js create mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.cc create mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.h create mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.js create mode 100644 node_modules/mongodb/node_modules/kerberos/lib/worker.cc create mode 100644 node_modules/mongodb/node_modules/kerberos/lib/worker.h create mode 100644 node_modules/mongodb/node_modules/kerberos/node_modules/nan/.dntrc create mode 100644 node_modules/mongodb/node_modules/kerberos/node_modules/nan/CHANGELOG.md create mode 100644 node_modules/mongodb/node_modules/kerberos/node_modules/nan/LICENSE create mode 100644 node_modules/mongodb/node_modules/kerberos/node_modules/nan/README.md create mode 100644 node_modules/mongodb/node_modules/kerberos/node_modules/nan/appveyor.yml create mode 100644 node_modules/mongodb/node_modules/kerberos/node_modules/nan/include_dirs.js create mode 100644 node_modules/mongodb/node_modules/kerberos/node_modules/nan/nan.h create mode 100644 node_modules/mongodb/node_modules/kerberos/node_modules/nan/package.json create mode 100644 node_modules/mongodb/node_modules/kerberos/package.json create mode 100644 node_modules/mongodb/node_modules/kerberos/test/kerberos_tests.js create mode 100644 node_modules/mongodb/node_modules/kerberos/test/kerberos_win32_test.js create mode 100644 node_modules/mongodb/node_modules/kerberos/test/win32/security_buffer_descriptor_tests.js create mode 100644 node_modules/mongodb/node_modules/kerberos/test/win32/security_buffer_tests.js create mode 100644 node_modules/mongodb/node_modules/kerberos/test/win32/security_credentials_tests.js create mode 100644 node_modules/mongodb/node_modules/readable-stream/.npmignore create mode 100644 node_modules/mongodb/node_modules/readable-stream/LICENSE create mode 100644 node_modules/mongodb/node_modules/readable-stream/README.md create mode 100644 node_modules/mongodb/node_modules/readable-stream/duplex.js create mode 100644 node_modules/mongodb/node_modules/readable-stream/lib/_stream_duplex.js create mode 100644 node_modules/mongodb/node_modules/readable-stream/lib/_stream_passthrough.js create mode 100644 node_modules/mongodb/node_modules/readable-stream/lib/_stream_readable.js create mode 100644 node_modules/mongodb/node_modules/readable-stream/lib/_stream_transform.js create mode 100644 node_modules/mongodb/node_modules/readable-stream/lib/_stream_writable.js create mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/README.md create mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/float.patch create mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/lib/util.js create mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/package.json create mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/util.js create mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/LICENSE create mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/README.md create mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/inherits.js create mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/inherits_browser.js create mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/package.json create mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/test.js create mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/README.md create mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/build/build.js create mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/component.json create mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/index.js create mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/package.json create mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/.npmignore create mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/LICENSE create mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/README.md create mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/index.js create mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/package.json create mode 100644 node_modules/mongodb/node_modules/readable-stream/package.json create mode 100644 node_modules/mongodb/node_modules/readable-stream/passthrough.js create mode 100644 node_modules/mongodb/node_modules/readable-stream/readable.js create mode 100644 node_modules/mongodb/node_modules/readable-stream/transform.js create mode 100644 node_modules/mongodb/node_modules/readable-stream/writable.js create mode 100755 node_modules/mongodb/package.json create mode 100644 node_modules/neon/.npmignore create mode 100644 node_modules/neon/CHANGELOG.markdown create mode 100644 node_modules/neon/README.markdown create mode 100644 node_modules/neon/neon.js create mode 100644 node_modules/neon/package.json create mode 100644 node_modules/neon/stdlib/bubbling_support.js create mode 100644 node_modules/neon/stdlib/custom_event.js create mode 100644 node_modules/neon/stdlib/custom_event_support.js create mode 100644 node_modules/neon/stdlib/index.js create mode 100644 node_modules/neon/stdlib/node_support.js create mode 100644 node_modules/neon/test/neon_browser.html create mode 100644 node_modules/neon/test/neon_stdlib_browser.html create mode 100644 node_modules/neon/test/neon_stdlib_test.js create mode 100644 node_modules/neon/test/neon_test.js create mode 100644 node_modules/tellurium/CHANGELOG.md create mode 100644 node_modules/tellurium/README.md create mode 100644 node_modules/tellurium/build/tellurium-min.js create mode 100644 node_modules/tellurium/package.json create mode 100644 node_modules/tellurium/reporters/firebug_reporter.js create mode 100644 node_modules/tellurium/spec/basic.js create mode 100644 node_modules/tellurium/spec/browser.html create mode 100644 node_modules/tellurium/tellurium.js create mode 100644 spec/spec/argon/storage/mongodb.js diff --git a/argon/storage/mongodb.js b/argon/storage/mongodb.js new file mode 100644 index 0000000..f1ce2db --- /dev/null +++ b/argon/storage/mongodb.js @@ -0,0 +1,90 @@ +Class(Argon.Storage, 'MongoDB')({ + + prototype : { + + driver : null, + collectionName : null, + collection : null, + + preprocessors : [], + processors : [], + + init : function init(config) { + if(this.preprocessors instanceof Array === false){ + this.preprocessors = [].concat(this.constructor.preprocessors); + } + + if(this.preprocessors instanceof Array === false){ + this.preprocessors = [].concat(this.constructor.preprocessors); + } + + this.driver = config.driver; + this.collectionName = config.collectionName; + this.collection = config.driver.collection(this.collectionName); + + return this; + }, + + create : function create(requestObj, callback) { + var storage = this; + + for (var i = 0; i < this.preprocessors.length; i++) { + requestObj.data = this.preprocessors[i](requestObj.data, requestObj); + } + + this.collection.insert(requestObj.data, function handleInsert(error, data) { + if (error) { + return callback(error); + } + + data = data[0]; + + for (var i = 0; i < storage.processors.length; i++) { + data = storage.processors[i](data, requestObj); + } + + callback(data); + }); + + return this; + }, + + update : function update(requestObj, callback) { + for (i = 0; i < this.preprocessors.length; i++) { + requestObj.data = this.preprocessors[i](requestObj.data, requestObj); + } + + this.collection.update({_id : requestObj.data._id}, requestObj.data, function handleInsert(error, data) { + callback(error || data); + }); + + return this; + }, + + find : function find(requestObj, callback) { + this.collection.find().toArray(function findCallback(error, data) { + callback(error || data.map(function (item) { return new requestObj.model(item)})); + }); + + return this; + }, + + findOne : function findOne(requestObj, callback) { + this.collection.find({_id : requestObj.data._id}, function findCallback(error, data) { + callback(error || data.map(function (item) { return new requestObj.model(item)})[0]); + }); + + return this; + }, + + remove : function remove(requestObj, callback) { + var id = requestObj.data._id; + + this.collection.remove({_id : id}, function removeCallback(error, data) { + callback(error || data); + }); + + return this; + } + } +}); \ No newline at end of file diff --git a/node_modules/mongodb/.gitmodules b/node_modules/mongodb/.gitmodules new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/mongodb/.travis.yml b/node_modules/mongodb/.travis.yml new file mode 100644 index 0000000..a55b235 --- /dev/null +++ b/node_modules/mongodb/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - 0.8 + - 0.10 + - 0.11 \ No newline at end of file diff --git a/node_modules/mongodb/CONTRIBUTING.md b/node_modules/mongodb/CONTRIBUTING.md new file mode 100644 index 0000000..c23e426 --- /dev/null +++ b/node_modules/mongodb/CONTRIBUTING.md @@ -0,0 +1,23 @@ +## Contributing to the driver + +### Bugfixes + +- Before starting to write code, look for existing [tickets](https://jira.mongodb.org/browse/NODE) or [create one](https://jira.mongodb.org/secure/CreateIssue!default.jspa) for your specific issue under the "Node Driver" project. That way you avoid working on something that might not be of interest or that has been addressed already in a different branch. +- Fork the [repo](https://github.com/mongodb/node-mongodb-native) _or_ for small documentation changes, navigate to the source on github and click the [Edit](https://github.com/blog/844-forking-with-the-edit-button) button. +- Follow the general coding style of the rest of the project: + - 2 space tabs + - no trailing whitespace + - comma last + - inline documentation for new methods, class members, etc + - 0 space between conditionals/functions, and their parenthesis and curly braces + - `if(..) {` + - `for(..) {` + - `while(..) {` + - `function(err) {` +- Write tests and make sure they pass (execute `npm test` from the cmd line to run the test suite). + +### Documentation + +To contribute to the [API documentation](http://mongodb.github.com/node-mongodb-native/) just make your changes to the inline documentation of the appropriate [source code](https://github.com/mongodb/node-mongodb-native/tree/master/docs) in the master branch and submit a [pull request](https://help.github.com/articles/using-pull-requests/). You might also use the github [Edit](https://github.com/blog/844-forking-with-the-edit-button) button. + +If you'd like to preview your documentation changes, first commit your changes to your local master branch, then execute `make generate_docs`. Make sure you have the python documentation framework sphinx installed `easy_install sphinx`. The docs are generated under `docs/build'. If all looks good, submit a [pull request](https://help.github.com/articles/using-pull-requests/) to the master branch with your changes. diff --git a/node_modules/mongodb/LICENSE b/node_modules/mongodb/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/node_modules/mongodb/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/node_modules/mongodb/Makefile b/node_modules/mongodb/Makefile new file mode 100644 index 0000000..59d2bfe --- /dev/null +++ b/node_modules/mongodb/Makefile @@ -0,0 +1,28 @@ +NODE = node +NPM = npm +NODEUNIT = node_modules/nodeunit/bin/nodeunit +DOX = node_modules/dox/bin/dox +name = all + +total: build_native + +test_functional: + node test/runner.js -t functional + +test_ssl: + node test/runner.js -t ssl + +test_replicaset: + node test/runner.js -t replicaset + +test_sharded: + node test/runner.js -t sharded + +test_auth: + node test/runner.js -t auth + +generate_docs: + $(NODE) dev/tools/build-docs.js + make --directory=./docs/sphinx-docs --file=Makefile html + +.PHONY: total diff --git a/node_modules/mongodb/Readme.md b/node_modules/mongodb/Readme.md new file mode 100644 index 0000000..5e4877d --- /dev/null +++ b/node_modules/mongodb/Readme.md @@ -0,0 +1,418 @@ +## MongoDB Node.JS Driver + +| what | where | +|---------------|------------------------------------------------| +| documentation | http://mongodb.github.io/node-mongodb-native/ | +| apidoc | http://mongodb.github.io/node-mongodb-native/ | +| source | https://github.com/mongodb/node-mongodb-native | +| mongodb | http://www.mongodb.org/ | + +### Blogs of Engineers involved in the driver +- Christian Kvalheim [@christkv](https://twitter.com/christkv) +- Valeri Karpov [@code_barbarian](https://twitter.com/code_barbarian) + +### Bugs / Feature Requests + +Think you’ve found a bug? Want to see a new feature in node-mongodb-native? Please open a +case in our issue management tool, JIRA: + +- Create an account and login . +- Navigate to the NODE project . +- Click **Create Issue** - Please provide as much information as possible about the issue type and how to reproduce it. + +Bug reports in JIRA for all driver projects (i.e. NODE, PYTHON, CSHARP, JAVA) and the +Core Server (i.e. SERVER) project are **public**. + +### Questions and Bug Reports + + * mailing list: https://groups.google.com/forum/#!forum/node-mongodb-native + * jira: http://jira.mongodb.org/ + +### Change Log + +http://jira.mongodb.org/browse/NODE + +## Install + +To install the most recent release from npm, run: + + npm install mongodb + +That may give you a warning telling you that bugs['web'] should be bugs['url'], it would be safe to ignore it (this has been fixed in the development version) + +To install the latest from the repository, run:: + + npm install path/to/node-mongodb-native + +## Live Examples + + +## Introduction + +This is a node.js driver for MongoDB. It's a port (or close to a port) of the library for ruby at http://github.com/mongodb/mongo-ruby-driver/. + +A simple example of inserting a document. + +```javascript + var MongoClient = require('mongodb').MongoClient + , format = require('util').format; + + MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) { + if(err) throw err; + + var collection = db.collection('test_insert'); + collection.insert({a:2}, function(err, docs) { + + collection.count(function(err, count) { + console.log(format("count = %s", count)); + }); + + // Locate all the entries using find + collection.find().toArray(function(err, results) { + console.dir(results); + // Let's close the db + db.close(); + }); + }); + }) +``` + +## Data types + +To store and retrieve the non-JSON MongoDb primitives ([ObjectID](http://www.mongodb.org/display/DOCS/Object+IDs), Long, Binary, [Timestamp](http://www.mongodb.org/display/DOCS/Timestamp+data+type), [DBRef](http://www.mongodb.org/display/DOCS/Database+References#DatabaseReferences-DBRef), Code). + +In particular, every document has a unique `_id` which can be almost any type, and by default a 12-byte ObjectID is created. ObjectIDs can be represented as 24-digit hexadecimal strings, but you must convert the string back into an ObjectID before you can use it in the database. For example: + +```javascript + // Get the objectID type + var ObjectID = require('mongodb').ObjectID; + + var idString = '4e4e1638c85e808431000003'; + collection.findOne({_id: new ObjectID(idString)}, console.log) // ok + collection.findOne({_id: idString}, console.log) // wrong! callback gets undefined +``` + +Here are the constructors the non-Javascript BSON primitive types: + +```javascript + // Fetch the library + var mongo = require('mongodb'); + // Create new instances of BSON types + new mongo.Long(numberString) + new mongo.ObjectID(hexString) + new mongo.Timestamp() // the actual unique number is generated on insert. + new mongo.DBRef(collectionName, id, dbName) + new mongo.Binary(buffer) // takes a string or Buffer + new mongo.Code(code, [context]) + new mongo.Symbol(string) + new mongo.MinKey() + new mongo.MaxKey() + new mongo.Double(number) // Force double storage +``` + +### The C/C++ bson parser/serializer + +If you are running a version of this library has the C/C++ parser compiled, to enable the driver to use the C/C++ bson parser pass it the option native_parser:true like below + +```javascript + // using native_parser: + MongoClient.connect('mongodb://127.0.0.1:27017/test' + , {db: {native_parser: true}}, function(err, db) {}) +``` + +The C++ parser uses the js objects both for serialization and deserialization. + +## GitHub information + +The source code is available at http://github.com/mongodb/node-mongodb-native. +You can either clone the repository or download a tarball of the latest release. + +Once you have the source you can test the driver by running + + $ node test/runner.js -t functional + +in the main directory. You will need to have a mongo instance running on localhost for the integration tests to pass. + +## Examples + +For examples look in the examples/ directory. You can execute the examples using node. + + $ cd examples + $ node queries.js + +## GridStore + +The GridStore class allows for storage of binary files in mongoDB using the mongoDB defined files and chunks collection definition. + +For more information have a look at [Gridstore](https://github.com/mongodb/node-mongodb-native/blob/master/docs/gridfs.md) + +## Replicasets + +For more information about how to connect to a replicaset have a look at the extensive documentation [Documentation](http://mongodb.github.com/node-mongodb-native/) + +### Primary Key Factories + +Defining your own primary key factory allows you to generate your own series of id's +(this could f.ex be to use something like ISBN numbers). The generated the id needs to be a 12 byte long "string". + +Simple example below + +```javascript + var MongoClient = require('mongodb').MongoClient + , format = require('util').format; + + // Custom factory (need to provide a 12 byte array); + CustomPKFactory = function() {} + CustomPKFactory.prototype = new Object(); + CustomPKFactory.createPk = function() { + return new ObjectID("aaaaaaaaaaaa"); + } + + MongoClient.connect('mongodb://127.0.0.1:27017/test', {'pkFactory':CustomPKFactory}, function(err, db) { + if(err) throw err; + + db.dropDatabase(function(err, done) { + + db.createCollection('test_custom_key', function(err, collection) { + + collection.insert({'a':1}, function(err, docs) { + + collection.find({'_id':new ObjectID("aaaaaaaaaaaa")}).toArray(function(err, items) { + console.dir(items); + // Let's close the db + db.close(); + }); + }); + }); + }); + }); +``` + +## Documentation + +If this document doesn't answer your questions, see the source of +[Collection](https://github.com/mongodb/node-mongodb-native/blob/master/lib/mongodb/collection.js) +or [Cursor](https://github.com/mongodb/node-mongodb-native/blob/master/lib/mongodb/cursor.js), +or the documentation at MongoDB for query and update formats. + +### Find + +The find method is actually a factory method to create +Cursor objects. A Cursor lazily uses the connection the first time +you call `nextObject`, `each`, or `toArray`. + +The basic operation on a cursor is the `nextObject` method +that fetches the next matching document from the database. The convenience +methods `each` and `toArray` call `nextObject` until the cursor is exhausted. + +Signatures: + +```javascript + var cursor = collection.find(query, [fields], options); + cursor.sort(fields).limit(n).skip(m). + + cursor.nextObject(function(err, doc) {}); + cursor.each(function(err, doc) {}); + cursor.toArray(function(err, docs) {}); + + cursor.rewind() // reset the cursor to its initial state. +``` + +Useful chainable methods of cursor. These can optionally be options of `find` instead of method calls: + + * `.limit(n).skip(m)` to control paging. + * `.sort(fields)` Order by the given fields. There are several equivalent syntaxes: + * `.sort({field1: -1, field2: 1})` descending by field1, then ascending by field2. + * `.sort([['field1', 'desc'], ['field2', 'asc']])` same as above + * `.sort([['field1', 'desc'], 'field2'])` same as above + * `.sort('field1')` ascending by field1 + +Other options of `find`: + +* `fields` the fields to fetch (to avoid transferring the entire document) +* `tailable` if true, makes the cursor [tailable](http://www.mongodb.org/display/DOCS/Tailable+Cursors). +* `batchSize` The number of the subset of results to request the database +to return for every request. This should initially be greater than 1 otherwise +the database will automatically close the cursor. The batch size can be set to 1 +with `batchSize(n, function(err){})` after performing the initial query to the database. +* `hint` See [Optimization: hint](http://www.mongodb.org/display/DOCS/Optimization#Optimization-Hint). +* `explain` turns this into an explain query. You can also call +`explain()` on any cursor to fetch the explanation. +* `snapshot` prevents documents that are updated while the query is active +from being returned multiple times. See more +[details about query snapshots](http://www.mongodb.org/display/DOCS/How+to+do+Snapshotted+Queries+in+the+Mongo+Database). +* `timeout` if false, asks MongoDb not to time out this cursor after an +inactivity period. + +For information on how to create queries, see the +[MongoDB section on querying](http://www.mongodb.org/display/DOCS/Querying). + +```javascript + var MongoClient = require('mongodb').MongoClient + , format = require('util').format; + + MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) { + if(err) throw err; + + var collection = db + .collection('test') + .find({}) + .limit(10) + .toArray(function(err, docs) { + console.dir(docs); + }); + }); +``` + +### Insert + +Signature: + +```javascript + collection.insert(docs, options, [callback]); +``` + +where `docs` can be a single document or an array of documents. + +Useful options: + +* `w:1` Should always set if you have a callback. + +See also: [MongoDB docs for insert](http://www.mongodb.org/display/DOCS/Inserting). + +```javascript + var MongoClient = require('mongodb').MongoClient + , format = require('util').format; + + MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) { + if(err) throw err; + + db.collection('test').insert({hello: 'world'}, {w:1}, function(err, objects) { + if (err) console.warn(err.message); + if (err && err.message.indexOf('E11000 ') !== -1) { + // this _id was already inserted in the database + } + }); + }); +``` + +Note that there's no reason to pass a callback to the insert or update commands +unless you use the `w:1` option. If you don't specify `w:1`, then +your callback will be called immediately. + +### Update: update and insert (upsert) + +The update operation will update the first document that matches your query +(or all documents that match if you use `multi:true`). +If `w:1`, `upsert` is not set, and no documents match, your callback will return 0 documents updated. + +See the [MongoDB docs](http://www.mongodb.org/display/DOCS/Updating) for +the modifier (`$inc`, `$set`, `$push`, etc.) formats. + +Signature: + +```javascript + collection.update(criteria, objNew, options, [callback]); +``` + +Useful options: + +* `w:1` Should always set if you have a callback. +* `multi:true` If set, all matching documents are updated, not just the first. +* `upsert:true` Atomically inserts the document if no documents matched. + +Example for `update`: + +```javascript + var MongoClient = require('mongodb').MongoClient + , format = require('util').format; + + MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) { + if(err) throw err; + + db.collection('test').update({hi: 'here'}, {$set: {hi: 'there'}}, {w:1}, function(err) { + if (err) console.warn(err.message); + else console.log('successfully updated'); + }); + }); +``` + +### Find and modify + +`findAndModify` is like `update`, but it also gives the updated document to +your callback. But there are a few key differences between findAndModify and +update: + + 1. The signatures differ. + 2. You can only findAndModify a single item, not multiple items. + +Signature: + +```javascript + collection.findAndModify(query, sort, update, options, callback) +``` + +The sort parameter is used to specify which object to operate on, if more than +one document matches. It takes the same format as the cursor sort (see +Connection.find above). + +See the +[MongoDB docs for findAndModify](http://www.mongodb.org/display/DOCS/findAndModify+Command) +for more details. + +Useful options: + +* `remove:true` set to a true to remove the object before returning +* `new:true` set to true if you want to return the modified object rather than the original. Ignored for remove. +* `upsert:true` Atomically inserts the document if no documents matched. + +Example for `findAndModify`: + +```javascript + var MongoClient = require('mongodb').MongoClient + , format = require('util').format; + + MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) { + if(err) throw err; + db.collection('test').findAndModify({hello: 'world'}, [['_id','asc']], {$set: {hi: 'there'}}, {}, function(err, object) { + if (err) console.warn(err.message); + else console.dir(object); // undefined if no matching object exists. + }); + }); +``` + +### Save + +The `save` method is a shorthand for upsert if the document contains an +`_id`, or an insert if there is no `_id`. + +## Release Notes + +See HISTORY + +## Credits + +1. [10gen](http://github.com/mongodb/mongo-ruby-driver/) +2. [Google Closure Library](http://code.google.com/closure/library/) +3. [Jonas Raoni Soares Silva](http://jsfromhell.com/classes/binary-parser) + +## Contributors + +Aaron Heckmann, Christoph Pojer, Pau Ramon Revilla, Nathan White, Emmerman, Seth LaForge, Boris Filipov, Stefan Schärmeli, Tedde Lundgren, renctan, Sergey Ukustov, Ciaran Jessup, kuno, srimonti, Erik Abele, Pratik Daga, Slobodan Utvic, Kristina Chodorow, Yonathan Randolph, Brian Noguchi, Sam Epstein, James Harrison Fisher, Vladimir Dronnikov, Ben Hockey, Henrik Johansson, Simon Weare, Alex Gorbatchev, Shimon Doodkin, Kyle Mueller, Eran Hammer-Lahav, Marcin Ciszak, François de Metz, Vinay Pulim, nstielau, Adam Wiggins, entrinzikyl, Jeremy Selier, Ian Millington, Public Keating, andrewjstone, Christopher Stott, Corey Jewett, brettkiefer, Rob Holland, Senmiao Liu, heroic, gitfy + +## License + + Copyright 2009 - 2013 MongoDb Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/node_modules/mongodb/index.js b/node_modules/mongodb/index.js new file mode 100755 index 0000000..4f59e9d --- /dev/null +++ b/node_modules/mongodb/index.js @@ -0,0 +1 @@ +module.exports = require('./lib/mongodb'); diff --git a/node_modules/mongodb/lib/mongodb/admin.js b/node_modules/mongodb/lib/mongodb/admin.js new file mode 100644 index 0000000..c1f6eb5 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/admin.js @@ -0,0 +1,340 @@ +/*! + * Module dependencies. + */ +var Collection = require('./collection').Collection, + Cursor = require('./cursor').Cursor, + DbCommand = require('./commands/db_command').DbCommand, + utils = require('./utils'); + +/** + * Allows the user to access the admin functionality of MongoDB + * + * @class Represents the Admin methods of MongoDB. + * @param {Object} db Current db instance we wish to perform Admin operations on. + * @return {Function} Constructor for Admin type. + */ +function Admin(db) { + if(!(this instanceof Admin)) return new Admin(db); + + /** + * Retrieve the server information for the current + * instance of the db client + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from buildInfo or null if an error occured. + * @return {null} Returns no result + * @api public + */ + this.buildInfo = function(callback) { + this.serverInfo(callback); + } + + /** + * Retrieve the server information for the current + * instance of the db client + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from serverInfo or null if an error occured. + * @return {null} Returns no result + * @api private + */ + this.serverInfo = function(callback) { + db.executeDbAdminCommand({buildinfo:1}, function(err, doc) { + if(err != null) return callback(err, null); + return callback(null, doc.documents[0]); + }); + } + + /** + * Retrieve this db's server status. + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from serverStatus or null if an error occured. + * @return {null} + * @api public + */ + this.serverStatus = function(callback) { + var self = this; + + db.executeDbAdminCommand({serverStatus: 1}, function(err, doc) { + if(err == null && doc.documents[0].ok === 1) { + callback(null, doc.documents[0]); + } else { + if(err) return callback(err, false); + return callback(utils.toError(doc.documents[0]), false); + } + }); + }; + + /** + * Retrieve the current profiling Level for MongoDB + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from profilingLevel or null if an error occured. + * @return {null} Returns no result + * @api public + */ + this.profilingLevel = function(callback) { + var self = this; + + db.executeDbAdminCommand({profile:-1}, function(err, doc) { + doc = doc.documents[0]; + + if(err == null && doc.ok === 1) { + var was = doc.was; + if(was == 0) return callback(null, "off"); + if(was == 1) return callback(null, "slow_only"); + if(was == 2) return callback(null, "all"); + return callback(new Error("Error: illegal profiling level value " + was), null); + } else { + err != null ? callback(err, null) : callback(new Error("Error with profile command"), null); + } + }); + }; + + /** + * Ping the MongoDB server and retrieve results + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from ping or null if an error occured. + * @return {null} Returns no result + * @api public + */ + this.ping = function(options, callback) { + // Unpack calls + var args = Array.prototype.slice.call(arguments, 0); + db.executeDbAdminCommand({ping: 1}, args.pop()); + } + + /** + * Authenticate against MongoDB + * + * @param {String} username The user name for the authentication. + * @param {String} password The password for the authentication. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from authenticate or null if an error occured. + * @return {null} Returns no result + * @api public + */ + this.authenticate = function(username, password, callback) { + db.authenticate(username, password, {authdb: 'admin'}, function(err, doc) { + return callback(err, doc); + }) + } + + /** + * Logout current authenticated user + * + * @param {Object} [options] Optional parameters to the command. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from logout or null if an error occured. + * @return {null} Returns no result + * @api public + */ + this.logout = function(callback) { + db.logout({authdb: 'admin'}, function(err, doc) { + return callback(err, doc); + }) + } + + /** + * Add a user to the MongoDB server, if the user exists it will + * overwrite the current password + * + * Options + * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal + * - **j**, (Boolean, default:false) write waits for journal sync before returning + * + * @param {String} username The user name for the authentication. + * @param {String} password The password for the authentication. + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from addUser or null if an error occured. + * @return {null} Returns no result + * @api public + */ + this.addUser = function(username, password, options, callback) { + var args = Array.prototype.slice.call(arguments, 2); + callback = args.pop(); + options = args.length ? args.shift() : {}; + // Set the db name to admin + options.dbName = 'admin'; + // Add user + db.addUser(username, password, options, function(err, doc) { + return callback(err, doc); + }) + } + /** + * Remove a user from the MongoDB server + * + * Options + * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal + * - **j**, (Boolean, default:false) write waits for journal sync before returning + * + * @param {String} username The user name for the authentication. + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from removeUser or null if an error occured. + * @return {null} Returns no result + * @api public + */ + this.removeUser = function(username, options, callback) { + var self = this; + var args = Array.prototype.slice.call(arguments, 1); + callback = args.pop(); + options = args.length ? args.shift() : {}; + options.dbName = 'admin'; + + db.removeUser(username, options, function(err, doc) { + return callback(err, doc); + }) + } + + /** + * Set the current profiling level of MongoDB + * + * @param {String} level The new profiling level (off, slow_only, all) + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from setProfilingLevel or null if an error occured. + * @return {null} Returns no result + * @api public + */ + this.setProfilingLevel = function(level, callback) { + var self = this; + var command = {}; + var profile = 0; + + if(level == "off") { + profile = 0; + } else if(level == "slow_only") { + profile = 1; + } else if(level == "all") { + profile = 2; + } else { + return callback(new Error("Error: illegal profiling level value " + level)); + } + + // Set up the profile number + command['profile'] = profile; + + db.executeDbAdminCommand(command, function(err, doc) { + doc = doc.documents[0]; + + if(err == null && doc.ok === 1) + return callback(null, level); + return err != null ? callback(err, null) : callback(new Error("Error with profile command"), null); + }); + }; + + /** + * Retrive the current profiling information for MongoDB + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from profilingInfo or null if an error occured. + * @return {null} Returns no result + * @api public + */ + this.profilingInfo = function(callback) { + try { + new Cursor(db, new Collection(db, DbCommand.SYSTEM_PROFILE_COLLECTION), {}, {}, {dbName: 'admin'}).toArray(function(err, items) { + return callback(err, items); + }); + } catch (err) { + return callback(err, null); + } + }; + + /** + * Execute a db command against the Admin database + * + * @param {Object} command A command object `{ping:1}`. + * @param {Object} [options] Optional parameters to the command. + * @param {Function} callback this will be called after executing this method. The command always return the whole result of the command as the second parameter. + * @return {null} Returns no result + * @api public + */ + this.command = function(command, options, callback) { + var self = this; + var args = Array.prototype.slice.call(arguments, 1); + callback = args.pop(); + options = args.length ? args.shift() : {}; + + // Execute a command + db.executeDbAdminCommand(command, options, function(err, doc) { + // Ensure change before event loop executes + return callback != null ? callback(err, doc) : null; + }); + } + + /** + * Validate an existing collection + * + * @param {String} collectionName The name of the collection to validate. + * @param {Object} [options] Optional parameters to the command. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from validateCollection or null if an error occured. + * @return {null} Returns no result + * @api public + */ + this.validateCollection = function(collectionName, options, callback) { + var args = Array.prototype.slice.call(arguments, 1); + callback = args.pop(); + options = args.length ? args.shift() : {}; + + var self = this; + var command = {validate: collectionName}; + var keys = Object.keys(options); + + // Decorate command with extra options + for(var i = 0; i < keys.length; i++) { + if(options.hasOwnProperty(keys[i])) { + command[keys[i]] = options[keys[i]]; + } + } + + db.command(command, function(err, doc) { + if(err != null) return callback(err, null); + + if(doc.ok === 0) + return callback(new Error("Error with validate command"), null); + if(doc.result != null && doc.result.constructor != String) + return callback(new Error("Error with validation data"), null); + if(doc.result != null && doc.result.match(/exception|corrupt/) != null) + return callback(new Error("Error: invalid collection " + collectionName), null); + if(doc.valid != null && !doc.valid) + return callback(new Error("Error: invalid collection " + collectionName), null); + + return callback(null, doc); + }); + }; + + /** + * List the available databases + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from listDatabases or null if an error occured. + * @return {null} Returns no result + * @api public + */ + this.listDatabases = function(callback) { + // Execute the listAllDatabases command + db.executeDbAdminCommand({listDatabases:1}, {}, function(err, doc) { + if(err != null) return callback(err, null); + return callback(null, doc.documents[0]); + }); + } + + /** + * Get ReplicaSet status + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from replSetGetStatus or null if an error occured. + * @return {null} + * @api public + */ + this.replSetGetStatus = function(callback) { + var self = this; + + db.executeDbAdminCommand({replSetGetStatus:1}, function(err, doc) { + if(err == null && doc.documents[0].ok === 1) + return callback(null, doc.documents[0]); + if(err) return callback(err, false); + return callback(utils.toError(doc.documents[0]), false); + }); + }; +}; + +/** + * @ignore + */ +exports.Admin = Admin; diff --git a/node_modules/mongodb/lib/mongodb/aggregation_cursor.js b/node_modules/mongodb/lib/mongodb/aggregation_cursor.js new file mode 100644 index 0000000..5d1cb51 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/aggregation_cursor.js @@ -0,0 +1,187 @@ +var ReadPreference = require('./connection/read_preference').ReadPreference + , Readable = require('stream').Readable || require('readable-stream').Readable + , CommandCursor = require('./command_cursor').CommandCursor + , utils = require('./utils') + , shared = require('./collection/shared') + , inherits = require('util').inherits; + +var AggregationCursor = function(collection, serverCapabilities, options) { + var pipe = []; + var self = this; + var results = null; + var _cursor_options = {}; + // Ensure we have options set up + options = options == null ? {} : options; + + // If a pipeline was provided + pipe = Array.isArray(options.pipe) ? options.pipe : pipe; + // Set passed in batchSize if provided + if(typeof options.batchSize == 'number') _cursor_options.batchSize = options.batchSize; + // Get the read Preference + var readPreference = shared._getReadConcern(collection, options); + + // Set up + Readable.call(this, {objectMode: true}); + + // Contains connection + var connection = null; + + // Set the read preference + var _options = { + readPreference: readPreference + }; + + // Actual command + var command = { + aggregate: collection.collectionName + , pipeline: pipe + , cursor: _cursor_options + } + + // If allowDiskUse is set + if(typeof options.allowDiskUse == 'boolean') + command.allowDiskUse = options.allowDiskUse; + + // Command cursor (if we support one) + var commandCursor = new CommandCursor(collection.db, collection, command); + + this.explain = function(callback) { + if(typeof callback != 'function') + throw utils.toError("AggregationCursor explain requires a callback function"); + + // Add explain options + _options.explain = true; + // Execute aggregation pipeline + collection.aggregate(pipe, _options, function(err, results) { + if(err) return callback(err, null); + callback(null, results); + }); + } + + this.get = function(callback) { + if(typeof callback != 'function') + throw utils.toError("AggregationCursor get requires a callback function"); + // Checkout a connection + var _connection = collection.db.serverConfig.checkoutReader(_options.readPreference); + // Fall back + if(!_connection.serverCapabilities.hasAggregationCursor) { + return collection.aggregate(pipe, _options, function(err, results) { + if(err) return callback(err); + callback(null, results); + }); + } + + // Execute get using command Cursor + commandCursor.get({connection: _connection}, callback); + } + + this.getOne = function(callback) { + if(typeof callback != 'function') + throw utils.toError("AggregationCursor getOne requires a callback function"); + // Set the limit to 1 + pipe.push({$limit: 1}); + // For now we have no cursor command so let's just wrap existing results + collection.aggregate(pipe, _options, function(err, results) { + if(err) return callback(err); + callback(null, results[0]); + }); + } + + this.each = function(callback) { + // Checkout a connection if we have none + if(!connection) + connection = collection.db.serverConfig.checkoutReader(_options.readPreference); + + // Fall back + if(!connection.serverCapabilities.hasAggregationCursor) { + return collection.aggregate(pipe, _options, function(err, _results) { + if(err) return callback(err); + + while(_results.length > 0) { + callback(null, _results.shift()); + } + + callback(null, null); + }); + } + + // Execute each using command Cursor + commandCursor.each({connection: connection}, function(err, doc) { + callback(err, doc); + }); + } + + this.next = function(callback) { + if(typeof callback != 'function') + throw utils.toError("AggregationCursor next requires a callback function"); + + // Checkout a connection if we have none + if(!connection) + connection = collection.db.serverConfig.checkoutReader(_options.readPreference); + + // Fall back + if(!connection.serverCapabilities.hasAggregationCursor) { + if(!results) { + // For now we have no cursor command so let's just wrap existing results + return collection.aggregate(pipe, _options, function(err, _results) { + if(err) return callback(err); + results = _results; + + // Ensure we don't issue undefined + var item = results.shift(); + callback(null, item ? item : null); + }); + } + + // Ensure we don't issue undefined + var item = results.shift(); + // Return the item + return callback(null, item ? item : null); + } + + // Execute next using command Cursor + commandCursor.next({connection: connection}, callback); + } + + // + // Close method + // + this.close = function(callback) { + if(typeof callback != 'function') + throw utils.toError("AggregationCursor close requires a callback function"); + + // Checkout a connection if we have none + if(!connection) + connection = collection.db.serverConfig.checkoutReader(_options.readPreference); + + // Fall back + if(!connection.serverCapabilities.hasAggregationCursor) { + return callback(null, null); + } + + // Execute next using command Cursor + commandCursor.close(callback); + } + + // + // Stream method + // + this._read = function(n) { + self.next(function(err, result) { + if(err) { + self.emit('error', err); + return self.push(null); + } + + self.push(result); + }); + } +} + +// Inherit from Readable +if(Readable != null) { + inherits(AggregationCursor, Readable); +} + +// Exports the Aggregation Framework +exports.AggregationCursor = AggregationCursor; diff --git a/node_modules/mongodb/lib/mongodb/auth/mongodb_cr.js b/node_modules/mongodb/lib/mongodb/auth/mongodb_cr.js new file mode 100644 index 0000000..3484dc3 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/auth/mongodb_cr.js @@ -0,0 +1,81 @@ +var DbCommand = require('../commands/db_command').DbCommand + , utils = require('../utils') + , crypto = require('crypto'); + +var authenticate = function(db, username, password, authdb, options, callback) { + var numberOfConnections = 0; + var errorObject = null; + var numberOfValidConnections = 0; + var credentialsValid = false; + options = options || {}; + + if(options['connection'] != null) { + //if a connection was explicitly passed on options, then we have only one... + numberOfConnections = 1; + } else { + // Get the amount of connections in the pool to ensure we have authenticated all comments + numberOfConnections = db.serverConfig.allRawConnections().length; + options['onAll'] = true; + } + + // Return connection option + options.returnConnection = true; + + // Execute nonce command + db.command({'getnonce':1}, options, function(err, result, connection) { + // Execute on all the connections + if(err == null) { + // Nonce used to make authentication request with md5 hash + var nonce = result.nonce; + + // Use node md5 generator + var md5 = crypto.createHash('md5'); + // Generate keys used for authentication + md5.update(username + ":mongo:" + password); + var hash_password = md5.digest('hex'); + // Final key + md5 = crypto.createHash('md5'); + md5.update(nonce + username + hash_password); + var key = md5.digest('hex'); + + // Creat cmd + var cmd = {'authenticate':1, 'user':username, 'nonce':nonce, 'key':key}; + + // Execute command + db.db(authdb).command(cmd, {connection:connection}, function(err, result) { + // Count down + numberOfConnections = numberOfConnections - 1; + + // Ensure we save any error + if(err) { + errorObject = err; + } else { + credentialsValid = true; + numberOfValidConnections = numberOfValidConnections + 1; + } + + // Work around the case where the number of connections are 0 + if(numberOfConnections <= 0 && typeof callback == 'function') { + var internalCallback = callback; + callback = null; + + if(errorObject == null && credentialsValid) { + db.serverConfig.auth.add('MONGODB-CR', db.databaseName, username, password, authdb); + // Return callback + internalCallback(errorObject, true); + } else if(numberOfValidConnections > 0 && numberOfValidConnections != numberOfConnections + && credentialsValid) { + // One or more servers failed on auth (f.ex secondary hanging on foreground indexing) + db.serverConfig.auth.add('MONGODB-CR', db.databaseName, username, password, authdb); + // Return callback + internalCallback(errorObject, true); + } else { + internalCallback(errorObject, false); + } + } + }); + } + }); +} + +exports.authenticate = authenticate; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/auth/mongodb_gssapi.js b/node_modules/mongodb/lib/mongodb/auth/mongodb_gssapi.js new file mode 100644 index 0000000..e088d19 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/auth/mongodb_gssapi.js @@ -0,0 +1,172 @@ +var DbCommand = require('../commands/db_command').DbCommand + , utils = require('../utils') + , format = require('util').format; + +// Kerberos class +var Kerberos = null; +var MongoAuthProcess = null; +// Try to grab the Kerberos class +try { + Kerberos = require('kerberos').Kerberos + // Authentication process for Mongo + MongoAuthProcess = require('kerberos').processes.MongoAuthProcess +} catch(err) {} + +var authenticate = function(db, username, password, authdb, options, callback) { + var numberOfConnections = 0; + var errorObject = null; + var numberOfValidConnections = 0; + var credentialsValid = false; + options = options || {}; + + // We don't have the Kerberos library + if(Kerberos == null) return callback(new Error("Kerberos library is not installed")); + + if(options['connection'] != null) { + //if a connection was explicitly passed on options, then we have only one... + numberOfConnections = 1; + } else { + // Get the amount of connections in the pool to ensure we have authenticated all comments + numberOfConnections = db.serverConfig.allRawConnections().length; + options['onAll'] = true; + } + + // Grab all the connections + var connections = options['connection'] != null ? [options['connection']] : db.serverConfig.allRawConnections(); + var gssapiServiceName = options['gssapiServiceName'] || 'mongodb'; + + // Authenticate all connections + for(var i = 0; i < numberOfConnections; i++) { + + // Start Auth process for a connection + GSSAPIInitialize(db, username, password, authdb, gssapiServiceName, connections[i], function(err, result) { + // Adjust number of connections left to connect + numberOfConnections = numberOfConnections - 1; + + // Ensure we save any error + if(err) { + errorObject = err; + } else { + credentialsValid = true; + numberOfValidConnections = numberOfValidConnections + 1; + } + + // Work around the case where the number of connections are 0 + if(numberOfConnections <= 0 && typeof callback == 'function') { + var internalCallback = callback; + callback = null; + + // We are done + if(errorObject == null && numberOfConnections == 0) { + // We authenticated correctly save the credentials + db.serverConfig.auth.add('GSSAPI', db.databaseName, username, password, authdb, gssapiServiceName); + // Return valid callback + return internalCallback(null, true); + } else if(numberOfValidConnections > 0 && numberOfValidConnections != numberOfConnections + && credentialsValid) { + // We authenticated correctly save the credentials + db.serverConfig.auth.add('GSSAPI', db.databaseName, username, password, authdb, gssapiServiceName); + // Return valid callback + return internalCallback(null, true); + } else { + return internalCallback(errorObject, false); + } + } + }); + } +} + +// +// Initialize step +var GSSAPIInitialize = function(db, username, password, authdb, gssapiServiceName, connection, callback) { + // Create authenticator + var mongo_auth_process = new MongoAuthProcess(connection.socketOptions.host, connection.socketOptions.port, gssapiServiceName); + + // Perform initialization + mongo_auth_process.init(username, password, function(err, context) { + if(err) return callback(err, false); + + // Perform the first step + mongo_auth_process.transition('', function(err, payload) { + if(err) return callback(err, false); + + // Call the next db step + MongoDBGSSAPIFirstStep(mongo_auth_process, payload, db, username, password, authdb, connection, callback); + }); + }); +} + +// +// Perform first step against mongodb +var MongoDBGSSAPIFirstStep = function(mongo_auth_process, payload, db, username, password, authdb, connection, callback) { + // Build the sasl start command + var command = { + saslStart: 1 + , mechanism: 'GSSAPI' + , payload: payload + , autoAuthorize: 1 + }; + + // Execute first sasl step + db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) { + if(err) return callback(err, false); + // Get the payload + doc = doc.documents[0]; + var db_payload = doc.payload; + + mongo_auth_process.transition(doc.payload, function(err, payload) { + if(err) return callback(err, false); + + // MongoDB API Second Step + MongoDBGSSAPISecondStep(mongo_auth_process, payload, doc, db, username, password, authdb, connection, callback); + }); + }); +} + +// +// Perform first step against mongodb +var MongoDBGSSAPISecondStep = function(mongo_auth_process, payload, doc, db, username, password, authdb, connection, callback) { + // Build Authentication command to send to MongoDB + var command = { + saslContinue: 1 + , conversationId: doc.conversationId + , payload: payload + }; + + // Execute the command + db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) { + if(err) return callback(err, false); + + // Get the result document + doc = doc.documents[0]; + + // Call next transition for kerberos + mongo_auth_process.transition(doc.payload, function(err, payload) { + if(err) return callback(err, false); + + // Call the last and third step + MongoDBGSSAPIThirdStep(mongo_auth_process, payload, doc, db, username, password, authdb, connection, callback); + }); + }); +} + +var MongoDBGSSAPIThirdStep = function(mongo_auth_process, payload, doc, db, username, password, authdb, connection, callback) { + // Build final command + var command = { + saslContinue: 1 + , conversationId: doc.conversationId + , payload: payload + }; + + // Let's finish the auth process against mongodb + db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) { + if(err) return callback(err, false); + + mongo_auth_process.transition(null, function(err, payload) { + if(err) return callback(err, false); + callback(null, true); + }); + }); +} + +exports.authenticate = authenticate; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/auth/mongodb_plain.js b/node_modules/mongodb/lib/mongodb/auth/mongodb_plain.js new file mode 100644 index 0000000..d2555cd --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/auth/mongodb_plain.js @@ -0,0 +1,79 @@ +var DbCommand = require('../commands/db_command').DbCommand + , utils = require('../utils') + , crypto = require('crypto') + , Binary = require('bson').Binary + , format = require('util').format; + +var authenticate = function(db, username, password, options, callback) { + var numberOfConnections = 0; + var errorObject = null; + var numberOfValidConnections = 0; + var credentialsValid = false; + options = options || {}; + + if(options['connection'] != null) { + //if a connection was explicitly passed on options, then we have only one... + numberOfConnections = 1; + } else { + // Get the amount of connections in the pool to ensure we have authenticated all comments + numberOfConnections = db.serverConfig.allRawConnections().length; + options['onAll'] = true; + } + + // Create payload + var payload = new Binary(format("\x00%s\x00%s", username, password)); + + // Let's start the sasl process + var command = { + saslStart: 1 + , mechanism: 'PLAIN' + , payload: payload + , autoAuthorize: 1 + }; + + // Grab all the connections + var connections = options['connection'] != null ? [options['connection']] : db.serverConfig.allRawConnections(); + + // Authenticate all connections + for(var i = 0; i < numberOfConnections; i++) { + var connection = connections[i]; + // Execute first sasl step + db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, result) { + // Count down + numberOfConnections = numberOfConnections - 1; + + // Ensure we save any error + if(err) { + errorObject = err; + } else if(result.documents[0].err != null || result.documents[0].errmsg != null){ + errorObject = utils.toError(result.documents[0]); + } else { + credentialsValid = true; + numberOfValidConnections = numberOfValidConnections + 1; + } + + // Work around the case where the number of connections are 0 + if(numberOfConnections <= 0 && typeof callback == 'function') { + var internalCallback = callback; + callback = null; + + if(errorObject == null && credentialsValid) { + // We authenticated correctly save the credentials + db.serverConfig.auth.add('PLAIN', db.databaseName, username, password); + // Return callback + internalCallback(errorObject, true); + } else if(numberOfValidConnections > 0 && numberOfValidConnections != numberOfConnections + && credentialsValid) { + // We authenticated correctly save the credentials + db.serverConfig.auth.add('PLAIN', db.databaseName, username, password); + // Return callback + internalCallback(errorObject, true); + } else { + internalCallback(errorObject, false); + } + } + }); + } +} + +exports.authenticate = authenticate; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/auth/mongodb_scram.js b/node_modules/mongodb/lib/mongodb/auth/mongodb_scram.js new file mode 100644 index 0000000..9c08686 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/auth/mongodb_scram.js @@ -0,0 +1,250 @@ +var DbCommand = require('../commands/db_command').DbCommand + , utils = require('../utils') + , crypto = require('crypto') + , Binary = require('bson').Binary + , f = require('util').format; + +var authenticate = function(db, username, password, authdb, options, callback) { + var numberOfConnections = 0; + var errorObject = null; + var numberOfValidConnections = 0; + var credentialsValid = false; + options = options || {}; + + // Grab all the connections + var connections = options['connection'] != null ? [options['connection']] : db.serverConfig.allRawConnections().slice(0); + if(connections.length > 1) { + options['onAll'] = true; + } + + // Total connections + var count = connections.length; + if(count == 0) return callback(null, null); + + // Valid connections + var numberOfValidConnections = 0; + var credentialsValid = false; + var errorObject = null; + + // For each connection we need to authenticate + while(connections.length > 0) { + // Execute MongoCR + var executeScram = function(connection) { + // Clean up the user + username = username.replace('=', "=3D").replace(',', '=2C'); + + // Create a random nonce + var nonce = crypto.randomBytes(24).toString('base64'); + // var nonce = 'MsQUY9iw0T9fx2MUEz6LZPwGuhVvWAhc' + var firstBare = f("n=%s,r=%s", username, nonce); + + // Build command structure + var cmd = { + saslStart: 1 + , mechanism: 'SCRAM-SHA-1' + , payload: new Binary(f("n,,%s", firstBare)) + , autoAuthorize: 1 + } + + // Handle the error + var handleError = function(err, r) { + if(err) { + errorObject = err; return false; + } else if(r['$err']) { + errorObject = r; return false; + } else if(r['errmsg']) { + errorObject = r; return false; + } else { + credentialsValid = true; + numberOfValidConnections = numberOfValidConnections + 1; + } + + return true + } + + // Finish up + var finish = function(_count, _numberOfValidConnections) { + if(_count == 0 && _numberOfValidConnections > 0) { + db.serverConfig.auth.add('SCRAM-SHA-1', db.databaseName, username, password, authdb); + // Return correct authentication + return callback(null, true); + } else if(_count == 0) { + if(errorObject == null) errorObject = utils.toError(f("failed to authenticate using scram")); + return callback(errorObject, false); + } + } + + var handleEnd = function(_err, _r) { + // Handle any error + handleError(_err, _r) + // Adjust the number of connections + count = count - 1; + // Execute the finish + finish(count, numberOfValidConnections); + } + + // Execute start sasl command + db.db(authdb).command(cmd, { connection: connection }, function(err, r) { + // Do we have an error, handle it + if(handleError(err, r) == false) { + count = count - 1; + + if(count == 0 && numberOfValidConnections > 0) { + // Store the auth details + addAuthSession(new AuthSession(db, username, password)); + // Return correct authentication + return callback(null, true); + } else if(count == 0) { + if(errorObject == null) errorObject = utils.toError(f("failed to authenticate using scram")); + return callback(errorObject, false); + } + + return; + } + + // Get the dictionary + var dict = parsePayload(r.payload.value()) + + // Unpack dictionary + var iterations = parseInt(dict.i, 10); + var salt = dict.s; + var rnonce = dict.r; + + // Set up start of proof + var withoutProof = f("c=biws,r=%s", rnonce); + var passwordDig = passwordDigest(username, password); + var saltedPassword = hi(passwordDig + , new Buffer(salt, 'base64') + , iterations); + + // Create the client key + var hmac = crypto.createHmac('sha1', saltedPassword); + hmac.update(new Buffer("Client Key")); + var clientKey = hmac.digest(); + + // Create the stored key + var hash = crypto.createHash('sha1'); + hash.update(clientKey); + var storedKey = hash.digest(); + + // Create the authentication message + var authMsg = [firstBare, r.payload.value().toString('base64'), withoutProof].join(','); + + // Create client signature + var hmac = crypto.createHmac('sha1', storedKey); + hmac.update(new Buffer(authMsg)); + var clientSig = hmac.digest(); + + // Create client proof + var clientProof = f("p=%s", new Buffer(xor(clientKey, clientSig)).toString('base64')); + + // Create client final + var clientFinal = [withoutProof, clientProof].join(','); + + // Generate server key + var hmac = crypto.createHmac('sha1', saltedPassword); + hmac.update(new Buffer('Server Key')) + var serverKey = hmac.digest(); + + // Generate server signature + var hmac = crypto.createHmac('sha1', serverKey); + hmac.update(new Buffer(authMsg)) + var serverSig = hmac.digest(); + + // + // Create continue message + var cmd = { + saslContinue: 1 + , conversationId: r.conversationId + , payload: new Binary(new Buffer(clientFinal)) + } + + // + // Execute sasl continue + db.db(authdb).command(cmd, { connection: connection }, function(err, r) { + if(r.done == false) { + var cmd = { + saslContinue: 1 + , conversationId: r.conversationId + , payload: new Buffer(0) + } + + db.db(authdb).command(cmd, { connection: connection }, function(err, r) { + handleEnd(err, r); + }); + } else { + handleEnd(err, r); + } + }); + }); + } + + // Get the connection + executeScram(connections.shift()); + } +} + +var parsePayload = function(payload) { + var dict = {}; + var parts = payload.split(','); + + for(var i = 0; i < parts.length; i++) { + var valueParts = parts[i].split('='); + dict[valueParts[0]] = valueParts[1]; + } + + return dict; +} + +var passwordDigest = function(username, password) { + if(typeof username != 'string') throw utils.toError("username must be a string"); + if(typeof password != 'string') throw utils.toError("password must be a string"); + if(password.length == 0) throw utils.toError("password cannot be empty"); + // Use node md5 generator + var md5 = crypto.createHash('md5'); + // Generate keys used for authentication + md5.update(username + ":mongo:" + password); + return md5.digest('hex'); +} + +// XOR two buffers +var xor = function(a, b) { + if (!Buffer.isBuffer(a)) a = new Buffer(a) + if (!Buffer.isBuffer(b)) b = new Buffer(b) + var res = [] + if (a.length > b.length) { + for (var i = 0; i < b.length; i++) { + res.push(a[i] ^ b[i]) + } + } else { + for (var i = 0; i < a.length; i++) { + res.push(a[i] ^ b[i]) + } + } + return new Buffer(res); +} + +// Create a final digest +var hi = function(data, salt, iterations) { + // Create digest + var digest = function(msg) { + var hmac = crypto.createHmac('sha1', data); + hmac.update(msg); + var result = hmac.digest() + return result; + } + + // Create variables + salt = Buffer.concat([salt, new Buffer('\x00\x00\x00\x01')]) + var ui = digest(salt); + var u1 = ui; + + for(var i = 0; i < iterations - 1; i++) { + u1 = digest(u1); + ui = xor(ui, u1); + } + + return ui; +} + +exports.authenticate = authenticate; diff --git a/node_modules/mongodb/lib/mongodb/auth/mongodb_sspi.js b/node_modules/mongodb/lib/mongodb/auth/mongodb_sspi.js new file mode 100644 index 0000000..13a87ea --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/auth/mongodb_sspi.js @@ -0,0 +1,156 @@ +var DbCommand = require('../commands/db_command').DbCommand + , utils = require('../utils') + , format = require('util').format; + +// Kerberos class +var Kerberos = null; +var MongoAuthProcess = null; +// Try to grab the Kerberos class +try { + Kerberos = require('kerberos').Kerberos + // Authentication process for Mongo + MongoAuthProcess = require('kerberos').processes.MongoAuthProcess +} catch(err) {} + +var authenticate = function(db, username, password, authdb, options, callback) { + var numberOfConnections = 0; + var errorObject = null; + var numberOfValidConnections = 0; + var credentialsValid = false; + options = options || {}; + + // We don't have the Kerberos library + if(Kerberos == null) return callback(new Error("Kerberos library is not installed")); + + if(options['connection'] != null) { + //if a connection was explicitly passed on options, then we have only one... + numberOfConnections = 1; + } else { + // Get the amount of connections in the pool to ensure we have authenticated all comments + numberOfConnections = db.serverConfig.allRawConnections().length; + options['onAll'] = true; + } + + // Set the sspi server name + var gssapiServiceName = options['gssapiServiceName'] || 'mongodb'; + + // Grab all the connections + var connections = db.serverConfig.allRawConnections(); + + // Authenticate all connections + for(var i = 0; i < numberOfConnections; i++) { + // Start Auth process for a connection + SSIPAuthenticate(db, username, password, authdb, gssapiServiceName, connections[i], function(err, result) { + // Adjust number of connections left to connect + numberOfConnections = numberOfConnections - 1; + + // Ensure we save any error + if(err) { + errorObject = err; + } else { + credentialsValid = true; + numberOfValidConnections = numberOfValidConnections + 1; + } + + // Work around the case where the number of connections are 0 + if(numberOfConnections <= 0 && typeof callback == 'function') { + var internalCallback = callback; + callback = null; + + if(errorObject == null) { + // We authenticated correctly save the credentials + db.serverConfig.auth.add('GSSAPI', db.databaseName, username, password, authdb, gssapiServiceName); + // Return valid callback + return internalCallback(null, true); + } else if(numberOfValidConnections > 0 && numberOfValidConnections != numberOfConnections + && credentialsValid) { + // We authenticated correctly save the credentials + db.serverConfig.auth.add('GSSAPI', db.databaseName, username, password, authdb, gssapiServiceName); + // Return valid callback + return internalCallback(null, true); + } else { + return internalCallback(errorObject, false); + } + } + }); + } +} + +var SSIPAuthenticate = function(db, username, password, authdb, service_name, connection, callback) { + // -------------------------------------------------------------- + // Async Version + // -------------------------------------------------------------- + var command = { + saslStart: 1 + , mechanism: 'GSSAPI' + , payload: '' + , autoAuthorize: 1 + }; + + // Create authenticator + var mongo_auth_process = new MongoAuthProcess(connection.socketOptions.host, connection.socketOptions.port, service_name); + + // Execute first sasl step + db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) { + if(err) return callback(err); + doc = doc.documents[0]; + + mongo_auth_process.init(username, password, function(err) { + if(err) return callback(err); + + mongo_auth_process.transition(doc.payload, function(err, payload) { + if(err) return callback(err); + + // Perform the next step against mongod + var command = { + saslContinue: 1 + , conversationId: doc.conversationId + , payload: payload + }; + + // Execute the command + db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) { + if(err) return callback(err); + doc = doc.documents[0]; + + mongo_auth_process.transition(doc.payload, function(err, payload) { + if(err) return callback(err); + + // Perform the next step against mongod + var command = { + saslContinue: 1 + , conversationId: doc.conversationId + , payload: payload + }; + + // Execute the command + db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) { + if(err) return callback(err); + doc = doc.documents[0]; + + mongo_auth_process.transition(doc.payload, function(err, payload) { + // Perform the next step against mongod + var command = { + saslContinue: 1 + , conversationId: doc.conversationId + , payload: payload + }; + + // Execute the command + db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) { + if(err) return callback(err); + doc = doc.documents[0]; + + if(doc.done) return callback(null, true); + callback(new Error("Authentication failed"), false); + }); + }); + }); + }); + }); + }); + }); + }); +} + +exports.authenticate = authenticate; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/auth/mongodb_x509.js b/node_modules/mongodb/lib/mongodb/auth/mongodb_x509.js new file mode 100644 index 0000000..8b8b7c2 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/auth/mongodb_x509.js @@ -0,0 +1,68 @@ +var DbCommand = require('../commands/db_command').DbCommand + , utils = require('../utils') + , Binary = require('bson').Binary + , format = require('util').format; + +var authenticate = function(db, username, password, options, callback, t) { + var numberOfConnections = 0; + var errorObject = null; + var numberOfValidConnections = 0; + var credentialsValid = false; + options = options || {}; + + if(options['connection'] != null) { + //if a connection was explicitly passed on options, then we have only one... + numberOfConnections = 1; + } else { + // Get the amount of connections in the pool to ensure we have authenticated all comments + numberOfConnections = db.serverConfig.allRawConnections().length; + options['onAll'] = true; + } + + // Let's start the sasl process + var command = { + authenticate: 1 + , mechanism: 'MONGODB-X509' + , user: username + }; + + // Grab all the connections + var connections = options['connection'] != null ? [options['connection']] : db.serverConfig.allRawConnections(); + + // Authenticate all connections + for(var i = 0; i < numberOfConnections; i++) { + var connection = connections[i]; + // Execute first sasl step + db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, result) { + // Count down + numberOfConnections = numberOfConnections - 1; + + // Ensure we save any error + if(err) { + errorObject = err; + } else if(result.documents[0].err != null || result.documents[0].errmsg != null){ + errorObject = utils.toError(result.documents[0]); + } else { + credentialsValid = true; + numberOfValidConnections = numberOfValidConnections + 1; + } + + // Work around the case where the number of connections are 0 + if(numberOfConnections <= 0 && typeof callback == 'function') { + var internalCallback = callback; + callback = null; + + if(errorObject == null && credentialsValid) { + // We authenticated correctly save the credentials + db.serverConfig.auth.add('MONGODB-X509', db.databaseName, username, password); + // Return callback + internalCallback(errorObject, true); + } else { + internalCallback(errorObject, false); + } + } + }); + } +} + +exports.authenticate = authenticate; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/collection.js b/node_modules/mongodb/lib/mongodb/collection.js new file mode 100644 index 0000000..b8e8a70 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/collection.js @@ -0,0 +1,676 @@ +/** + * Module dependencies. + * @ignore + */ +var InsertCommand = require('./commands/insert_command').InsertCommand + , QueryCommand = require('./commands/query_command').QueryCommand + , DeleteCommand = require('./commands/delete_command').DeleteCommand + , UpdateCommand = require('./commands/update_command').UpdateCommand + , DbCommand = require('./commands/db_command').DbCommand + , ObjectID = require('bson').ObjectID + , Code = require('bson').Code + , Cursor = require('./cursor').Cursor + , utils = require('./utils') + , shared = require('./collection/shared') + , core = require('./collection/core') + , query = require('./collection/query') + , index = require('./collection/index') + , geo = require('./collection/geo') + , commands = require('./collection/commands') + , aggregation = require('./collection/aggregation') + , unordered = require('./collection/batch/unordered') + , ordered = require('./collection/batch/ordered'); + +/** + * Create a new Collection instance (INTERNAL TYPE, do not instantiate directly) + * + * Options + * - **readPreference** {String}, the prefered read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). + * - **slaveOk** {Boolean, default:false}, Allow reads from secondaries. + * - **serializeFunctions** {Boolean, default:false}, serialize functions on the document. + * - **raw** {Boolean, default:false}, perform all operations using raw bson objects. + * - **pkFactory** {Object}, object overriding the basic ObjectID primary key generation. + * + * @class Represents a Collection + * @param {Object} db db instance. + * @param {String} collectionName collection name. + * @param {Object} [pkFactory] alternative primary key factory. + * @param {Object} [options] additional options for the collection. + * @return {Object} a collection instance. + */ +function Collection (db, collectionName, pkFactory, options) { + if(!(this instanceof Collection)) return new Collection(db, collectionName, pkFactory, options); + + shared.checkCollectionName(collectionName); + + this.db = db; + this.collectionName = collectionName; + this.internalHint = null; + this.opts = options != null && ('object' === typeof options) ? options : {}; + this.slaveOk = options == null || options.slaveOk == null ? db.slaveOk : options.slaveOk; + this.serializeFunctions = options == null || options.serializeFunctions == null ? db.serializeFunctions : options.serializeFunctions; + this.raw = options == null || options.raw == null ? db.raw : options.raw; + + // Assign the right collection level readPreference + if(options && options.readPreference) { + this.readPreference = options.readPreference; + } else if(this.db.options.readPreference) { + this.readPreference = this.db.options.readPreference; + } else if(this.db.serverConfig.options.readPreference) { + this.readPreference = this.db.serverConfig.options.readPreference; + } + + // Set custom primary key factory if provided + this.pkFactory = pkFactory == null + ? ObjectID + : pkFactory; + + // Server Capabilities + this.serverCapabilities = this.db.serverConfig._serverCapabilities; +} + +/** + * Inserts a single document or a an array of documents into MongoDB. + * + * Options + * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal + * - **j**, (Boolean, default:false) write waits for journal sync before returning + * - **continueOnError/keepGoing** {Boolean, default:false}, keep inserting documents even if one document has an error, *mongodb 1.9.1 >*. + * - **serializeFunctions** {Boolean, default:false}, serialize functions on the document. + * - **forceServerObjectId** {Boolean, default:false}, let server assign ObjectId instead of the driver + * - **checkKeys** {Boolean, default:true}, allows for disabling of document key checking (WARNING OPENS YOU UP TO INJECTION ATTACKS) + * - **fullResult** {Boolean, default:false}, returns the full result document (document returned will differ by server version) + * + * @param {Array|Object} docs + * @param {Object} [options] optional options for insert command + * @param {Function} [callback] optional callback for the function, must be provided when using a writeconcern + * @return {Collection} + * @api public + */ +Collection.prototype.insert = function() { return core.insert; }(); + +/** + * Removes documents specified by `selector` from the db. + * + * Options + * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal + * - **j**, (Boolean, default:false) write waits for journal sync before returning + * - **single** {Boolean, default:false}, removes the first document found. + * - **fullResult** {Boolean, default:false}, returns the full result document (document returned will differ by server version) + * + * @param {Object} [selector] optional select, no selector is equivalent to removing all documents. + * @param {Object} [options] additional options during remove. + * @param {Function} [callback] must be provided if you performing a remove with a writeconcern + * @return {null} + * @api public + */ +Collection.prototype.remove = function() { return core.remove; }(); + +/** + * Renames the collection. + * + * Options + * - **dropTarget** {Boolean, default:false}, drop the target name collection if it previously exists. + * + * @param {String} newName the new name of the collection. + * @param {Object} [options] returns option results. + * @param {Function} callback the callback accepting the result + * @return {null} + * @api public + */ +Collection.prototype.rename = function() { return commands.rename; }(); + +/** + * Save a document. Simple full document replacement function. Not recommended for efficiency, use atomic + * operators and update instead for more efficient operations. + * + * Options + * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal + * - **j**, (Boolean, default:false) write waits for journal sync before returning + * + * @param {Object} [doc] the document to save + * @param {Object} [options] additional options during remove. + * @param {Function} [callback] must be provided if you performing an update with a writeconcern + * @return {null} + * @api public + */ +Collection.prototype.save = function() { return core.save; }(); + +/** + * Updates documents. + * + * Options + * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal + * - **j**, (Boolean, default:false) write waits for journal sync before returning + * - **upsert** {Boolean, default:false}, perform an upsert operation. + * - **multi** {Boolean, default:false}, update all documents matching the selector. + * - **serializeFunctions** {Boolean, default:false}, serialize functions on the document. + * - **checkKeys** {Boolean, default:true}, allows for disabling of document key checking (WARNING OPENS YOU UP TO INJECTION ATTACKS) + * - **fullResult** {Boolean, default:false}, returns the full result document (document returned will differ by server version) + * + * @param {Object} selector the query to select the document/documents to be updated + * @param {Object} document the fields/vals to be updated, or in the case of an upsert operation, inserted. + * @param {Object} [options] additional options during update. + * @param {Function} [callback] must be provided if you performing an update with a writeconcern + * @return {null} + * @api public + */ +Collection.prototype.update = function() { return core.update; }(); + +/** + * The distinct command returns returns a list of distinct values for the given key across a collection. + * + * Options + * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). + * + * @param {String} key key to run distinct against. + * @param {Object} [query] option query to narrow the returned objects. + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from distinct or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.distinct = function() { return commands.distinct; }(); + +/** + * Count number of matching documents in the db to a query. + * + * Options + * - **skip** {Number}, The number of documents to skip for the count. + * - **limit** {Number}, The limit of documents to count. + * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). + * + * @param {Object} [query] query to filter by before performing count. + * @param {Object} [options] additional options during count. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the count method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.count = function() { return commands.count; }(); + +/** + * Drop the collection + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the drop method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.drop = function drop(callback) { + this.db.dropCollection(this.collectionName, callback); +}; + +/** + * Find and update a document. + * + * Options + * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal + * - **j**, (Boolean, default:false) write waits for journal sync before returning + * - **remove** {Boolean, default:false}, set to true to remove the object before returning. + * - **upsert** {Boolean, default:false}, perform an upsert operation. + * - **new** {Boolean, default:false}, set to true if you want to return the modified object rather than the original. Ignored for remove. + * + * @param {Object} query query object to locate the object to modify + * @param {Array} sort - if multiple docs match, choose the first one in the specified sort order as the object to manipulate + * @param {Object} doc - the fields/vals to be updated + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the findAndModify method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.findAndModify = function() { return core.findAndModify; }(); + +/** + * Find and remove a document + * + * Options + * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal + * - **j**, (Boolean, default:false) write waits for journal sync before returning + * + * @param {Object} query query object to locate the object to modify + * @param {Array} sort - if multiple docs match, choose the first one in the specified sort order as the object to manipulate + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the findAndRemove method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.findAndRemove = function() { return core.findAndRemove; }(); + +/** + * Creates a cursor for a query that can be used to iterate over results from MongoDB + * + * Various argument possibilities + * - callback? + * - selector, callback?, + * - selector, fields, callback? + * - selector, options, callback? + * - selector, fields, options, callback? + * - selector, fields, skip, limit, callback? + * - selector, fields, skip, limit, timeout, callback? + * + * Options + * - **limit** {Number, default:0}, sets the limit of documents returned in the query. + * - **sort** {Array | Object}, set to sort the documents coming back from the query. Array of indexes, [['a', 1]] etc. + * - **fields** {Object}, the fields to return in the query. Object of fields to include or exclude (not both), {'a':1} + * - **skip** {Number, default:0}, set to skip N documents ahead in your query (useful for pagination). + * - **hint** {Object}, tell the query to use specific indexes in the query. Object of indexes to use, {'_id':1} + * - **explain** {Boolean, default:false}, explain the query instead of returning the data. + * - **snapshot** {Boolean, default:false}, snapshot query. + * - **timeout** {Boolean, default:false}, specify if the cursor can timeout. + * - **tailable** {Boolean, default:false}, specify if the cursor is tailable. + * - **tailableRetryInterval** {Number, default:100}, specify the miliseconds between getMores on tailable cursor. + * - **numberOfRetries** {Number, default:5}, specify the number of times to retry the tailable cursor. + * - **awaitdata** {Boolean, default:false} allow the cursor to wait for data, only applicable for tailable cursor. + * - **oplogReplay** {Boolean, default:false} sets an internal flag, only applicable for tailable cursor. + * - **exhaust** {Boolean, default:false} have the server send all the documents at once as getMore packets, not recommended. + * - **batchSize** {Number, default:0}, set the batchSize for the getMoreCommand when iterating over the query results. + * - **returnKey** {Boolean, default:false}, only return the index key. + * - **maxScan** {Number}, Limit the number of items to scan. + * - **min** {Number}, Set index bounds. + * - **max** {Number}, Set index bounds. + * - **showDiskLoc** {Boolean, default:false}, Show disk location of results. + * - **comment** {String}, You can put a $comment field on a query to make looking in the profiler logs simpler. + * - **raw** {Boolean, default:false}, Return all BSON documents as Raw Buffer documents. + * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference ((ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). + * - **numberOfRetries** {Number, default:5}, if using awaidata specifies the number of times to retry on timeout. + * - **partial** {Boolean, default:false}, specify if the cursor should return partial results when querying against a sharded system + * - **maxTimeMS** {Number}, number of miliseconds to wait before aborting the query. + * + * @param {Object|ObjectID} query query object to locate the object to modify + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the find method or null if an error occured. + * @return {Cursor} returns a cursor to the query + * @api public + */ +Collection.prototype.find = function() { return query.find; }(); + +/** + * Finds a single document based on the query + * + * Various argument possibilities + * - callback? + * - selector, callback?, + * - selector, fields, callback? + * - selector, options, callback? + * - selector, fields, options, callback? + * - selector, fields, skip, limit, callback? + * - selector, fields, skip, limit, timeout, callback? + * + * Options + * - **limit** {Number, default:0}, sets the limit of documents returned in the query. + * - **sort** {Array | Object}, set to sort the documents coming back from the query. Array of indexes, [['a', 1]] etc. + * - **fields** {Object}, the fields to return in the query. Object of fields to include or exclude (not both), {'a':1} + * - **skip** {Number, default:0}, set to skip N documents ahead in your query (useful for pagination). + * - **hint** {Object}, tell the query to use specific indexes in the query. Object of indexes to use, {'_id':1} + * - **explain** {Boolean, default:false}, explain the query instead of returning the data. + * - **snapshot** {Boolean, default:false}, snapshot query. + * - **timeout** {Boolean, default:false}, specify if the cursor can timeout. + * - **tailable** {Boolean, default:false}, specify if the cursor is tailable. + * - **batchSize** {Number, default:0}, set the batchSize for the getMoreCommand when iterating over the query results. + * - **returnKey** {Boolean, default:false}, only return the index key. + * - **maxScan** {Number}, Limit the number of items to scan. + * - **min** {Number}, Set index bounds. + * - **max** {Number}, Set index bounds. + * - **showDiskLoc** {Boolean, default:false}, Show disk location of results. + * - **comment** {String}, You can put a $comment field on a query to make looking in the profiler logs simpler. + * - **raw** {Boolean, default:false}, Return all BSON documents as Raw Buffer documents. + * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). + * - **partial** {Boolean, default:false}, specify if the cursor should return partial results when querying against a sharded system + * - **maxTimeMS** {Number}, number of miliseconds to wait before aborting the query. + * + * @param {Object|ObjectID} query query object to locate the object to modify + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the findOne method or null if an error occured. + * @return {Cursor} returns a cursor to the query + * @api public + */ +Collection.prototype.findOne = function() { return query.findOne; }(); + +/** + * Creates an index on the collection. + * + * Options + * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal + * - **j**, (Boolean, default:false) write waits for journal sync before returning + * - **unique** {Boolean, default:false}, creates an unique index. + * - **sparse** {Boolean, default:false}, creates a sparse index. + * - **background** {Boolean, default:false}, creates the index in the background, yielding whenever possible. + * - **min** {Number}, for geospatial indexes set the lower bound for the co-ordinates. + * - **max** {Number}, for geospatial indexes set the high bound for the co-ordinates. + * - **v** {Number}, specify the format version of the indexes. + * - **expireAfterSeconds** {Number}, allows you to expire data on indexes applied to a data (MongoDB 2.2 or higher) + * - **name** {String}, override the autogenerated index name (useful if the resulting name is larger than 128 bytes) + * + * @param {Object} fieldOrSpec fieldOrSpec that defines the index. + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the createIndex method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.createIndex = function() { return index.createIndex; }(); + +/** + * Ensures that an index exists, if it does not it creates it + * + * Options + * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal + * - **j**, (Boolean, default:false) write waits for journal sync before returning + * - **unique** {Boolean, default:false}, creates an unique index. + * - **sparse** {Boolean, default:false}, creates a sparse index. + * - **background** {Boolean, default:false}, creates the index in the background, yielding whenever possible. + * - **min** {Number}, for geospatial indexes set the lower bound for the co-ordinates. + * - **max** {Number}, for geospatial indexes set the high bound for the co-ordinates. + * - **v** {Number}, specify the format version of the indexes. + * - **expireAfterSeconds** {Number}, allows you to expire data on indexes applied to a data (MongoDB 2.2 or higher) + * - **name** {String}, override the autogenerated index name (useful if the resulting name is larger than 128 bytes) + * + * @param {Object} fieldOrSpec fieldOrSpec that defines the index. + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the ensureIndex method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.ensureIndex = function() { return index.ensureIndex; }(); + +/** + * Retrieves this collections index info. + * + * Options + * - **full** {Boolean, default:false}, returns the full raw index information. + * + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the indexInformation method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.indexInformation = function() { return index.indexInformation; }(); + +/** + * Drops an index from this collection. + * + * @param {String} name + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the dropIndex method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.dropIndex = function dropIndex (name, options, callback) { + if(typeof options == 'function') { + callback = options; + options = {}; + } + // Execute dropIndex command + this.db.dropIndex(this.collectionName, name, options, callback); +}; + +/** + * Drops all indexes from this collection. + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the dropAllIndexes method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.dropAllIndexes = function() { return index.dropAllIndexes; }(); + +/** + * Drops all indexes from this collection. + * + * @deprecated + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the dropIndexes method or null if an error occured. + * @return {null} + * @api private + */ +Collection.prototype.dropIndexes = function() { return Collection.prototype.dropAllIndexes; }(); + +/** + * Reindex all indexes on the collection + * Warning: reIndex is a blocking operation (indexes are rebuilt in the foreground) and will be slow for large collections. + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the reIndex method or null if an error occured. + * @return {null} + * @api public +**/ +Collection.prototype.reIndex = function(options, callback) { + if(typeof options == 'function') { + callback = options; + options = {}; + } + // Execute reIndex + this.db.reIndex(this.collectionName, options, callback); +} + +/** + * Run Map Reduce across a collection. Be aware that the inline option for out will return an array of results not a collection. + * + * Options + * - **out** {Object}, sets the output target for the map reduce job. *{inline:1} | {replace:'collectionName'} | {merge:'collectionName'} | {reduce:'collectionName'}* + * - **query** {Object}, query filter object. + * - **sort** {Object}, sorts the input objects using this key. Useful for optimization, like sorting by the emit key for fewer reduces. + * - **limit** {Number}, number of objects to return from collection. + * - **keeptemp** {Boolean, default:false}, keep temporary data. + * - **finalize** {Function | String}, finalize function. + * - **scope** {Object}, can pass in variables that can be access from map/reduce/finalize. + * - **jsMode** {Boolean, default:false}, it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X. + * - **verbose** {Boolean, default:false}, provide statistics on job execution time. + * - **readPreference** {String, only for inline results}, the preferred read preference, require('mongodb').ReadPreference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). + * + * @param {Function|String} map the mapping function. + * @param {Function|String} reduce the reduce function. + * @param {Objects} [options] options for the map reduce job. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the mapReduce method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.mapReduce = function() { return aggregation.mapReduce; }(); + +/** + * Run a group command across a collection + * + * Options + * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). + * + * @param {Object|Array|Function|Code} keys an object, array or function expressing the keys to group by. + * @param {Object} condition an optional condition that must be true for a row to be considered. + * @param {Object} initial initial value of the aggregation counter object. + * @param {Function|Code} reduce the reduce function aggregates (reduces) the objects iterated + * @param {Function|Code} finalize an optional function to be run on each item in the result set just before the item is returned. + * @param {Boolean} command specify if you wish to run using the internal group command or using eval, default is true. + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the group method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.group = function() { return aggregation.group; }(); + +/** + * Returns the options of the collection. + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the options method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.options = function() { return commands.options; }(); + +/** + * Returns if the collection is a capped collection + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the isCapped method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.isCapped = function() { return commands.isCapped; }(); + +/** + * Checks if one or more indexes exist on the collection + * + * @param {String|Array} indexNames check if one or more indexes exist on the collection. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the indexExists method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.indexExists = function() { return index.indexExists; }(); + +/** + * Execute the geoNear command to search for items in the collection + * + * Options + * - **num** {Number}, max number of results to return. + * - **minDistance** {Number}, include results starting at minDistance from a point (2.6 or higher) + * - **maxDistance** {Number}, include results up to maxDistance from the point. + * - **distanceMultiplier** {Number}, include a value to multiply the distances with allowing for range conversions. + * - **query** {Object}, filter the results by a query. + * - **spherical** {Boolean, default:false}, perform query using a spherical model. + * - **uniqueDocs** {Boolean, default:false}, the closest location in a document to the center of the search region will always be returned MongoDB > 2.X. + * - **includeLocs** {Boolean, default:false}, include the location data fields in the top level of the results MongoDB > 2.X. + * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference ((ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). + * + * @param {Number} x point to search on the x axis, ensure the indexes are ordered in the same order. + * @param {Number} y point to search on the y axis, ensure the indexes are ordered in the same order. + * @param {Objects} [options] options for the map reduce job. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the geoNear method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.geoNear = function() { return geo.geoNear; }(); + +/** + * Execute a geo search using a geo haystack index on a collection. + * + * Options + * - **maxDistance** {Number}, include results up to maxDistance from the point. + * - **search** {Object}, filter the results by a query. + * - **limit** {Number}, max number of results to return. + * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference ((ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). + * + * @param {Number} x point to search on the x axis, ensure the indexes are ordered in the same order. + * @param {Number} y point to search on the y axis, ensure the indexes are ordered in the same order. + * @param {Objects} [options] options for the map reduce job. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the geoHaystackSearch method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.geoHaystackSearch = function() { return geo.geoHaystackSearch; }(); + +/** + * Retrieve all the indexes on the collection. + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the indexes method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.indexes = function indexes(callback) { + this.db.indexInformation(this.collectionName, {full:true}, callback); +} + +/** + * Execute an aggregation framework pipeline against the collection, needs MongoDB >= 2.2 + * + * Options + * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference ((ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). + * - **cursor** {Object}, return the query as cursor, on 2.6 > it returns as a real cursor on pre 2.6 it returns as an emulated cursor. + * - **cursor.batchSize** {Number}, the batchSize for the cursor + * - **out** {String}, the collection name to where to write the results from the aggregation (MongoDB 2.6 or higher). Warning any existing collection will be overwritten. + * - **explain** {Boolean, default:false}, explain returns the aggregation execution plan (requires mongodb 2.6 >). + * - **allowDiskUse** {Boolean, default:false}, allowDiskUse lets the server know if it can use disk to store temporary results for the aggregation (requires mongodb 2.6 >). + * + * @param {Array} array containing all the aggregation framework commands for the execution. + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the aggregate method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.aggregate = function() { return aggregation.aggregate; }(); + +/** + * Get all the collection statistics. + * + * Options + * - **scale** {Number}, divide the returned sizes by scale value. + * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference ((ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). + * + * @param {Objects} [options] options for the stats command. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the stats method or null if an error occured. + * @return {null} + * @api public + */ +Collection.prototype.stats = function() { return commands.stats; }(); + +/** + * Initiate a Out of order batch write operation. All operations will be buffered into insert/update/remove commands executed out of order. + * + * Options + * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal + * - **j**, (Boolean, default:false) write waits for journal sync before returning + * + * @param {Objects} [options] options for the initializeUnorderedBatch + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. The second argument will be a UnorderedBulkOperation object. + * @return {UnorderedBulkOperation} + * @api public + */ +Collection.prototype.initializeUnorderedBulkOp = function() { return unordered.initializeUnorderedBulkOp; }(); + +/** + * Initiate an In order bulk write operation, operations will be serially executed in the order they are added, creating a new operation for each switch in types. + * + * Options + * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal + * - **j**, (Boolean, default:false) write waits for journal sync before returning + * + * @param {Objects} [options] options for the initializeOrderedBulkOp + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. The second argument will be a OrderedBulkOperation object. + * @return {OrderedBulkOperation} + * @api public + */ +Collection.prototype.initializeOrderedBulkOp = function() { return ordered.initializeOrderedBulkOp; }(); + +/** + * Return N number of parallel cursors for a collection allowing parallel reading of entire collection. There are + * no ordering guarantees for returned results. + * + * Options + * - **readPreference** {String}, the prefered read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). + * - **batchSize** {Number, default:0}, set the batchSize for the getMoreCommand when iterating over the query results. + * - **numCursors**, {Number, 1} the maximum number of parallel command cursors to return (the number of returned cursors will be in the range 1:numCursors) + * + * @param {Objects} [options] options for the initializeOrderedBulkOp + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. The second argument will be an array of CommandCursor instances. + * @return {OrderedBulkOperation} + * @api public + */ +Collection.prototype.parallelCollectionScan = function() { return query.parallelCollectionScan; }(); + +/** + * @ignore + */ +Object.defineProperty(Collection.prototype, "hint", { + enumerable: true + , get: function () { + return this.internalHint; + } + , set: function (v) { + this.internalHint = shared.normalizeHintField(v); + } +}); + +/** + * Expose. + */ +exports.Collection = Collection; diff --git a/node_modules/mongodb/lib/mongodb/collection/aggregation.js b/node_modules/mongodb/lib/mongodb/collection/aggregation.js new file mode 100644 index 0000000..41c884c --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/collection/aggregation.js @@ -0,0 +1,318 @@ +var shared = require('./shared') + , utils = require('../utils') + , AggregationCursor = require('../aggregation_cursor').AggregationCursor + , Code = require('bson').Code + , DbCommand = require('../commands/db_command').DbCommand; + +/** + * Functions that are passed as scope args must + * be converted to Code instances. + * @ignore + */ +function processScope (scope) { + if (!utils.isObject(scope)) { + return scope; + } + + var keys = Object.keys(scope); + var i = keys.length; + var key; + var new_scope = {}; + + while (i--) { + key = keys[i]; + if ('function' == typeof scope[key]) { + new_scope[key] = new Code(String(scope[key])); + } else { + new_scope[key] = processScope(scope[key]); + } + } + + return new_scope; +} + +var pipe = function() { + return new AggregationCursor(this, this.serverCapabilities); +} + +var mapReduce = function mapReduce (map, reduce, options, callback) { + if ('function' === typeof options) callback = options, options = {}; + // Out must allways be defined (make sure we don't break weirdly on pre 1.8+ servers) + if(null == options.out) { + throw new Error("the out option parameter must be defined, see mongodb docs for possible values"); + } + + if ('function' === typeof map) { + map = map.toString(); + } + + if ('function' === typeof reduce) { + reduce = reduce.toString(); + } + + if ('function' === typeof options.finalize) { + options.finalize = options.finalize.toString(); + } + + var mapCommandHash = { + mapreduce: this.collectionName + , map: map + , reduce: reduce + }; + + // Add any other options passed in + for (var name in options) { + if ('scope' == name) { + mapCommandHash[name] = processScope(options[name]); + } else { + mapCommandHash[name] = options[name]; + } + } + + // Set read preference if we set one + var readPreference = shared._getReadConcern(this, options); + + // If we have a read preference and inline is not set as output fail hard + if((readPreference != false && readPreference != 'primary') + && options['out'] && (options['out'].inline != 1 && options['out'] != 'inline')) { + readPreference = 'primary'; + } + + // self + var self = this; + var cmd = DbCommand.createDbCommand(this.db, mapCommandHash); + + this.db._executeQueryCommand(cmd, {readPreference:readPreference}, function (err, result) { + if(err) return callback(err); + if(!result || !result.documents || result.documents.length == 0) + return callback(Error("command failed to return results"), null) + + // Check if we have an error + if(1 != result.documents[0].ok || result.documents[0].err || result.documents[0].errmsg) { + return callback(utils.toError(result.documents[0])); + } + + // Create statistics value + var stats = {}; + if(result.documents[0].timeMillis) stats['processtime'] = result.documents[0].timeMillis; + if(result.documents[0].counts) stats['counts'] = result.documents[0].counts; + if(result.documents[0].timing) stats['timing'] = result.documents[0].timing; + + // invoked with inline? + if(result.documents[0].results) { + // If we wish for no verbosity + if(options['verbose'] == null || !options['verbose']) { + return callback(null, result.documents[0].results); + } + return callback(null, result.documents[0].results, stats); + } + + // The returned collection + var collection = null; + + // If we have an object it's a different db + if(result.documents[0].result != null && typeof result.documents[0].result == 'object') { + var doc = result.documents[0].result; + collection = self.db.db(doc.db).collection(doc.collection); + } else { + // Create a collection object that wraps the result collection + collection = self.db.collection(result.documents[0].result) + } + + // If we wish for no verbosity + if(options['verbose'] == null || !options['verbose']) { + return callback(err, collection); + } + + // Return stats as third set of values + callback(err, collection, stats); + }); +}; + +/** + * Group function helper + * @ignore + */ +var groupFunction = function () { + var c = db[ns].find(condition); + var map = new Map(); + var reduce_function = reduce; + + while (c.hasNext()) { + var obj = c.next(); + var key = {}; + + for (var i = 0, len = keys.length; i < len; ++i) { + var k = keys[i]; + key[k] = obj[k]; + } + + var aggObj = map.get(key); + + if (aggObj == null) { + var newObj = Object.extend({}, key); + aggObj = Object.extend(newObj, initial); + map.put(key, aggObj); + } + + reduce_function(obj, aggObj); + } + + return { "result": map.values() }; +}.toString(); + +var group = function group(keys, condition, initial, reduce, finalize, command, options, callback) { + var args = Array.prototype.slice.call(arguments, 3); + callback = args.pop(); + // Fetch all commands + reduce = args.length ? args.shift() : null; + finalize = args.length ? args.shift() : null; + command = args.length ? args.shift() : null; + options = args.length ? args.shift() || {} : {}; + + // Make sure we are backward compatible + if(!(typeof finalize == 'function')) { + command = finalize; + finalize = null; + } + + if (!Array.isArray(keys) && keys instanceof Object && typeof(keys) !== 'function' && !(keys instanceof Code)) { + keys = Object.keys(keys); + } + + if(typeof reduce === 'function') { + reduce = reduce.toString(); + } + + if(typeof finalize === 'function') { + finalize = finalize.toString(); + } + + // Set up the command as default + command = command == null ? true : command; + + // Execute using the command + if(command) { + var reduceFunction = reduce instanceof Code + ? reduce + : new Code(reduce); + + var selector = { + group: { + 'ns': this.collectionName + , '$reduce': reduceFunction + , 'cond': condition + , 'initial': initial + , 'out': "inline" + } + }; + + // if finalize is defined + if(finalize != null) selector.group['finalize'] = finalize; + // Set up group selector + if ('function' === typeof keys || keys instanceof Code) { + selector.group.$keyf = keys instanceof Code + ? keys + : new Code(keys); + } else { + var hash = {}; + keys.forEach(function (key) { + hash[key] = 1; + }); + selector.group.key = hash; + } + + // Set read preference if we set one + var readPreference = shared._getReadConcern(this, options); + // Execute command + this.db.command(selector, {readPreference: readPreference}, function(err, result) { + if(err) return callback(err, null); + callback(null, result.retval); + }); + } else { + // Create execution scope + var scope = reduce != null && reduce instanceof Code + ? reduce.scope + : {}; + + scope.ns = this.collectionName; + scope.keys = keys; + scope.condition = condition; + scope.initial = initial; + + // Pass in the function text to execute within mongodb. + var groupfn = groupFunction.replace(/ reduce;/, reduce.toString() + ';'); + + this.db.eval(new Code(groupfn, scope), function (err, results) { + if (err) return callback(err, null); + callback(null, results.result || results); + }); + } +}; + +var aggregate = function(pipeline, options, callback) { + var args = Array.prototype.slice.call(arguments, 0); + callback = args.pop(); + var self = this; + + // If we have any of the supported options in the options object + var opts = args[args.length - 1] || {}; + options = opts.readPreference + || opts.explain + || opts.cursor + || opts.out + || opts.allowDiskUse ? args.pop() : {} + // If the callback is the option (as for cursor override it) + if(typeof callback == 'object' && callback != null) options = callback; + + // Convert operations to an array + if(!Array.isArray(args[0])) { + pipeline = []; + // Push all the operations to the pipeline + for(var i = 0; i < args.length; i++) pipeline.push(args[i]); + } + + // Is the user requesting a cursor + if(options.cursor != null && options.out == null) { + // Set the aggregation cursor options + var agg_cursor_options = options.cursor; + agg_cursor_options.pipe = pipeline; + agg_cursor_options.allowDiskUse = options.allowDiskUse == null ? false : options.allowDiskUse; + // Return the aggregation cursor + return new AggregationCursor(this, this.serverCapabilities, agg_cursor_options); + } + + // If out was specified + if(typeof options.out == 'string') { + pipeline.push({$out: options.out}); + } + + // Build the command + var command = { aggregate : this.collectionName, pipeline : pipeline}; + // If we have allowDiskUse defined + if(options.allowDiskUse) command.allowDiskUse = options.allowDiskUse; + + // Ensure we have the right read preference inheritance + options.readPreference = shared._getReadConcern(this, options); + // If explain has been specified add it + if(options.explain) command.explain = options.explain; + // Execute the command + this.db.command(command, options, function(err, result) { + if(err) { + callback(err); + } else if(result['err'] || result['errmsg']) { + callback(utils.toError(result)); + } else if(typeof result == 'object' && result['serverPipeline']) { + callback(null, result['serverPipeline']); + } else if(typeof result == 'object' && result['stages']) { + callback(null, result['stages']); + } else { + callback(null, result.result); + } + }); +} + +exports.mapReduce = mapReduce; +exports.group = group; +exports.aggregate = aggregate; +exports.pipe = pipe; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/collection/batch/common.js b/node_modules/mongodb/lib/mongodb/collection/batch/common.js new file mode 100644 index 0000000..c31c364 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/collection/batch/common.js @@ -0,0 +1,439 @@ +var utils = require('../../utils'); + +// Error codes +var UNKNOWN_ERROR = 8; +var INVALID_BSON_ERROR = 22; +var WRITE_CONCERN_ERROR = 64; +var MULTIPLE_ERROR = 65; + +// Insert types +var INSERT = 1; +var UPDATE = 2; +var REMOVE = 3 + +/** + * Helper function to define properties + */ +var defineReadOnlyProperty = function(self, name, value) { + Object.defineProperty(self, name, { + enumerable: true + , get: function() { + return value; + } + }); +} + +/** + * Keeps the state of a unordered batch so we can rewrite the results + * correctly after command execution + */ +var Batch = function(batchType, originalZeroIndex) { + this.originalZeroIndex = originalZeroIndex; + this.currentIndex = 0; + this.originalIndexes = []; + this.batchType = batchType; + this.operations = []; + this.size = 0; +} + +/** + * Wraps a legacy operation so we can correctly rewrite it's error + */ +var LegacyOp = function(batchType, operation, index) { + this.batchType = batchType; + this.index = index; + this.operation = operation; +} + +/** + * Create a new BatchWriteResult instance (INTERNAL TYPE, do not instantiate directly) + * + * @class Represents a BatchWriteResult + * @property **ok** {boolean} did bulk operation correctly execute + * @property **nInserted** {number} number of inserted documents + * @property **nUpdated** {number} number of documents updated logically + * @property **nUpserted** {number} number of upserted documents + * @property **nModified** {number} number of documents updated physically on disk + * @property **nRemoved** {number} number of removed documents + * @param {Object} batchResult internal data structure with results. + * @return {BatchWriteResult} a BatchWriteResult instance + */ +var BatchWriteResult = function(bulkResult) { + defineReadOnlyProperty(this, "ok", bulkResult.ok); + defineReadOnlyProperty(this, "nInserted", bulkResult.nInserted); + defineReadOnlyProperty(this, "nUpserted", bulkResult.nUpserted); + defineReadOnlyProperty(this, "nMatched", bulkResult.nMatched); + defineReadOnlyProperty(this, "nModified", bulkResult.nModified); + defineReadOnlyProperty(this, "nRemoved", bulkResult.nRemoved); + + /** + * Return an array of upserted ids + * + * @return {Array} + * @api public + */ + this.getUpsertedIds = function() { + return bulkResult.upserted; + } + + /** + * Return the upserted id at position x + * + * @param {Number} index the number of the upserted id to return, returns undefined if no result for passed in index + * @return {Array} + * @api public + */ + this.getUpsertedIdAt = function(index) { + return bulkResult.upserted[index]; + } + + /** + * Return raw internal result + * + * @return {Object} + * @api public + */ + this.getRawResponse = function() { + return bulkResult; + } + + /** + * Returns true if the bulk operation contains a write error + * + * @return {Boolean} + * @api public + */ + this.hasWriteErrors = function() { + return bulkResult.writeErrors.length > 0; + } + + /** + * Returns the number of write errors off the bulk operation + * + * @return {Number} + * @api public + */ + this.getWriteErrorCount = function() { + return bulkResult.writeErrors.length; + } + + /** + * Returns a specific write error object + * + * @return {WriteError} + * @api public + */ + this.getWriteErrorAt = function(index) { + if(index < bulkResult.writeErrors.length) { + return bulkResult.writeErrors[index]; + } + return null; + } + + /** + * Retrieve all write errors + * + * @return {Array} + * @api public + */ + this.getWriteErrors = function() { + return bulkResult.writeErrors; + } + + /** + * Retrieve lastOp if available + * + * @return {Array} + * @api public + */ + this.getLastOp = function() { + return bulkResult.lastOp; + } + + /** + * Retrieve the write concern error if any + * + * @return {WriteConcernError} + * @api public + */ + this.getWriteConcernError = function() { + if(bulkResult.writeConcernErrors.length == 0) { + return null; + } else if(bulkResult.writeConcernErrors.length == 1) { + // Return the error + return bulkResult.writeConcernErrors[0]; + } else { + + // Combine the errors + var errmsg = ""; + for(var i = 0; i < bulkResult.writeConcernErrors.length; i++) { + var err = bulkResult.writeConcernErrors[i]; + errmsg = errmsg + err.errmsg; + + // TODO: Something better + if(i == 0) errmsg = errmsg + " and "; + } + + return new WriteConcernError({ errmsg : errmsg, code : WRITE_CONCERN_ERROR }); + } + } + + this.toJSON = function() { + return bulkResult; + } + + this.toString = function() { + return "BatchWriteResult(" + this.toJSON(bulkResult) + ")"; + } + + this.isOk = function() { + return bulkResult.ok == 1; + } +} + +/** + * Wraps a write concern error + */ +var WriteConcernError = function(err) { + if(!(this instanceof WriteConcernError)) return new WriteConcernError(err); + + // Define properties + defineReadOnlyProperty(this, "code", err.code); + defineReadOnlyProperty(this, "errmsg", err.errmsg); + + this.toJSON = function() { + return {code: err.code, errmsg: err.errmsg}; + } + + this.toString = function() { + return "WriteConcernError(" + err.errmsg + ")"; + } +} + +/** + * Wraps the error + */ +var WriteError = function(err) { + if(!(this instanceof WriteError)) return new WriteError(err); + + // Define properties + defineReadOnlyProperty(this, "code", err.code); + defineReadOnlyProperty(this, "index", err.index); + defineReadOnlyProperty(this, "errmsg", err.errmsg); + + // + // Define access methods + this.getOperation = function() { + return err.op; + } + + this.toJSON = function() { + return {code: err.code, index: err.index, errmsg: err.errmsg, op: err.op}; + } + + this.toString = function() { + return "WriteError(" + JSON.stringify(this.toJSON()) + ")"; + } +} + +/** + * Merges results into shared data structure + */ +var mergeBatchResults = function(ordered, batch, bulkResult, err, result) { + // If we have an error set the result to be the err object + if(err) { + result = err; + } + + // Do we have a top level error stop processing and return + if(result.ok == 0 && bulkResult.ok == 1) { + bulkResult.ok = 0; + bulkResult.error = utils.toError(result); + return; + } else if(result.ok == 0 && bulkResult.ok == 0) { + return; + } + + // Add lastop if available + if(result.lastOp) { + bulkResult.lastOp = result.lastOp; + } + + // If we have an insert Batch type + if(batch.batchType == INSERT && result.n) { + bulkResult.nInserted = bulkResult.nInserted + result.n; + } + + // If we have an insert Batch type + if(batch.batchType == REMOVE && result.n) { + bulkResult.nRemoved = bulkResult.nRemoved + result.n; + } + + var nUpserted = 0; + + // We have an array of upserted values, we need to rewrite the indexes + if(Array.isArray(result.upserted)) { + nUpserted = result.upserted.length; + + for(var i = 0; i < result.upserted.length; i++) { + bulkResult.upserted.push({ + index: result.upserted[i].index + batch.originalZeroIndex + , _id: result.upserted[i]._id + }); + } + } else if(result.upserted) { + + nUpserted = 1; + + bulkResult.upserted.push({ + index: batch.originalZeroIndex + , _id: result.upserted + }); + } + + // If we have an update Batch type + if(batch.batchType == UPDATE && result.n) { + var nModified = result.nModified; + bulkResult.nUpserted = bulkResult.nUpserted + nUpserted; + bulkResult.nMatched = bulkResult.nMatched + (result.n - nUpserted); + + if(typeof nModified == 'number') { + bulkResult.nModified = bulkResult.nModified + nModified; + } else { + bulkResult.nModified = null; + } + } + + if(Array.isArray(result.writeErrors)) { + for(var i = 0; i < result.writeErrors.length; i++) { + + var writeError = { + index: batch.originalZeroIndex + result.writeErrors[i].index + , code: result.writeErrors[i].code + , errmsg: result.writeErrors[i].errmsg + , op: batch.operations[result.writeErrors[i].index] + }; + + bulkResult.writeErrors.push(new WriteError(writeError)); + } + } + + if(result.writeConcernError) { + bulkResult.writeConcernErrors.push(new WriteConcernError(result.writeConcernError)); + } +} + +// +// Merge a legacy result into the master results +var mergeLegacyResults = function(_ordered, _op, _batch, _results, _result, _index) { + // If we have an error already + if(_results.ok == 0) return false; + // Handle error + if((_result.errmsg || _result.err || _result instanceof Error) && _result.wtimeout != true) { + // && ((_result.wtimeout == null && _result.jnote == null && _result.wnote == null)) || _result.err == "norepl") { + var code = _result.code || UNKNOWN_ERROR; // Returned error code or unknown code + var errmsg = _result.errmsg || _result.err; + errmsg = errmsg || _result.message; + + // Result is replication issue, rewrite error to match write command + if(_result.wnote || _result.wtimeout || _result.jnote) { + // Set the code to replication error + code = WRITE_CONCERN_ERROR; + // Ensure we get the right error message + errmsg = _result.wnote || errmsg; + errmsg = _result.jnote || errmsg; + } + + // + // We have an error that is a show stopper, 16544 and 13 are auth errors that should stop processing + if(_result.wnote + || _result.jnote == "journaling not enabled on this server" + || _result.err == "norepl" + || _result.code == 16544 + || _result.code == 13) { + _results.ok = 0; + _results.error = utils.toError({code: code, errmsg: errmsg}); + return false; + } + + // Create a write error + var errResult = new WriteError({ + index: _index + , code: code + , errmsg: errmsg + , op: _op + }); + + // Err details + _results.writeErrors.push(errResult); + + // Check if we any errors + if(_ordered == true + && _result.jnote == null + && _result.wnote == null + && _result.wtimeout == null) { + return false; + } + } else if(_batch.batchType == INSERT) { + _results.nInserted = _results.nInserted + 1; + } else if(_batch.batchType == UPDATE) { + // If we have an upserted value or if the user provided a custom _id value + if(_result.upserted || (!_result.updatedExisting && _result.upserted == null)) { + _results.nUpserted = _results.nUpserted + 1; + } else { + _results.nMatched = _results.nMatched + _result.n; + _results.nModified = null; + } + } else if(_batch.batchType == REMOVE) { + _results.nRemoved = _results.nRemoved + _result; + } + + // We have a write concern error, add a write concern error to the results + if(_result.wtimeout != null || _result.jnote != null || _result.wnote != null) { + var error = _result.err || _result.errmsg || _result.wnote || _result.jnote || _result.wtimeout; + var code = _result.code || WRITE_CONCERN_ERROR; + // Push a write concern error to the list + _results.writeConcernErrors.push(new WriteConcernError({errmsg: error, code: code})); + } + + // We have an upserted field (might happen with a write concern error) + if(_result.upserted) { + _results.upserted.push({ + index: _index + , _id: _result.upserted + }) + } else if(!_result.updatedExisting && _result.upserted == null && _op.q && _op.q._id) { + _results.upserted.push({ + index: _index + , _id: _op.q._id + }) + } +} + +// +// Clone the options +var cloneOptions = function(options) { + var clone = {}; + var keys = Object.keys(options); + for(var i = 0; i < keys.length; i++) { + clone[keys[i]] = options[keys[i]]; + } + + return clone; +} + +// Exports symbols +exports.BatchWriteResult = BatchWriteResult; +exports.WriteError = WriteError; +exports.Batch = Batch; +exports.LegacyOp = LegacyOp; +exports.mergeBatchResults = mergeBatchResults; +exports.cloneOptions = cloneOptions; +exports.mergeLegacyResults = mergeLegacyResults; +exports.INVALID_BSON_ERROR = INVALID_BSON_ERROR; +exports.WRITE_CONCERN_ERROR = WRITE_CONCERN_ERROR; +exports.MULTIPLE_ERROR = MULTIPLE_ERROR; +exports.UNKNOWN_ERROR = UNKNOWN_ERROR; +exports.INSERT = INSERT; +exports.UPDATE = UPDATE; +exports.REMOVE = REMOVE; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/collection/batch/ordered.js b/node_modules/mongodb/lib/mongodb/collection/batch/ordered.js new file mode 100644 index 0000000..6fe275f --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/collection/batch/ordered.js @@ -0,0 +1,530 @@ +var shared = require('../shared') + , common = require('./common') + , utils = require('../../utils') + , hasWriteCommands = utils.hasWriteCommands + , WriteError = common.WriteError + , BatchWriteResult = common.BatchWriteResult + , LegacyOp = common.LegacyOp + , ObjectID = require('bson').ObjectID + , Batch = common.Batch + , mergeBatchResults = common.mergeBatchResults; + +/** + * Create a new OrderedBulkOperation instance (INTERNAL TYPE, do not instantiate directly) + * + * Options + * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal + * - **j**, (Boolean, default:false) write waits for journal sync before returning + * + * @class Represents a OrderedBulkOperation + * @param {Object} collection collection instance. + * @param {Object} [options] additional options for the collection. + * @return {Object} a ordered bulk operation instance. + */ +function OrderedBulkOperation (collection, options) { + options = options == null ? {} : options; + // TODO Bring from driver information in isMaster + var self = this; + var executed = false; + + // Current item + var currentOp = null; + + // Handle to the bson serializer, used to calculate running sizes + var db = collection.db; + var bson = db.bson; + + // Namespace for the operation + var namespace = collection.collectionName; + + // Set max byte size + var maxWriteBatchSize = db.serverConfig.checkoutWriter().maxWriteBatchSize || 1000; + var maxBatchSizeBytes = db.serverConfig.checkoutWriter().maxBsonSize; + + // Get the write concern + var writeConcern = shared._getWriteConcern(collection, options); + + // Current batch + var currentBatch = null; + var currentIndex = 0; + var currentBatchSize = 0; + var currentBatchSizeBytes = 0; + var batches = []; + + // Final results + var bulkResult = { + ok: 1 + , writeErrors: [] + , writeConcernErrors: [] + , nInserted: 0 + , nUpserted: 0 + , nMatched: 0 + , nModified: 0 + , nRemoved: 0 + , upserted: [] + }; + + // Specify a full class so we can generate documentation correctly + var FindOperators = function() { + /** + * Add a single update document to the bulk operation + * + * @param {Object} doc update operations + * @return {OrderedBulkOperation} + * @api public + */ + this.update = function(updateDocument) { + // Perform upsert + var upsert = typeof currentOp.upsert == 'boolean' ? currentOp.upsert : false; + + // Establish the update command + var document = { + q: currentOp.selector + , u: updateDocument + , multi: true + , upsert: upsert + } + + // Clear out current Op + currentOp = null; + // Add the update document to the list + return addToOperationsList(self, common.UPDATE, document); + } + + /** + * Add a single update one document to the bulk operation + * + * @param {Object} doc update operations + * @return {OrderedBulkOperation} + * @api public + */ + this.updateOne = function(updateDocument) { + // Perform upsert + var upsert = typeof currentOp.upsert == 'boolean' ? currentOp.upsert : false; + + // Establish the update command + var document = { + q: currentOp.selector + , u: updateDocument + , multi: false + , upsert: upsert + } + + // Clear out current Op + currentOp = null; + // Add the update document to the list + return addToOperationsList(self, common.UPDATE, document); + } + + /** + * Add a replace one operation to the bulk operation + * + * @param {Object} doc the new document to replace the existing one with + * @return {OrderedBulkOperation} + * @api public + */ + this.replaceOne = function(updateDocument) { + this.updateOne(updateDocument); + } + + /** + * Upsert modifier for update bulk operation + * + * @return {OrderedBulkOperation} + * @api public + */ + this.upsert = function() { + currentOp.upsert = true; + return this; + } + + /** + * Add a remove one operation to the bulk operation + * + * @param {Object} doc selector for the removal of documents + * @return {OrderedBulkOperation} + * @api public + */ + this.removeOne = function() { + // Establish the update command + var document = { + q: currentOp.selector + , limit: 1 + } + + // Clear out current Op + currentOp = null; + // Add the remove document to the list + return addToOperationsList(self, common.REMOVE, document); + } + + /** + * Add a remove operation to the bulk operation + * + * @param {Object} doc selector for the single document to remove + * @return {OrderedBulkOperation} + * @api public + */ + this.remove = function() { + // Establish the update command + var document = { + q: currentOp.selector + , limit: 0 + } + + // Clear out current Op + currentOp = null; + // Add the remove document to the list + return addToOperationsList(self, common.REMOVE, document); + } + } + + /** + * Add a single insert document to the bulk operation + * + * @param {Object} doc the document to insert + * @return {OrderedBulkOperation} + * @api public + */ + this.insert = function(document) { + if(document._id == null) document._id = new ObjectID(); + return addToOperationsList(self, common.INSERT, document); + } + + var getOrderedCommand = function(_self, _namespace, _docType, _operationDocuments) { + // Set up the types of operation + if(_docType == common.INSERT) { + return { + insert: _namespace + , documents: _operationDocuments + , ordered:true + } + } else if(_docType == common.UPDATE) { + return { + update: _namespace + , updates: _operationDocuments + , ordered:true + }; + } else if(_docType == common.REMOVE) { + return { + delete: _namespace + , deletes: _operationDocuments + , ordered:true + }; + } + } + + // Add to internal list of documents + var addToOperationsList = function(_self, docType, document) { + // Get the bsonSize + var bsonSize = bson.calculateObjectSize(document, false); + // Throw error if the doc is bigger than the max BSON size + if(bsonSize >= maxBatchSizeBytes) throw utils.toError("document is larger than the maximum size " + maxBatchSizeBytes); + // Create a new batch object if we don't have a current one + if(currentBatch == null) currentBatch = new Batch(docType, currentIndex); + + // Check if we need to create a new batch + if(((currentBatchSize + 1) >= maxWriteBatchSize) + || ((currentBatchSizeBytes + currentBatchSizeBytes) >= maxBatchSizeBytes) + || (currentBatch.batchType != docType)) { + // Save the batch to the execution stack + batches.push(currentBatch); + + // Create a new batch + currentBatch = new Batch(docType, currentIndex); + + // Reset the current size trackers + currentBatchSize = 0; + currentBatchSizeBytes = 0; + } else { + // Update current batch size + currentBatchSize = currentBatchSize + 1; + currentBatchSizeBytes = currentBatchSizeBytes + bsonSize; + } + + // We have an array of documents + if(Array.isArray(document)) { + throw utils.toError("operation passed in cannot be an Array"); + } else { + currentBatch.originalIndexes.push(currentIndex); + currentBatch.operations.push(document) + currentIndex = currentIndex + 1; + } + + // Return self + return _self; + } + + /** + * Initiate a find operation for an update/updateOne/remove/removeOne/replaceOne + * + * @param {Object} doc + * @return {OrderedBulkOperation} + * @api public + */ + this.find = function(selector) { + if (!selector) { + throw utils.toError("Bulk find operation must specify a selector"); + } + + // Save a current selector + currentOp = { + selector: selector + } + + return new FindOperators(); + } + + // + // Execute next write command in a chain + var executeCommands = function(callback) { + if(batches.length == 0) { + return callback(null, new BatchWriteResult(bulkResult)); + } + + // Ordered execution of the command + var batch = batches.shift(); + + // Build the command + var cmd = null; + + // Generate the right update + if(batch.batchType == common.UPDATE) { + cmd = { update: namespace, updates: batch.operations, ordered: true } + } else if(batch.batchType == common.INSERT) { + cmd = { insert: namespace, documents: batch.operations, ordered: true } + } else if(batch.batchType == common.REMOVE) { + cmd = { delete: namespace, deletes: batch.operations, ordered: true } + } + + // If we have a write concern + if(writeConcern != null) { + cmd.writeConcern = writeConcern; + } + + // Execute it + db.command(cmd, function(err, result) { + // Merge the results together + var mergeResult = mergeBatchResults(true, batch, bulkResult, err, result); + if(mergeResult != null) { + return callback(null, new BatchWriteResult(bulkResult)); + } + + // If we had a serious error + if(bulkResult.ok == 0) { + return callback(bulkResult.error, null); + } + + // If we are ordered and have errors and they are + // not all replication errors terminate the operation + if(bulkResult.writeErrors.length > 0) { + return callback(null, new BatchWriteResult(bulkResult)); + } + + // Execute the next command in line + executeCommands(callback); + }); + } + + // + // Execute the inserts + var executeInserts = function(_collection, _batch, _result, _callback) { + if(_batch.operations.length == 0) { + return _callback(null, _result); + } + + // Get the first update + var document = _batch.operations.shift(); + var index = _batch.originalIndexes.shift(); + + // Options for the update operation + var options = writeConcern || {}; + + // Execute the update + _collection.insert(document, options, function(err, r) { + // If we have don't have w:0 merge the result + if(options.w == null || options.w != 0) { + // Merge the results in + var result = common.mergeLegacyResults(true, document, _batch, bulkResult, err || r, index); + + if(result == false) { + return _callback(null, new BatchWriteResult(bulkResult)); + } + } + + // Update the index + _batch.currentIndex = _batch.currentIndex + 1; + + // Execute the next insert + executeInserts(_collection, _batch, _result, _callback); + }); + } + + // + // Execute updates + var executeUpdates = function(_collection, _batch, _result, _callback) { + if(_batch.operations.length == 0) { + return _callback(null, _result); + } + + // Get the first update + var update = _batch.operations.shift(); + var index = _batch.originalIndexes.shift(); + + // Options for the update operation + var options = writeConcern != null ? common.cloneOptions(writeConcern) : {}; + + // Add any additional options + if(update.multi) options.multi = update.multi; + if(update.upsert) options.upsert = update.upsert; + + // Execute the update + _collection.update(update.q, update.u, options, function(err, r, full) { + // If we have don't have w:0 merge the result + if(options.w == null || options.w != 0) { + // Merge the results in + var result = common.mergeLegacyResults(true, update, _batch, bulkResult, err || full, index); + if(result == false) { + return _callback(null, new BatchWriteResult(bulkResult)); + } + } + + // Update the index + _batch.currentIndex = _batch.currentIndex + 1; + + // Execute the next insert + executeUpdates(_collection, _batch, _result, _callback); + }); + } + + // + // Execute updates + var executeRemoves = function(_collection, _batch, _result, _callback) { + if(_batch.operations.length == 0) { + return _callback(null, _result); + } + + // Get the first update + var remove = _batch.operations.shift(); + var index = _batch.originalIndexes.shift(); + + // Options for the update operation + var options = writeConcern != null ? common.cloneOptions(writeConcern) : {}; + + // Add any additional options + options.single = remove.limit == 1 ? true : false; + + // Execute the update + _collection.remove(remove.q, options, function(err, r) { + // If we have don't have w:0 merge the result + if(options.w == null || options.w != 0) { + // Merge the results in + var result = common.mergeLegacyResults(true, remove, _batch, bulkResult, err || r, index); + if(result == false) { + return _callback(null, new BatchWriteResult(bulkResult)); + } + } + + // Update the index + _batch.currentIndex = _batch.currentIndex + 1; + + // Execute the next insert + executeRemoves(_collection, _batch, _result, _callback); + }); + } + + // + // Execute all operation in backwards compatible fashion + var backwardsCompatibilityExecuteCommands = function(callback) { + if(batches.length == 0) { + return callback(null, new BatchWriteResult(bulkResult)); + } + + // Ordered execution of the command + var batch = batches.shift(); + + // Process the legacy operations + var processLegacyOperations = function(err, results) { + // If we have any errors stop executing + if(bulkResult.writeErrors.length > 0) { + return callback(null, new BatchWriteResult(bulkResult)); + } + + // If we have a top level error stop + if(bulkResult.ok == 0) { + return callback(bulkResult.error, null); + } + + // Execute the next step + backwardsCompatibilityExecuteCommands(callback); + } + + // Execute an insert batch + if(batch.batchType == common.INSERT) { + return executeInserts(collection, batch, {n: 0}, processLegacyOperations); + } + + // Execute an update batch + if(batch.batchType == common.UPDATE) { + return executeUpdates(collection, batch, {n: 0}, processLegacyOperations); + } + + // Execute an update batch + if(batch.batchType == common.REMOVE) { + return executeRemoves(collection, batch, {n: 0}, processLegacyOperations); + } + } + + /** + * Execute the ordered bulk operation + * + * Options + * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal + * - **j**, (Boolean, default:false) write waits for journal sync before returning + * + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from from the ordered bulk operation. + * @return {null} + * @api public + */ + this.execute = function(_writeConcern, callback) { + if(executed) throw new utils.toError("batch cannot be re-executed"); + if(typeof _writeConcern == 'function') { + callback = _writeConcern; + } else { + writeConcern = _writeConcern; + } + + // If we have current batch + if(currentBatch) batches.push(currentBatch); + + // If we have no operations in the bulk raise an error + if(batches.length == 0) { + throw utils.toError("Invalid Operation, No operations in bulk"); + } + + // Check if we support bulk commands, override if needed to use legacy ops + if(hasWriteCommands(db.serverConfig.checkoutWriter())) + return executeCommands(callback); + + // Set nModified to null as we don't support this field + bulkResult.nModified = null; + + // Run in backward compatibility mode + backwardsCompatibilityExecuteCommands(callback); + } +} + +/** + * Returns an unordered batch object + * + */ +var initializeOrderedBulkOp = function(options) { + return new OrderedBulkOperation(this, options); +} + +exports.initializeOrderedBulkOp = initializeOrderedBulkOp; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/collection/batch/unordered.js b/node_modules/mongodb/lib/mongodb/collection/batch/unordered.js new file mode 100644 index 0000000..0024708 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/collection/batch/unordered.js @@ -0,0 +1,576 @@ +var shared = require('../shared') + , common = require('./common') + , utils = require('../../utils') + , hasWriteCommands = utils.hasWriteCommands + , WriteError = common.WriteError + , BatchWriteResult = common.BatchWriteResult + , LegacyOp = common.LegacyOp + , ObjectID = require('bson').ObjectID + , Batch = common.Batch + , mergeBatchResults = common.mergeBatchResults; + +/** + * Create a new UnorderedBulkOperation instance (INTERNAL TYPE, do not instantiate directly) + * + * Options + * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal + * - **j**, (Boolean, default:false) write waits for journal sync before returning + * + * @class Represents a UnorderedBulkOperation + * @param {Object} collection collection instance. + * @param {Object} [options] additional options for the collection. + * @return {Object} a ordered bulk operation instance. + */ +var UnorderedBulkOperation = function(collection, options) { + options = options == null ? {} : options; + + // Contains reference to self + var self = this; + // Get the namesspace for the write operations + var namespace = collection.collectionName; + // Used to mark operation as executed + var executed = false; + + // Current item + // var currentBatch = null; + var currentOp = null; + var currentIndex = 0; + var currentBatchSize = 0; + var currentBatchSizeBytes = 0; + var batches = []; + + // The current Batches for the different operations + var currentInsertBatch = null; + var currentUpdateBatch = null; + var currentRemoveBatch = null; + + // Handle to the bson serializer, used to calculate running sizes + var db = collection.db; + var bson = db.bson; + + // Set max byte size + var maxBatchSizeBytes = db.serverConfig.checkoutWriter().maxBsonSize; + var maxWriteBatchSize = db.serverConfig.checkoutWriter().maxWriteBatchSize || 1000; + + // Get the write concern + var writeConcern = shared._getWriteConcern(collection, options); + + // Final results + var bulkResult = { + ok: 1 + , writeErrors: [] + , writeConcernErrors: [] + , nInserted: 0 + , nUpserted: 0 + , nMatched: 0 + , nModified: 0 + , nRemoved: 0 + , upserted: [] + }; + + // Specify a full class so we can generate documentation correctly + var FindOperators = function() { + /** + * Add a single update document to the bulk operation + * + * @param {Object} doc update operations + * @return {UnorderedBulkOperation} + * @api public + */ + this.update = function(updateDocument) { + // Perform upsert + var upsert = typeof currentOp.upsert == 'boolean' ? currentOp.upsert : false; + + // Establish the update command + var document = { + q: currentOp.selector + , u: updateDocument + , multi: true + , upsert: upsert + } + + // Clear out current Op + currentOp = null; + // Add the update document to the list + return addToOperationsList(self, common.UPDATE, document); + } + + /** + * Add a single update one document to the bulk operation + * + * @param {Object} doc update operations + * @return {UnorderedBulkOperation} + * @api public + */ + this.updateOne = function(updateDocument) { + // Perform upsert + var upsert = typeof currentOp.upsert == 'boolean' ? currentOp.upsert : false; + + // Establish the update command + var document = { + q: currentOp.selector + , u: updateDocument + , multi: false + , upsert: upsert + } + + // Clear out current Op + currentOp = null; + // Add the update document to the list + return addToOperationsList(self, common.UPDATE, document); + } + + /** + * Add a replace one operation to the bulk operation + * + * @param {Object} doc the new document to replace the existing one with + * @return {UnorderedBulkOperation} + * @api public + */ + this.replaceOne = function(updateDocument) { + this.updateOne(updateDocument); + } + + /** + * Upsert modifier for update bulk operation + * + * @return {UnorderedBulkOperation} + * @api public + */ + this.upsert = function() { + currentOp.upsert = true; + return this; + } + + /** + * Add a remove one operation to the bulk operation + * + * @param {Object} doc selector for the removal of documents + * @return {UnorderedBulkOperation} + * @api public + */ + this.removeOne = function() { + // Establish the update command + var document = { + q: currentOp.selector + , limit: 1 + } + + // Clear out current Op + currentOp = null; + // Add the remove document to the list + return addToOperationsList(self, common.REMOVE, document); + } + + /** + * Add a remove operation to the bulk operation + * + * @param {Object} doc selector for the single document to remove + * @return {UnorderedBulkOperation} + * @api public + */ + this.remove = function() { + // Establish the update command + var document = { + q: currentOp.selector + , limit: 0 + } + + // Clear out current Op + currentOp = null; + // Add the remove document to the list + return addToOperationsList(self, common.REMOVE, document); + } + } + + // + // Add to the operations list + // + var addToOperationsList = function(_self, docType, document) { + // Get the bsonSize + var bsonSize = bson.calculateObjectSize(document, false); + // Throw error if the doc is bigger than the max BSON size + if(bsonSize >= maxBatchSizeBytes) throw utils.toError("document is larger than the maximum size " + maxBatchSizeBytes); + // Holds the current batch + var currentBatch = null; + // Get the right type of batch + if(docType == common.INSERT) { + currentBatch = currentInsertBatch; + } else if(docType == common.UPDATE) { + currentBatch = currentUpdateBatch; + } else if(docType == common.REMOVE) { + currentBatch = currentRemoveBatch; + } + + // Create a new batch object if we don't have a current one + if(currentBatch == null) currentBatch = new Batch(docType, currentIndex); + + // Check if we need to switch batch type + if(currentBatch.batchType != docType) { + // Save current batch + batches.push(currentBatch); + // Create a new batch + currentBatch = new Batch(docType, currentIndex); + + // Reset the current size trackers + currentBatchSize = 0; + currentBatchSizeBytes = 0; + } + + // Check if we need to create a new batch + if(((currentBatchSize + 1) >= maxWriteBatchSize) + || ((currentBatchSizeBytes + currentBatchSizeBytes) >= maxBatchSizeBytes) + || (currentBatch.batchType != docType)) { + // Save the batch to the execution stack + batches.push(currentBatch); + + // Create a new batch + currentBatch = new Batch(docType, currentIndex); + + // Reset the current size trackers + currentBatchSize = 0; + currentBatchSizeBytes = 0; + } else { + // Update current batch size + currentBatchSize = currentBatchSize + 1; + currentBatchSizeBytes = currentBatchSizeBytes + bsonSize; + } + + // We have an array of documents + if(Array.isArray(document)) { + throw utils.toError("operation passed in cannot be an Array"); + } else { + currentBatch.operations.push(document); + currentBatch.originalIndexes.push(currentIndex); + currentIndex = currentIndex + 1; + } + + // Save back the current Batch to the right type + if(docType == common.INSERT) { + currentInsertBatch = currentBatch; + } else if(docType == common.UPDATE) { + currentUpdateBatch = currentBatch; + } else if(docType == common.REMOVE) { + currentRemoveBatch = currentBatch; + } + + // Update current batch size + currentBatchSize = currentBatchSize + 1; + currentBatchSizeBytes = currentBatchSizeBytes + bsonSize; + + // Return self + return _self; + } + + /** + * Add a single insert document to the bulk operation + * + * @param {Object} doc the document to insert + * @return {UnorderedBulkOperation} + * @api public + */ + this.insert = function(document) { + if(document._id == null) document._id = new ObjectID(); + return addToOperationsList(self, common.INSERT, document); + } + + /** + * Initiate a find operation for an update/updateOne/remove/removeOne/replaceOne + * + * @param {Object} selector the selector used to locate documents for the operation + * @return {UnorderedBulkOperation} + * @api public + */ + this.find = function(selector) { + if (!selector) { + throw utils.toError("Bulk find operation must specify a selector"); + } + + // Save a current selector + currentOp = { + selector: selector + } + + return new FindOperators(); + } + + // + // Execute the command + var executeBatch = function(batch, callback) { + // Contains the command we are going to execute + var cmd = null; + + // Generate the right update + if(batch.batchType == common.UPDATE) { + cmd = { update: namespace, updates: batch.operations, ordered: false } + } else if(batch.batchType == common.INSERT) { + cmd = { insert: namespace, documents: batch.operations, ordered: false } + } else if(batch.batchType == common.REMOVE) { + cmd = { delete: namespace, deletes: batch.operations, ordered: false } + } + + // If we have a write concern + if(writeConcern != null) { + cmd.writeConcern = writeConcern; + } + + // Execute the write command + db.command(cmd, function(err, result) { + callback(null, mergeBatchResults(false, batch, bulkResult, err, result)); + }); + } + + // + // Execute all the commands + var executeBatches = function(callback) { + var numberOfCommandsToExecute = batches.length; + // Execute over all the batches + for(var i = 0; i < batches.length; i++) { + executeBatch(batches[i], function(err, result) { + numberOfCommandsToExecute = numberOfCommandsToExecute - 1; + + // Execute + if(numberOfCommandsToExecute == 0) { + // If we have an error stop + if(bulkResult.ok == 0 && callback) { + return callback(bulkResult.error, null); + } + + callback(null, new BatchWriteResult(bulkResult)); + } + }); + } + } + + /** + * Execute the unordered bulk operation + * + * Options + * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal + * - **j**, (Boolean, default:false) write waits for journal sync before returning + * + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from from the unordered bulk operation. + * @return {null} + * @api public + */ + this.execute = function(_writeConcern, callback) { + if(executed) throw utils.toError("batch cannot be re-executed"); + if(typeof _writeConcern == 'function') { + callback = _writeConcern; + } else { + writeConcern = _writeConcern; + } + + // If we have current batch + if(currentInsertBatch) batches.push(currentInsertBatch); + if(currentUpdateBatch) batches.push(currentUpdateBatch); + if(currentRemoveBatch) batches.push(currentRemoveBatch); + + // If we have no operations in the bulk raise an error + if(batches.length == 0) { + throw utils.toError("Invalid Operation, No operations in bulk"); + } + + // Check if we support bulk commands + if(hasWriteCommands(db.serverConfig.checkoutWriter())) + return executeBatches(function(err, result) { + callback(err, result); + }); + + // Set nModified to null as we don't support this field + bulkResult.nModified = null; + + // Run in backward compatibility mode + backwardsCompatibilityExecuteCommands(function(err, result) { + callback(err, result); + }); + } + + // + // Execute the inserts + var executeInserts = function(_collection, _batch, _result, _callback) { + var totalNumberOfInserts = _batch.operations.length; + + // Options for the update operation + var batchOptions = writeConcern || {}; + + // Execute the op + var executeLegacyInsert = function(_i, _op, _options, __callback) { + // Execute the update + _collection.insert(_op.operation, _options, function(err, r) { + // If we have don't have w:0 merge the result + if(_options.w == null || _options.w != 0) { + // Merge the results in + var result = common.mergeLegacyResults(false, _op.operation, _batch, bulkResult, err || r, _op.index); + if(result == false) { + return _callback(null, new BatchWriteResult(bulkResult)); + } + } + + __callback(null, _result); + }); + } + + // Execute all the insert operations + for(var i = 0; i < _batch.operations.length; i++) { + var legacyOp = new LegacyOp(_batch.batchType, _batch.operations[i], _batch.originalIndexes[i]); + executeLegacyInsert(i, legacyOp, batchOptions, function(err, result) { + totalNumberOfInserts = totalNumberOfInserts - 1; + + // No more inserts + if(totalNumberOfInserts == 0) { + _callback(null, _result); + } + }); + } + } + + // + // Execute updates + var executeUpdates = function(_collection, _batch, _result, _callback) { + var totalNumberOfUpdates = _batch.operations.length; + // Options for the update operation + var batchOptions = writeConcern || {}; + + // Execute the op + var executeLegacyUpdate = function(_i, _op, _options, __callback) { + var options = common.cloneOptions(batchOptions); + + // Add any additional options + if(_op.operation.multi != null) options.multi = _op.operation.multi ? true : false; + if(_op.operation.upsert != null) options.upsert = _op.operation.upsert; + + // Execute the update + _collection.update(_op.operation.q, _op.operation.u, options, function(err, r, full) { + // If we have don't have w:0 merge the result + if(options.w == null || options.w != 0) { + // Merge the results in + var result = common.mergeLegacyResults(false, _op.operation, _batch, bulkResult, err || full, _op.index); + if(result == false) { + return _callback(null, new BatchWriteResult(bulkResult)); + } + } + + return __callback(null, _result); + }); + } + + // Execute all the insert operations + for(var i = 0; i < _batch.operations.length; i++) { + var legacyOp = new LegacyOp(_batch.batchType, _batch.operations[i], _batch.originalIndexes[i]); + executeLegacyUpdate(i, legacyOp, options, function(err, result) { + totalNumberOfUpdates = totalNumberOfUpdates - 1; + + // No more inserts + if(totalNumberOfUpdates == 0) { + _callback(null, _result); + } + }); + } + } + + // + // Execute updates + var executeRemoves = function(_collection, _batch, _result, _callback) { + var totalNumberOfRemoves = _batch.operations.length; + // Options for the update operation + var batchOptions = writeConcern || {}; + + // Execute the op + var executeLegacyRemove = function(_i, _op, _options, __callback) { + var options = common.cloneOptions(batchOptions); + + // Add any additional options + if(_op.operation.limit != null) options.single = _op.operation.limit == 1 ? true : false; + + // Execute the update + _collection.remove(_op.operation.q, options, function(err, r) { + // If we have don't have w:0 merge the result + if(options.w == null || options.w != 0) { + // Merge the results in + var result = common.mergeLegacyResults(false, _op.operation, _batch, bulkResult, err || r, _op.index); + if(result == false) { + return _callback(null, new BatchWriteResult(bulkResult)); + } + } + + return __callback(null, _result); + }); + } + + // Execute all the insert operations + for(var i = 0; i < _batch.operations.length; i++) { + var legacyOp = new LegacyOp(_batch.batchType, _batch.operations[i], _batch.originalIndexes[i]); + executeLegacyRemove(i, legacyOp, options, function(err, result) { + totalNumberOfRemoves = totalNumberOfRemoves - 1; + + // No more inserts + if(totalNumberOfRemoves == 0) { + _callback(null, _result); + } + }); + } + } + + // + // Execute all operation in backwards compatible fashion + var backwardsCompatibilityExecuteCommands = function(callback) { + if(batches.length == 0) { + return callback(null, new BatchWriteResult(bulkResult)); + } + + // Ordered execution of the command + var batch = batches.shift(); + + // Process the legacy operations + var processLegacyOperations = function(err, results) { + // Merge the results together + var mergeResult = mergeBatchResults(false, batch, bulkResult, err, results); + if(mergeResult != null) { + return callback(null, mergeResult) + } + + // If we have an error stop + if(bulkResult.ok == 0 && callback) { + var internalCallback = callback; + callback = null; + return internalCallback(bulkResult.error, null); + } else if(bulkResult.ok == 0 && callback == null) { + return; + } + + // Execute the next step + backwardsCompatibilityExecuteCommands(callback); + } + + // Execute an insert batch + if(batch.batchType == common.INSERT) { + return executeInserts(collection, batch, {n: 0}, processLegacyOperations); + } + + // Execute an update batch + if(batch.batchType == common.UPDATE) { + return executeUpdates(collection, batch, {n: 0}, processLegacyOperations); + } + + // Execute an update batch + if(batch.batchType == common.REMOVE) { + return executeRemoves(collection, batch, {n: 0}, processLegacyOperations); + } + } +} + +/** + * Returns an unordered batch object + * + */ +var initializeUnorderedBulkOp = function(options) { + return new UnorderedBulkOperation(this, options); +} + +exports.initializeUnorderedBulkOp = initializeUnorderedBulkOp; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/collection/commands.js b/node_modules/mongodb/lib/mongodb/collection/commands.js new file mode 100644 index 0000000..91632d0 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/collection/commands.js @@ -0,0 +1,139 @@ +var shared = require('./shared') + , utils = require('../utils') + , f = require('util').format + , DbCommand = require('../commands/db_command').DbCommand; + +var stats = function stats(options, callback) { + var args = Array.prototype.slice.call(arguments, 0); + callback = args.pop(); + // Fetch all commands + options = args.length ? args.shift() || {} : {}; + + // Build command object + var commandObject = { + collStats:this.collectionName, + } + + // Check if we have the scale value + if(options['scale'] != null) commandObject['scale'] = options['scale']; + + // Ensure we have the right read preference inheritance + options.readPreference = shared._getReadConcern(this, options); + + // Execute the command + this.db.command(commandObject, options, callback); +} + +var count = function count(query, options, callback) { + var args = Array.prototype.slice.call(arguments, 0); + callback = args.pop(); + query = args.length ? args.shift() || {} : {}; + options = args.length ? args.shift() || {} : {}; + var skip = options.skip; + var limit = options.limit; + var hint = options.hint; + var maxTimeMS = options.maxTimeMS; + + // Final query + var cmd = { + 'count': this.collectionName + , 'query': query + , 'fields': null + }; + + // Add limit and skip if defined + if(typeof skip == 'number') cmd.skip = skip; + if(typeof limit == 'number') cmd.limit = limit; + if(hint) cmd.hint = hint; + + // Ensure we have the right read preference inheritance + options.readPreference = shared._getReadConcern(this, options); + + // Execute the command + this.db.command(cmd, options, function(err, result) { + if(err) return callback(err); + callback(null, result.n); + }); +}; + +var distinct = function distinct(key, query, options, callback) { + var args = Array.prototype.slice.call(arguments, 1); + callback = args.pop(); + query = args.length ? args.shift() || {} : {}; + options = args.length ? args.shift() || {} : {}; + var maxTimeMS = options.maxTimeMS; + + var cmd = { + 'distinct': this.collectionName + , 'key': key + , 'query': query + }; + + // Ensure we have the right read preference inheritance + options.readPreference = shared._getReadConcern(this, options); + + // Execute the command + this.db.command(cmd, options, function(err, result) { + if(err) return callback(err); + callback(null, result.values); + }); +}; + +var rename = function rename (newName, options, callback) { + var self = this; + if(typeof options == 'function') { + callback = options; + options = {} + } + + // Get collection class + var Collection = require('../collection').Collection; + // Ensure the new name is valid + shared.checkCollectionName(newName); + + // Build the command + var renameCollection = self.db.databaseName + "." + self.collectionName; + var toCollection = self.db.databaseName + "." + newName; + var dropTarget = typeof options.dropTarget == 'boolean' ? options.dropTarget : false; + var cmd = {'renameCollection':renameCollection, 'to':toCollection, 'dropTarget':dropTarget}; + + // Execute against admin + self.db.admin().command(cmd, options, function(err, result) { + if(err) return callback(err, null); + var doc = result.documents[0]; + // We have an error + if(doc.errmsg) return callback(utils.toError(doc), null); + try { + return callback(null, new Collection(self.db, newName, self.db.pkFactory)); + } catch(err) { + return callback(utils.toError(err), null); + } + }); +}; + +var options = function options(callback) { + var self = this; + + self.db.listCollections(self.collectionName, function(err, collections) { + if(err) return callback(err); + if(collections.length == 0) return callback(utils.toError(f("collection %s.%s not found", self.db.databaseName, self.collectionName))); + callback(err, collections[0].options || null); + }); +}; + +var isCapped = function isCapped(callback) { + this.options(function(err, document) { + if(err != null) { + callback(err); + } else { + callback(null, document && document.capped); + } + }); +}; + +exports.stats = stats; +exports.count = count; +exports.distinct = distinct; +exports.rename = rename; +exports.options = options; +exports.isCapped = isCapped; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/collection/core.js b/node_modules/mongodb/lib/mongodb/collection/core.js new file mode 100644 index 0000000..76583a9 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/collection/core.js @@ -0,0 +1,800 @@ +var InsertCommand = require('../commands/insert_command').InsertCommand + , DeleteCommand = require('../commands/delete_command').DeleteCommand + , UpdateCommand = require('../commands/update_command').UpdateCommand + , DbCommand = require('../commands/db_command').DbCommand + , utils = require('../utils') + , hasWriteCommands = require('../utils').hasWriteCommands + , shared = require('./shared'); + +/** + * Precompiled regexes + * @ignore + **/ +var eErrorMessages = /No matching object found/; + +// *************************************************** +// Insert function +// *************************************************** +var insert = function insert (docs, options, callback) { + if ('function' === typeof options) callback = options, options = {}; + if(options == null) options = {}; + if(!('function' === typeof callback)) callback = null; + + // Get a connection + var connection = this.db.serverConfig.checkoutWriter(); + var useLegacyOps = options.useLegacyOps == null || options.useLegacyOps == false ? false : true; + // If we support write commands let's perform the insert using it + if(!useLegacyOps && hasWriteCommands(connection) + && !Buffer.isBuffer(docs) + && !(Array.isArray(docs) && docs.length > 0 && Buffer.isBuffer(docs[0]))) { + insertWithWriteCommands(this, Array.isArray(docs) ? docs : [docs], options, callback); + return this + } + + // Backwards compatibility + insertAll(this, Array.isArray(docs) ? docs : [docs], options, callback); + return this; +}; + +// +// Uses the new write commands available from 2.6 > +// +var insertWithWriteCommands = function(self, docs, options, callback) { + // Get the intended namespace for the operation + var namespace = self.collectionName; + + // Ensure we have no \x00 bytes in the name causing wrong parsing + if(!!~namespace.indexOf("\x00")) { + return callback(new Error("namespace cannot contain a null character"), null); + } + + // Check if we have passed in continue on error + var continueOnError = typeof options['keepGoing'] == 'boolean' + ? options['keepGoing'] : false; + continueOnError = typeof options['continueOnError'] == 'boolean' + ? options['continueOnError'] : continueOnError; + + // Do we serialzie functions + var serializeFunctions = typeof options.serializeFunctions != 'boolean' + ? self.serializeFunctions : options.serializeFunctions; + + // Checkout a write connection + var connection = self.db.serverConfig.checkoutWriter(); + + // Do we return the actual result document + var fullResult = typeof options.fullResult == 'boolean' ? options.fullResult : false; + + // Collect errorOptions + var errorOptions = shared._getWriteConcern(self, options); + + // If we have a write command with no callback and w:0 fail + if(errorOptions.w && errorOptions.w != 0 && callback == null) { + throw new Error("writeConcern requires callback") + } + + // Add the documents and decorate them with id's if they have none + for(var index = 0, len = docs.length; index < len; ++index) { + var doc = docs[index]; + + // Add id to each document if it's not already defined + if (!(Buffer.isBuffer(doc)) + && doc['_id'] == null + && self.db.forceServerObjectId != true + && options.forceServerObjectId != true) { + doc['_id'] = self.pkFactory.createPk(); + } + } + + // Single document write + if(docs.length == 1) { + // Create the write command + var write_command = { + insert: namespace + , writeConcern: errorOptions + , ordered: !continueOnError + , documents: docs + } + + // Execute the write command + return self.db.command(write_command + , { connection:connection + , checkKeys: typeof options.checkKeys == 'boolean' ? options.checkKeys : true + , serializeFunctions: serializeFunctions + , writeCommand: true } + , function(err, result) { + if(errorOptions.w == 0 && typeof callback == 'function') return callback(null, null); + if(errorOptions.w == 0) return; + if(callback == null) return; + if(err != null) { + return callback(err, null); + } + + // Result has an error + if(!result.ok || Array.isArray(result.writeErrors) && result.writeErrors.length > 0) { + var error = utils.toError(result.writeErrors[0].errmsg); + error.code = result.writeErrors[0].code; + error.err = result.writeErrors[0].errmsg; + + if (fullResult) return callback(error, result != null ? result.getRawResponse() : null); + // Return the error + return callback(error, null); + } + + if(fullResult) return callback(null, result); + // Return the results for a whole batch + callback(null, docs) + }); + } else { + try { + // Multiple document write (use bulk) + var bulk = !continueOnError ? self.initializeOrderedBulkOp() : self.initializeUnorderedBulkOp(); + // Add all the documents + for(var i = 0; i < docs.length;i++) { + bulk.insert(docs[i]); + } + + // Execute the command + bulk.execute(errorOptions, function(err, result) { + if(errorOptions.w == 0 && typeof callback == 'function') return callback(null, null); + if(errorOptions.w == 0) return; + if(callback == null) return; + if(err) return callback(err, null); + if(result.hasWriteErrors()) { + var error = result.getWriteErrors()[0]; + error.code = result.getWriteErrors()[0].code; + error.err = result.getWriteErrors()[0].errmsg; + + if (fullResult) return callback(error, result != null ? result.getRawResponse() : null); + // Return the error + return callback(error, null); + } + + if(fullResult) return callback(null, result != null ? result.getRawResponse() : null); + // Return the results for a whole batch + callback(null, docs) + }); + } catch(err) { + callback(utils.toError(err), null); + } + } +} + +// +// Uses pre 2.6 OP_INSERT wire protocol +// +var insertAll = function insertAll (self, docs, options, callback) { + if('function' === typeof options) callback = options, options = {}; + if(options == null) options = {}; + if(!('function' === typeof callback)) callback = null; + + // Insert options (flags for insert) + var insertFlags = {}; + // If we have a mongodb version >= 1.9.1 support keepGoing attribute + if(options['keepGoing'] != null) { + insertFlags['keepGoing'] = options['keepGoing']; + } + + // If we have a mongodb version >= 1.9.1 support keepGoing attribute + if(options['continueOnError'] != null) { + insertFlags['continueOnError'] = options['continueOnError']; + } + + // DbName + var dbName = options['dbName']; + // If no dbname defined use the db one + if(dbName == null) { + dbName = self.db.databaseName; + } + + // Either use override on the function, or go back to default on either the collection + // level or db + if(options['serializeFunctions'] != null) { + insertFlags['serializeFunctions'] = options['serializeFunctions']; + } else { + insertFlags['serializeFunctions'] = self.serializeFunctions; + } + + // Get checkKeys value + var checkKeys = typeof options.checkKeys != 'boolean' ? true : options.checkKeys; + + // Do we return the actual result document + var fullResult = typeof options.fullResult == 'boolean' ? options.fullResult : false; + + // Pass in options + var insertCommand = new InsertCommand( + self.db + , dbName + "." + self.collectionName, checkKeys, insertFlags); + + // Add the documents and decorate them with id's if they have none + for(var index = 0, len = docs.length; index < len; ++index) { + var doc = docs[index]; + + // Add id to each document if it's not already defined + if (!(Buffer.isBuffer(doc)) + && doc['_id'] == null + && self.db.forceServerObjectId != true + && options.forceServerObjectId != true) { + doc['_id'] = self.pkFactory.createPk(); + } + + insertCommand.add(doc); + } + + // Collect errorOptions + var errorOptions = shared._getWriteConcern(self, options); + // Default command options + var commandOptions = {}; + // If safe is defined check for error message + if(shared._hasWriteConcern(errorOptions) && typeof callback == 'function') { + // Set safe option + commandOptions['safe'] = errorOptions; + // If we have an error option + if(typeof errorOptions == 'object') { + var keys = Object.keys(errorOptions); + for(var i = 0; i < keys.length; i++) { + commandOptions[keys[i]] = errorOptions[keys[i]]; + } + } + + // If we have a passed in connection use it + if(options.connection) { + commandOptions.connection = options.connection; + } + + // Execute command with safe options (rolls up both command and safe command into one and executes them on the same connection) + self.db._executeInsertCommand(insertCommand, commandOptions, handleWriteResults(function (err, results) { + if(err) return callback(err, null); + if(results == null) return callback(new Error("command failed to return result")); + if(fullResult) return callback(null, results); + callback(null, docs); + })); + } else if(shared._hasWriteConcern(errorOptions) && callback == null) { + throw new Error("Cannot use a writeConcern without a provided callback"); + } else { + // Execute the call without a write concern + var result = self.db._executeInsertCommand(insertCommand, commandOptions); + // If no callback just return + if(!callback) return; + // If error return error + if(result instanceof Error) { + return callback(result); + } + + // Otherwise just return + return callback(null, docs); + } +}; + +// *************************************************** +// Remove function +// *************************************************** +var removeWithWriteCommands = function(self, selector, options, callback) { + if('function' === typeof selector) { + callback = selector; + selector = options = {}; + } else if ('function' === typeof options) { + callback = options; + options = {}; + } + + // Get the intended namespace for the operation + var namespace = self.collectionName; + + // Ensure we have no \x00 bytes in the name causing wrong parsing + if(!!~namespace.indexOf("\x00")) { + return callback(new Error("namespace cannot contain a null character"), null); + } + + // Set default empty selector if none + selector = selector == null ? {} : selector; + + // Check if we have passed in continue on error + var continueOnError = typeof options['keepGoing'] == 'boolean' + ? options['keepGoing'] : false; + continueOnError = typeof options['continueOnError'] == 'boolean' + ? options['continueOnError'] : continueOnError; + + // Do we serialzie functions + var serializeFunctions = typeof options.serializeFunctions != 'boolean' + ? self.serializeFunctions : options.serializeFunctions; + + // Checkout a write connection + var connection = self.db.serverConfig.checkoutWriter(); + + // Figure out the value of top + var limit = options.single == true ? 1 : 0; + var upsert = typeof options.upsert == 'boolean' ? options.upsert : false; + + // Do we return the actual result document + var fullResult = typeof options.fullResult == 'boolean' ? options.fullResult : false; + + // Collect errorOptions + var errorOptions = shared._getWriteConcern(self, options); + + // If we have a write command with no callback and w:0 fail + if(errorOptions.w && errorOptions.w != 0 && callback == null) { + throw new Error("writeConcern requires callback") + } + + // Create the write command + var write_command = { + delete: namespace, + writeConcern: errorOptions, + ordered: !continueOnError, + deletes: [{ + q : selector, + limit: limit + }] + } + + // Execute the write command + self.db.command(write_command + , { connection:connection + , checkKeys: false + , serializeFunctions: serializeFunctions + , writeCommand: true } + , function(err, result) { + if(errorOptions.w == 0 && typeof callback == 'function') return callback(null, null); + if(errorOptions.w == 0) return; + if(callback == null) return; + if(err != null) { + return callback(err, null); + } + + // Result has an error + if(!result.ok || Array.isArray(result.writeErrors) && result.writeErrors.length > 0) { + var error = utils.toError(result.writeErrors[0].errmsg); + error.code = result.writeErrors[0].code; + error.err = result.writeErrors[0].errmsg; + // Return the error + return callback(error, null); + } + + if(fullResult) return callback(null, result); + // Backward compatibility format + var r = backWardsCompatibiltyResults(result, 'remove'); + // Return the results for a whole batch + callback(null, r.n, r) + }); +} + +var remove = function remove(selector, options, callback) { + if('function' === typeof options) callback = options, options = null; + if(options == null) options = {}; + if(!('function' === typeof callback)) callback = null; + + // Get a connection + var connection = this.db.serverConfig.checkoutWriter(); + var useLegacyOps = options.useLegacyOps == null || options.useLegacyOps == false ? false : true; + + // If we support write commands let's perform the insert using it + if(!useLegacyOps && hasWriteCommands(connection) && !Buffer.isBuffer(selector)) { + return removeWithWriteCommands(this, selector, options, callback); + } + + if ('function' === typeof selector) { + callback = selector; + selector = options = {}; + } else if ('function' === typeof options) { + callback = options; + options = {}; + } + + // Ensure options + if(options == null) options = {}; + if(!('function' === typeof callback)) callback = null; + // Ensure we have at least an empty selector + selector = selector == null ? {} : selector; + // Set up flags for the command, if we have a single document remove + var flags = 0 | (options.single ? 1 : 0); + + // Do we return the actual result document + var fullResult = typeof options.fullResult == 'boolean' ? options.fullResult : false; + + // DbName + var dbName = options['dbName']; + // If no dbname defined use the db one + if(dbName == null) { + dbName = this.db.databaseName; + } + + // Create a delete command + var deleteCommand = new DeleteCommand( + this.db + , dbName + "." + this.collectionName + , selector + , flags); + + var self = this; + var errorOptions = shared._getWriteConcern(self, options); + + // Execute the command, do not add a callback as it's async + if(shared._hasWriteConcern(errorOptions) && typeof callback == 'function') { + // Insert options + var commandOptions = {}; + // Set safe option + commandOptions['safe'] = true; + // If we have an error option + if(typeof errorOptions == 'object') { + var keys = Object.keys(errorOptions); + for(var i = 0; i < keys.length; i++) { + commandOptions[keys[i]] = errorOptions[keys[i]]; + } + } + + // If we have a passed in connection use it + if(options.connection) { + commandOptions.connection = options.connection; + } + + // Execute command with safe options (rolls up both command and safe command into one and executes them on the same connection) + this.db._executeRemoveCommand(deleteCommand, commandOptions, handleWriteResults(function (err, results) { + if(err) return callback(err, null); + if(results == null) return callback(new Error("command failed to return result")); + if(fullResult) return callback(null, results); + callback(null, results[0].n); + })); + } else if(shared._hasWriteConcern(errorOptions) && callback == null) { + throw new Error("Cannot use a writeConcern without a provided callback"); + } else { + var result = this.db._executeRemoveCommand(deleteCommand); + // If no callback just return + if (!callback) return; + // If error return error + if (result instanceof Error) { + return callback(result); + } + // Otherwise just return + return callback(); + } +}; + +// *************************************************** +// Save function +// *************************************************** +var save = function save(doc, options, callback) { + if('function' === typeof options) callback = options, options = null; + if(options == null) options = {}; + if(!('function' === typeof callback)) callback = null; + // Throw an error if attempting to perform a bulk operation + if(Array.isArray(doc)) throw new Error("doc parameter must be a single document"); + // Extract the id, if we have one we need to do a update command + var id = doc['_id']; + var commandOptions = shared._getWriteConcern(this, options); + if(options.connection) commandOptions.connection = options.connection; + if(typeof options.fullResult == 'boolean') commandOptions.fullResult = options.fullResult; + + if(id != null) { + commandOptions.upsert = true; + this.update({ _id: id }, doc, commandOptions, callback); + } else { + this.insert(doc, commandOptions, callback && function (err, docs) { + if(err) return callback(err, null); + + if(Array.isArray(docs)) { + callback(err, docs[0]); + } else { + callback(err, docs); + } + }); + } +}; + +// *************************************************** +// Update document function +// *************************************************** +var updateWithWriteCommands = function(self, selector, document, options, callback) { + if('function' === typeof options) callback = options, options = null; + if(options == null) options = {}; + if(!('function' === typeof callback)) callback = null; + + // Get the intended namespace for the operation + var namespace = self.collectionName; + + // Ensure we have no \x00 bytes in the name causing wrong parsing + if(!!~namespace.indexOf("\x00")) { + return callback(new Error("namespace cannot contain a null character"), null); + } + + // If we are not providing a selector or document throw + if(selector == null || typeof selector != 'object') + return callback(new Error("selector must be a valid JavaScript object")); + if(document == null || typeof document != 'object') + return callback(new Error("document must be a valid JavaScript object")); + + // Check if we have passed in continue on error + var continueOnError = typeof options['keepGoing'] == 'boolean' + ? options['keepGoing'] : false; + continueOnError = typeof options['continueOnError'] == 'boolean' + ? options['continueOnError'] : continueOnError; + + // Do we serialzie functions + var serializeFunctions = typeof options.serializeFunctions != 'boolean' + ? self.serializeFunctions : options.serializeFunctions; + + // Checkout a write connection + var connection = self.db.serverConfig.checkoutWriter(); + + // Figure out the value of top + var multi = typeof options.multi == 'boolean' ? options.multi : false; + var upsert = typeof options.upsert == 'boolean' ? options.upsert : false; + + // Do we return the actual result document + var fullResult = typeof options.fullResult == 'boolean' ? options.fullResult : false; + + // Collect errorOptions + var errorOptions = shared._getWriteConcern(self, options); + + // If we have a write command with no callback and w:0 fail + if(errorOptions.w && errorOptions.w != 0 && callback == null) { + throw new Error("writeConcern requires callback") + } + + // Create the write command + var write_command = { + update: namespace, + writeConcern: errorOptions, + ordered: !continueOnError, + updates: [{ + q : selector, + u: document, + multi: multi, + upsert: upsert + }] + } + + // Check if we have a checkKeys override + var checkKeys = typeof options.checkKeys == 'boolean' ? options.checkKeys : false; + + // Execute the write command + self.db.command(write_command + , { connection:connection + , checkKeys: checkKeys + , serializeFunctions: serializeFunctions + , writeCommand: true } + , function(err, result) { + if(errorOptions.w == 0 && typeof callback == 'function') return callback(null, null); + if(errorOptions.w == 0) return; + if(callback == null) return; + + if(errorOptions.w == 0 && typeof callback == 'function') return callback(null, null); + if(errorOptions.w == 0) return; + if(callback == null) return; + if(err != null) { + return callback(err, null); + } + + // Result has an error + if(!result.ok || Array.isArray(result.writeErrors) && result.writeErrors.length > 0) { + var error = utils.toError(result.writeErrors[0].errmsg); + error.code = result.writeErrors[0].code; + error.err = result.writeErrors[0].errmsg; + return callback(error, null); + } + + if(fullResult) return callback(null, result); + // Backward compatibility format + var r = backWardsCompatibiltyResults(result, 'update'); + // Return the results for a whole batch + callback(null, r.n, r) + }); +} + +var backWardsCompatibiltyResults = function(result, op) { + // Upserted + var upsertedValue = null; + var finalResult = null; + var updatedExisting = true; + + // We have a single document upserted result + if(Array.isArray(result.upserted) || result.upserted != null) { + updatedExisting = false; + upsertedValue = result.upserted; + } + + // Final result + if(op == 'remove' || op == 'insert') { + finalResult = {ok: true, n: result.n} + } else { + finalResult = {ok: true, n: result.n, updatedExisting: updatedExisting} + } + + if(upsertedValue != null) finalResult.upserted = upsertedValue; + return finalResult; +} + +var handleWriteResults = function handleWriteResults(callback) { + return function(err, error) { + var documents = error && error.documents; + if(!callback) return; + // We have an error + if(err) return callback(err, null); + // If no document something is terribly wrong + if(error == null) return callback(utils.toError("MongoDB did not return a response")); + // Handle the case where no result was returned + if(error != null && documents == null) { + if(typeof error.err == 'string') { + return callback(utils.toError(error.err)); + } else if(typeof error.errmsg == 'string') { + return callback(utils.toError(error.errmsg)); + } else { + return callback(utils.toError("Unknown MongoDB error")); + } + } + + // Handler normal cases + if(documents[0].err || documents[0].errmsg) { + callback(utils.toError(documents[0])); + } else if(documents[0].jnote || documents[0].wtimeout) { + callback(utils.toError(documents[0])); + } else { + callback(err, documents); + } + } +} + +var update = function update(selector, document, options, callback) { + if('function' === typeof options) callback = options, options = null; + if(options == null) options = {}; + if(!('function' === typeof callback)) callback = null; + + // Get a connection + var connection = options.connection || this.db.serverConfig.checkoutWriter(); + var useLegacyOps = options.useLegacyOps == null || options.useLegacyOps == false ? false : true; + // If we support write commands let's perform the insert using it + if(!useLegacyOps && hasWriteCommands(connection) && !Buffer.isBuffer(selector) && !Buffer.isBuffer(document)) { + return updateWithWriteCommands(this, selector, document, options, callback); + } + + // DbName + var dbName = options['dbName']; + // If no dbname defined use the db one + if(dbName == null) { + dbName = this.db.databaseName; + } + + // If we are not providing a selector or document throw + if(selector == null || typeof selector != 'object') return callback(new Error("selector must be a valid JavaScript object")); + if(document == null || typeof document != 'object') return callback(new Error("document must be a valid JavaScript object")); + + // Do we return the actual result document + var fullResult = typeof options.fullResult == 'boolean' ? options.fullResult : false; + + // Either use override on the function, or go back to default on either the collection + // level or db + if(options['serializeFunctions'] != null) { + options['serializeFunctions'] = options['serializeFunctions']; + } else { + options['serializeFunctions'] = this.serializeFunctions; + } + + // Build the options command + var updateCommand = new UpdateCommand( + this.db + , dbName + "." + this.collectionName + , selector + , document + , options); + + var self = this; + // Unpack the error options if any + var errorOptions = shared._getWriteConcern(this, options); + // If safe is defined check for error message + if(shared._hasWriteConcern(errorOptions) && typeof callback == 'function') { + // Insert options + var commandOptions = {}; + // Set safe option + commandOptions['safe'] = errorOptions; + // If we have an error option + if(typeof errorOptions == 'object') { + var keys = Object.keys(errorOptions); + for(var i = 0; i < keys.length; i++) { + commandOptions[keys[i]] = errorOptions[keys[i]]; + } + } + + // If we have a passed in connection use it + if(options.connection) { + commandOptions.connection = options.connection; + } + + // Execute command with safe options (rolls up both command and safe command into one and executes them on the same connection) + this.db._executeUpdateCommand(updateCommand, commandOptions, handleWriteResults(function(err, results) { + if(err) return callback(err, null); + if(results == null) return callback(new Error("command failed to return result")); + if(fullResult) return callback(null, results); + callback(null, results[0].n, results[0]); + })); + } else if(shared._hasWriteConcern(errorOptions) && callback == null) { + throw new Error("Cannot use a writeConcern without a provided callback"); + } else { + // Execute update + var result = this.db._executeUpdateCommand(updateCommand); + // If no callback just return + if (!callback) return; + // If error return error + if (result instanceof Error) { + return callback(result); + } + + // Otherwise just return + return callback(); + } +}; + +// *************************************************** +// findAndModify function +// *************************************************** +var findAndModify = function findAndModify (query, sort, doc, options, callback) { + var args = Array.prototype.slice.call(arguments, 1); + callback = args.pop(); + sort = args.length ? args.shift() || [] : []; + doc = args.length ? args.shift() : null; + options = args.length ? args.shift() || {} : {}; + var self = this; + + var queryObject = { + 'findandmodify': this.collectionName + , 'query': query + }; + + sort = utils.formattedOrderClause(sort); + if (sort) { + queryObject.sort = sort; + } + + queryObject.new = options.new ? 1 : 0; + queryObject.remove = options.remove ? 1 : 0; + queryObject.upsert = options.upsert ? 1 : 0; + + if (options.fields) { + queryObject.fields = options.fields; + } + + if (doc && !options.remove) { + queryObject.update = doc; + } + + // Checkout a write connection + options.connection = self.db.serverConfig.checkoutWriter(); + + // Either use override on the function, or go back to default on either the collection + // level or db + if(options['serializeFunctions'] != null) { + options['serializeFunctions'] = options['serializeFunctions']; + } else { + options['serializeFunctions'] = this.serializeFunctions; + } + + // No check on the documents + options.checkKeys = false; + + // Execute the command + this.db.command(queryObject + , options, function(err, result) { + if(err) return callback(err, null); + return callback(null, result.value, result); + }); +} + +// *************************************************** +// findAndRemove function +// *************************************************** +var findAndRemove = function(query, sort, options, callback) { + var args = Array.prototype.slice.call(arguments, 1); + callback = args.pop(); + sort = args.length ? args.shift() || [] : []; + options = args.length ? args.shift() || {} : {}; + // Add the remove option + options['remove'] = true; + // Execute the callback + this.findAndModify(query, sort, null, options, callback); +} + +// Map methods +exports.insert = insert; +exports.remove = remove; +exports.save = save; +exports.update = update; +exports.findAndModify = findAndModify; +exports.findAndRemove = findAndRemove; diff --git a/node_modules/mongodb/lib/mongodb/collection/geo.js b/node_modules/mongodb/lib/mongodb/collection/geo.js new file mode 100644 index 0000000..05d0c59 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/collection/geo.js @@ -0,0 +1,78 @@ +var shared = require('./shared') + , utils = require('../utils'); + +var geoNear = function geoNear(x, y, options, callback) { + var point = typeof(x) == 'object' && x + , args = Array.prototype.slice.call(arguments, point?1:2); + + callback = args.pop(); + // Fetch all commands + options = args.length ? args.shift() || {} : {}; + + // Build command object + var commandObject = { + geoNear:this.collectionName, + near: point || [x, y] + } + + // Ensure we have the right read preference inheritance + options.readPreference = shared._getReadConcern(this, options); + + // Exclude readPreference and existing options to prevent user from + // shooting themselves in the foot + var exclude = { + readPreference: true, + geoNear: true, + near: true + }; + + commandObject = utils.decorateCommand(commandObject, options, exclude); + + // Execute the command + this.db.command(commandObject, options, function (err, res) { + if (err) { + callback(err); + } else if (res.err || res.errmsg) { + callback(utils.toError(res)); + } else { + // should we only be returning res.results here? Not sure if the user + // should see the other return information + callback(null, res); + } + }); +} + +var geoHaystackSearch = function geoHaystackSearch(x, y, options, callback) { + var args = Array.prototype.slice.call(arguments, 2); + callback = args.pop(); + // Fetch all commands + options = args.length ? args.shift() || {} : {}; + + // Build command object + var commandObject = { + geoSearch:this.collectionName, + near: [x, y] + } + + // Remove read preference from hash if it exists + commandObject = utils.decorateCommand(commandObject, options, {readPreference: true}); + + // Ensure we have the right read preference inheritance + options.readPreference = shared._getReadConcern(this, options); + + // Execute the command + this.db.command(commandObject, options, function (err, res) { + if (err) { + callback(err); + } else if (res.err || res.errmsg) { + callback(utils.toError(res)); + } else { + // should we only be returning res.results here? Not sure if the user + // should see the other return information + callback(null, res); + } + }); +} + +exports.geoNear = geoNear; +exports.geoHaystackSearch = geoHaystackSearch; diff --git a/node_modules/mongodb/lib/mongodb/collection/index.js b/node_modules/mongodb/lib/mongodb/collection/index.js new file mode 100644 index 0000000..dda9cc8 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/collection/index.js @@ -0,0 +1,72 @@ +var _getWriteConcern = require('./shared')._getWriteConcern; + +var createIndex = function createIndex (fieldOrSpec, options, callback) { + // Clean up call + var args = Array.prototype.slice.call(arguments, 1); + callback = args.pop(); + options = args.length ? args.shift() || {} : {}; + options = typeof callback === 'function' ? options : callback; + options = options == null ? {} : options; + + // Collect errorOptions + var errorOptions = _getWriteConcern(this, options); + // Execute create index + this.db.createIndex(this.collectionName, fieldOrSpec, options, callback); +}; + +var indexExists = function indexExists(indexes, callback) { + this.indexInformation(function(err, indexInformation) { + // If we have an error return + if(err != null) return callback(err, null); + // Let's check for the index names + if(Array.isArray(indexes)) { + for(var i = 0; i < indexes.length; i++) { + if(indexInformation[indexes[i]] == null) { + return callback(null, false); + } + } + + // All keys found return true + return callback(null, true); + } else { + return callback(null, indexInformation[indexes] != null); + } + }); +} + +var dropAllIndexes = function dropIndexes (callback) { + this.db.dropIndex(this.collectionName, '*', function (err, result) { + if(err) return callback(err, false); + callback(null, true); + }); +}; + +var indexInformation = function indexInformation (options, callback) { + // Unpack calls + var args = Array.prototype.slice.call(arguments, 0); + callback = args.pop(); + options = args.length ? args.shift() || {} : {}; + // Call the index information + this.db.indexInformation(this.collectionName, options, callback); +}; + +var ensureIndex = function ensureIndex (fieldOrSpec, options, callback) { + // Clean up call + if (typeof callback === 'undefined' && typeof options === 'function') { + callback = options; + options = {}; + } + + if (options == null) { + options = {}; + } + + // Execute create index + this.db.ensureIndex(this.collectionName, fieldOrSpec, options, callback); +}; + +exports.createIndex = createIndex; +exports.indexExists = indexExists; +exports.dropAllIndexes = dropAllIndexes; +exports.indexInformation = indexInformation; +exports.ensureIndex = ensureIndex; diff --git a/node_modules/mongodb/lib/mongodb/collection/query.js b/node_modules/mongodb/lib/mongodb/collection/query.js new file mode 100644 index 0000000..ebff44d --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/collection/query.js @@ -0,0 +1,218 @@ +var ObjectID = require('bson').ObjectID + , Long = require('bson').Long + , DbCommand = require('../commands/db_command').DbCommand + , CommandCursor = require('../command_cursor').CommandCursor + , Scope = require('../scope').Scope + , shared = require('./shared') + , utils = require('../utils'); + +var testForFields = { + limit: 1, sort: 1, fields:1, skip: 1, hint: 1, explain: 1, snapshot: 1, timeout: 1, tailable: 1, tailableRetryInterval: 1 + , numberOfRetries: 1, awaitdata: 1, exhaust: 1, batchSize: 1, returnKey: 1, maxScan: 1, min: 1, max: 1, showDiskLoc: 1 + , comment: 1, raw: 1, readPreference: 1, partial: 1, read: 1, dbName: 1, oplogReplay: 1, connection: 1, maxTimeMS: 1 +}; + +// +// Find method +// +var find = function find () { + var options + , args = Array.prototype.slice.call(arguments, 0) + , has_callback = typeof args[args.length - 1] === 'function' + , has_weird_callback = typeof args[0] === 'function' + , callback = has_callback ? args.pop() : (has_weird_callback ? args.shift() : null) + , len = args.length + , selector = len >= 1 ? args[0] : {} + , fields = len >= 2 ? args[1] : undefined; + + if(len === 1 && has_weird_callback) { + // backwards compat for callback?, options case + selector = {}; + options = args[0]; + } + + if(len === 2 && !Array.isArray(fields)) { + var fieldKeys = Object.keys(fields); + var is_option = false; + + for(var i = 0; i < fieldKeys.length; i++) { + if(testForFields[fieldKeys[i]] != null) { + is_option = true; + break; + } + } + + if(is_option) { + options = fields; + fields = undefined; + } else { + options = {}; + } + } else if(len === 2 && Array.isArray(fields) && !Array.isArray(fields[0])) { + var newFields = {}; + // Rewrite the array + for(var i = 0; i < fields.length; i++) { + newFields[fields[i]] = 1; + } + // Set the fields + fields = newFields; + } + + if(3 === len) { + options = args[2]; + } + + // Ensure selector is not null + selector = selector == null ? {} : selector; + // Validate correctness off the selector + var object = selector; + if(Buffer.isBuffer(object)) { + var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24; + if(object_size != object.length) { + var error = new Error("query selector raw message size does not match message header size [" + object.length + "] != [" + object_size + "]"); + error.name = 'MongoError'; + throw error; + } + } + + // Validate correctness of the field selector + var object = fields; + if(Buffer.isBuffer(object)) { + var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24; + if(object_size != object.length) { + var error = new Error("query fields raw message size does not match message header size [" + object.length + "] != [" + object_size + "]"); + error.name = 'MongoError'; + throw error; + } + } + + // Check special case where we are using an objectId + if(selector instanceof ObjectID || (selector != null && selector._bsontype == 'ObjectID')) { + selector = {_id:selector}; + } + + // If it's a serialized fields field we need to just let it through + // user be warned it better be good + if(options && options.fields && !(Buffer.isBuffer(options.fields))) { + fields = {}; + + if(Array.isArray(options.fields)) { + if(!options.fields.length) { + fields['_id'] = 1; + } else { + for (var i = 0, l = options.fields.length; i < l; i++) { + fields[options.fields[i]] = 1; + } + } + } else { + fields = options.fields; + } + } + + if (!options) options = {}; + + var newOptions = {}; + // Make a shallow copy of options + for (var key in options) { + newOptions[key] = options[key]; + } + + newOptions.skip = len > 3 ? args[2] : options.skip ? options.skip : 0; + newOptions.limit = len > 3 ? args[3] : options.limit ? options.limit : 0; + newOptions.raw = options.raw != null && typeof options.raw === 'boolean' ? options.raw : this.raw; + newOptions.hint = options.hint != null ? shared.normalizeHintField(options.hint) : this.internalHint; + newOptions.timeout = len == 5 ? args[4] : typeof options.timeout === 'undefined' ? undefined : options.timeout; + // If we have overridden slaveOk otherwise use the default db setting + newOptions.slaveOk = options.slaveOk != null ? options.slaveOk : this.db.slaveOk; + + // Set option + var o = newOptions; + // Support read/readPreference + if(o["read"] != null) o["readPreference"] = o["read"]; + // If no readPreference specified set the collection level readPreference + o.readPreference = o.readPreference ? o.readPreference : this.readPreference; + // If still no readPreference specified set the db level + o.readPreference = o.readPreference ? o.readPreference : this.db.options.readPreference; + // Set slaveok if needed + if(o.readPreference == "secondary" || o.read == "secondaryOnly") o.slaveOk = true; + + // Ensure the query is an object + if(selector != null && typeof selector != 'object') { + throw utils.toError("query selector must be an object"); + } + + // Set the selector + o.selector = selector; + + // Create precursor + var scope = new Scope(this, {}, fields, o); + // Callback for backward compatibility + if(callback) return callback(null, scope.find(selector)); + // Return the pre cursor object + return scope.find(selector); +}; + +var findOne = function findOne () { + var self = this; + var args = Array.prototype.slice.call(arguments, 0); + var callback = args.pop(); + var cursor = this.find.apply(this, args).limit(-1).batchSize(1); + + // Return the item + cursor.nextObject(function(err, item) { + if(err != null) return callback(utils.toError(err), null); + callback(null, item); + }); +}; + +var parallelCollectionScan = function parallelCollectionScan (options, callback) { + var self = this; + + if(typeof options == 'function') { + callback = options; + options = {numCursors: 1}; + } + + // Set number of cursors to 1 + options.numCursors = options.numCursors || 1; + options.batchSize = options.batchSize || 1000; + + // Set read preference if we set one + options.readPreference = shared._getReadConcern(this, options); + + // Create command object + var commandObject = { + parallelCollectionScan: this.collectionName + , numCursors: options.numCursors + } + + // Execute the command + this.db.command(commandObject, options, function(err, result) { + if(err) return callback(err, null); + if(result == null) return callback(new Error("no result returned for parallelCollectionScan"), null); + + var cursors = []; + // Create command cursors for each item + for(var i = 0; i < result.cursors.length; i++) { + var rawId = result.cursors[i].cursor.id + // Convert cursorId to Long if needed + var cursorId = typeof rawId == 'number' ? Long.fromNumber(rawId) : rawId; + + // Command cursor options + var commandOptions = { + batchSize: options.batchSize + , cursorId: cursorId + , items: result.cursors[i].cursor.firstBatch + } + + // Add a command cursor + cursors.push(new CommandCursor(self.db, self, {}, commandOptions)); + } + + callback(null, cursors); + }); +} + +exports.find = find; +exports.findOne = findOne; +exports.parallelCollectionScan = parallelCollectionScan; diff --git a/node_modules/mongodb/lib/mongodb/collection/shared.js b/node_modules/mongodb/lib/mongodb/collection/shared.js new file mode 100644 index 0000000..77eae03 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/collection/shared.js @@ -0,0 +1,120 @@ +// *************************************************** +// Write concerns +// *************************************************** +var _hasWriteConcern = function(errorOptions) { + return errorOptions == true + || errorOptions.w > 0 + || errorOptions.w == 'majority' + || errorOptions.j == true + || errorOptions.journal == true + || errorOptions.fsync == true +} + +var _setWriteConcernHash = function(options) { + var finalOptions = {}; + if(options.w != null) finalOptions.w = options.w; + if(options.journal == true) finalOptions.j = options.journal; + if(options.j == true) finalOptions.j = options.j; + if(options.fsync == true) finalOptions.fsync = options.fsync; + if(options.wtimeout != null) finalOptions.wtimeout = options.wtimeout; + return finalOptions; +} + +var _getWriteConcern = function(self, options) { + // Final options + var finalOptions = {w:1}; + // Local options verification + if(options.w != null || typeof options.j == 'boolean' || typeof options.journal == 'boolean' || typeof options.fsync == 'boolean') { + finalOptions = _setWriteConcernHash(options); + } else if(typeof options.safe == "boolean") { + finalOptions = {w: (options.safe ? 1 : 0)}; + } else if(options.safe != null && typeof options.safe == 'object') { + finalOptions = _setWriteConcernHash(options.safe); + } else if(self.opts.w != null || typeof self.opts.j == 'boolean' || typeof self.opts.journal == 'boolean' || typeof self.opts.fsync == 'boolean') { + finalOptions = _setWriteConcernHash(self.opts); + } else if(typeof self.opts.safe == "boolean") { + finalOptions = {w: (self.opts.safe ? 1 : 0)}; + } else if(self.db.safe.w != null || typeof self.db.safe.j == 'boolean' || typeof self.db.safe.journal == 'boolean' || typeof self.db.safe.fsync == 'boolean') { + finalOptions = _setWriteConcernHash(self.db.safe); + } else if(self.db.options.w != null || typeof self.db.options.j == 'boolean' || typeof self.db.options.journal == 'boolean' || typeof self.db.options.fsync == 'boolean') { + finalOptions = _setWriteConcernHash(self.db.options); + } else if(typeof self.db.safe == "boolean") { + finalOptions = {w: (self.db.safe ? 1 : 0)}; + } + + // Ensure we don't have an invalid combination of write concerns + if(finalOptions.w < 1 + && (finalOptions.journal == true || finalOptions.j == true || finalOptions.fsync == true)) throw new Error("No acknowlegement using w < 1 cannot be combined with journal:true or fsync:true"); + + // Return the options + return finalOptions; +} + +var _getReadConcern = function(self, options) { + if(options.readPreference) return options.readPreference; + if(self.readPreference) return self.readPreference; + if(self.db.readPreference) return self.readPreference; + return 'primary'; +} + +/** + * @ignore + */ +var checkCollectionName = function checkCollectionName (collectionName) { + if('string' !== typeof collectionName) { + throw Error("collection name must be a String"); + } + + if(!collectionName || collectionName.indexOf('..') != -1) { + throw Error("collection names cannot be empty"); + } + + if(collectionName.indexOf('$') != -1 && + collectionName.match(/((^\$cmd)|(oplog\.\$main))/) == null) { + throw Error("collection names must not contain '$'"); + } + + if(collectionName.match(/^\.|\.$/) != null) { + throw Error("collection names must not start or end with '.'"); + } + + // Validate that we are not passing 0x00 in the colletion name + if(!!~collectionName.indexOf("\x00")) { + throw new Error("collection names cannot contain a null character"); + } +}; + + +/** + * Normalizes a `hint` argument. + * + * @param {String|Object|Array} hint + * @return {Object} + * @api private + */ +var normalizeHintField = function normalizeHintField(hint) { + var finalHint = null; + + if(typeof hint == 'string') { + finalHint = hint; + } else if(Array.isArray(hint)) { + finalHint = {}; + + hint.forEach(function(param) { + finalHint[param] = 1; + }); + } else if(hint != null && typeof hint == 'object') { + finalHint = {}; + for (var name in hint) { + finalHint[name] = hint[name]; + } + } + + return finalHint; +}; + +exports._getWriteConcern = _getWriteConcern; +exports._hasWriteConcern = _hasWriteConcern; +exports._getReadConcern = _getReadConcern; +exports.checkCollectionName = checkCollectionName; +exports.normalizeHintField = normalizeHintField; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/command_cursor.js b/node_modules/mongodb/lib/mongodb/command_cursor.js new file mode 100644 index 0000000..d248b22 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/command_cursor.js @@ -0,0 +1,362 @@ +var Long = require('bson').Long + , Readable = require('stream').Readable || require('readable-stream').Readable + , GetMoreCommand = require('./commands/get_more_command').GetMoreCommand + , inherits = require('util').inherits; + +var CommandCursor = function(db, collection, command, options) { + // Ensure empty options if no options passed + options = options || {}; + + // Set up + Readable.call(this, {objectMode: true}); + + // Default cursor id is 0 + var cursorId = options.cursorId || Long.fromInt(0); + var zeroCursor = Long.fromInt(0); + var state = 'init'; + var batchSize = options.batchSize || 0; + + // Hardcode batch size + if(command && command.cursor) { + batchSize = command.cursor.batchSize || 0; + } + + // BatchSize + var raw = options.raw || false; + var readPreference = options.readPreference || 'primary'; + + // Checkout a connection + var connection = db.serverConfig.checkoutReader(readPreference); + // MaxTimeMS + var maxTimeMS = options.maxTimeMS; + + // Contains all the items + var items = options.items || null; + + // Execute getmore + var getMore = function(callback) { + // Resolve more of the cursor using the getMore command + var getMoreCommand = new GetMoreCommand(db + , db.databaseName + "." + collection.collectionName + , batchSize + , cursorId + ); + + // Set up options + var command_options = { connection:connection }; + + // Execute the getMore Command + db._executeQueryCommand(getMoreCommand, command_options, function(err, result) { + if(err) { + items = []; + state = 'closed'; + return callback(err); + } + + // Return all the documents + callback(null, result); + }); + } + + var exhaustGetMore = function(callback) { + getMore(function(err, result) { + if(err) { + items = []; + state = 'closed'; + return callback(err, null); + } + + // Add the items + items = items.concat(result.documents); + + // Set the cursor id + cursorId = result.cursorId; + if(typeof cursorId == 'number') cursorId = Long.fromNumber(cursorId); + + // If the cursor is done + if(result.cursorId.equals(zeroCursor)) { + return callback(null, items); + } + + // Check the cursor id + exhaustGetMore(callback); + }); + } + + var exhaustGetMoreEach = function(callback) { + getMore(function(err, result) { + if(err) { + items = []; + state = 'closed'; + return callback(err, null); + } + + // Add the items + items = result.documents; + + // Emit all the items in the first batch + while(items.length > 0) { + callback(null, items.shift()); + } + + // Set the cursor id + cursorId = result.cursorId; + if(typeof cursorId == 'number') cursorId = Long.fromNumber(cursorId); + + // If the cursor is done + if(result.cursorId.equals(zeroCursor)) { + state = "closed"; + return callback(null, null); + } + + // Check the cursor id + exhaustGetMoreEach(callback); + }); + } + + // + // Get all the elements + // + this.get = function(options, callback) { + if(typeof options == 'function') { + callback = options; + options = {}; + } + + // Set the connection to the passed in one if it's provided + connection = options.connection ? options.connection : connection; + + // Command options + var _options = {connection:connection}; + if(typeof maxTimeMS == 'number') _options.maxTimeMS = maxTimeMS; + + // If we have a cursor Id already not equal to 0 we are just going to + // exhaust the cursor + if(cursorId.notEquals(zeroCursor)) { + // If no items set an empty array + items = items || []; + // Exhaust the cursor + return exhaustGetMore(callback); + } + + // Execute the internal command first + db.command(command, _options, function(err, result) { + if(err) { + state = 'closed'; + return callback(err, null); + } + + // Retrieve the cursor id + cursorId = result.cursor.id; + if(typeof cursorId == 'number') cursorId = Long.fromNumber(cursorId); + + // Validate cursorId + if(cursorId.equals(zeroCursor)) { + return callback(null, result.cursor.firstBatch); + }; + + // Add to the items + items = result.cursor.firstBatch; + // Execute the getMore + exhaustGetMore(callback); + }); + } + + // + // Iterate over all the items + // + this.each = function(options, callback) { + if(typeof options == 'function') { + callback = options; + options = {}; + } + + // If it's a closed cursor return error + if(this.isClosed()) return callback(new Error("cursor is closed")); + // Set the connection to the passed in one if it's provided + connection = options.connection ? options.connection : connection; + + // Command options + var _options = {connection:connection}; + if(typeof maxTimeMS == 'number') _options.maxTimeMS = maxTimeMS; + + // If we have a cursor Id already not equal to 0 we are just going to + // exhaust the cursor + if(cursorId.notEquals(zeroCursor)) { + // If no items set an empty array + items = items || []; + + // Emit all the items in the first batch + while(items.length > 0) { + callback(null, items.shift()); + } + + // Exhaust the cursor + return exhaustGetMoreEach(callback); + } + + // Execute the internal command first + db.command(command, _options, function(err, result) { + if(err) { + state = 'closed'; + return callback(err, null); + } + + // Get all the items + items = result.cursor.firstBatch; + + // Emit all the items in the first batch + while(items.length > 0) { + callback(null, items.shift()); + } + + // Retrieve the cursor id + cursorId = result.cursor.id; + if(typeof cursorId == 'number') cursorId = Long.fromNumber(cursorId); + + // If no cursor we just finish up the current batch of items + if(cursorId.equals(zeroCursor)) { + state = 'closed'; + return callback(null, null); + } + + // Emit each until no more getMore's + exhaustGetMoreEach(callback); + }); + } + + // + // Get the next object + // + this.next = function(options, callback) { + if(typeof options == 'function') { + callback = options; + options = {}; + } + + // If it's a closed cursor return error + if(this.isClosed()) return callback(new Error("cursor is closed")); + + // Set the connection to the passed in one if it's provided + connection = options.connection ? options.connection : connection; + + // Command options + var _options = {connection:connection}; + if(typeof maxTimeMS == 'number') _options.maxTimeMS = maxTimeMS; + + // If we have a cursor Id already not equal to 0 we are just going to + // going to bypass the command execution + if(cursorId.notEquals(zeroCursor)) { + items = items || []; + } + + // Execute the internal command first + if(!items) { + db.command(command, _options, function(err, result) { + if(err) { + state = 'closed'; + return callback(err, null); + } + + // Retrieve the cursor id + cursorId = result.cursor.id; + if(typeof cursorId == 'number') cursorId = Long.fromNumber(cursorId); + // Get the first batch results + items = result.cursor.firstBatch; + // We have items return the first one + if(items.length > 0) { + callback(null, items.shift()); + } else { + state = 'closed'; + callback(null, null); + } + }); + } else if(items.length > 0) { + callback(null, items.shift()); + } else if(items.length == 0 && cursorId.equals(zeroCursor)) { + state = 'closed'; + callback(null, null); + } else { + // Execute a getMore + getMore(function(err, result) { + if(err) { + state = 'closed'; + return callback(err, null); + } + + // Set the cursor id + cursorId = result.cursorId; + if(typeof cursorId == 'number') cursorId = Long.fromNumber(cursorId); + + // Add the items + items = items.concat(result.documents); + // If no more items + if(items.length == 0) { + state = 'closed'; + return callback(null, null); + } + + // Return the item + return callback(null, items.shift()); + }) + } + } + + // Validate if the cursor is closed + this.isClosed = function() { + return state == 'closed'; + } + + // Allow us to set the MaxTimeMS + this.maxTimeMS = function(_maxTimeMS) { + maxTimeMS = _maxTimeMS; + } + + // Close the cursor sending a kill cursor command if needed + this.close = function(callback) { + // Close the cursor if not needed + if(cursorId instanceof Long && cursorId.greaterThan(Long.fromInt(0))) { + try { + var command = new KillCursorCommand(this.db, [cursorId]); + // Added an empty callback to ensure we don't throw any null exceptions + db._executeQueryCommand(command, {connection:connection}); + } catch(err) {} + } + + // Null out the connection + connection = null; + // Reset cursor id + cursorId = Long.fromInt(0); + // Set to closed status + state = 'closed'; + // Clear out all the items + items = null; + + if(callback) { + callback(null, null); + } + } + + // + // Stream method + // + this._read = function(n) { + var self = this; + // Read the next command cursor doc + self.next(function(err, result) { + if(err) { + self.emit('error', err); + return self.push(null); + } + + self.push(result); + }); + } +} + +// Inherit from Readable +if(Readable != null) { + inherits(CommandCursor, Readable); +} + +exports.CommandCursor = CommandCursor; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/commands/base_command.js b/node_modules/mongodb/lib/mongodb/commands/base_command.js new file mode 100644 index 0000000..9558582 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/commands/base_command.js @@ -0,0 +1,29 @@ +/** + Base object used for common functionality +**/ +var BaseCommand = exports.BaseCommand = function BaseCommand() { +}; + +var id = 1; +BaseCommand.prototype.getRequestId = function getRequestId() { + if (!this.requestId) this.requestId = id++; + return this.requestId; +}; + +BaseCommand.prototype.setMongosReadPreference = function setMongosReadPreference(readPreference, tags) {} + +BaseCommand.prototype.updateRequestId = function() { + this.requestId = id++; + return this.requestId; +}; + +// OpCodes +BaseCommand.OP_REPLY = 1; +BaseCommand.OP_MSG = 1000; +BaseCommand.OP_UPDATE = 2001; +BaseCommand.OP_INSERT = 2002; +BaseCommand.OP_GET_BY_OID = 2003; +BaseCommand.OP_QUERY = 2004; +BaseCommand.OP_GET_MORE = 2005; +BaseCommand.OP_DELETE = 2006; +BaseCommand.OP_KILL_CURSORS = 2007; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/commands/db_command.js b/node_modules/mongodb/lib/mongodb/commands/db_command.js new file mode 100644 index 0000000..39bdb6e --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/commands/db_command.js @@ -0,0 +1,101 @@ +var QueryCommand = require('./query_command').QueryCommand, + InsertCommand = require('./insert_command').InsertCommand, + inherits = require('util').inherits, + utils = require('../utils'), + crypto = require('crypto'); + +/** + Db Command +**/ +var DbCommand = exports.DbCommand = function(dbInstance, collectionName, queryOptions, numberToSkip, numberToReturn, query, returnFieldSelector, options) { + QueryCommand.call(this); + this.collectionName = collectionName; + this.queryOptions = queryOptions; + this.numberToSkip = numberToSkip; + this.numberToReturn = numberToReturn; + this.query = query; + this.returnFieldSelector = returnFieldSelector; + this.db = dbInstance; + + // Set the slave ok bit + if(this.db && this.db.slaveOk) { + this.queryOptions |= QueryCommand.OPTS_SLAVE; + } + + // Make sure we don't get a null exception + options = options == null ? {} : options; + + // Allow for overriding the BSON checkKeys function + this.checkKeys = typeof options['checkKeys'] == 'boolean' ? options["checkKeys"] : true; + + // Let us defined on a command basis if we want functions to be serialized or not + if(options['serializeFunctions'] != null && options['serializeFunctions']) { + this.serializeFunctions = true; + } +}; + +inherits(DbCommand, QueryCommand); + +// Constants +DbCommand.SYSTEM_NAMESPACE_COLLECTION = "system.namespaces"; +DbCommand.SYSTEM_INDEX_COLLECTION = "system.indexes"; +DbCommand.SYSTEM_PROFILE_COLLECTION = "system.profile"; +DbCommand.SYSTEM_USER_COLLECTION = "system.users"; +DbCommand.SYSTEM_COMMAND_COLLECTION = "$cmd"; +DbCommand.SYSTEM_JS_COLLECTION = "system.js"; + +// New commands +DbCommand.NcreateIsMasterCommand = function(db, databaseName) { + return new DbCommand(db, databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'ismaster':1}, null); +}; + +// Provide constructors for different db commands +DbCommand.createIsMasterCommand = function(db) { + return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'ismaster':1}, null); +}; + +DbCommand.createGetLastErrorCommand = function(options, db) { + if (typeof db === 'undefined') { + db = options; + options = {}; + } + // Final command + var command = {'getlasterror':1}; + // If we have an options Object let's merge in the fields (fsync/wtimeout/w) + if('object' === typeof options) { + for(var name in options) { + command[name] = options[name] + } + } + + // Special case for w == 1, remove the w + if(1 == command.w) { + delete command.w; + } + + // Execute command + return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, command, null); +}; + +DbCommand.createGetLastStatusCommand = DbCommand.createGetLastErrorCommand; + +DbCommand.createDbCommand = function(db, command_hash, options, auth_db) { + var db_name = (auth_db ? auth_db : db.databaseName) + "." + DbCommand.SYSTEM_COMMAND_COLLECTION; + options = options == null ? {checkKeys: false} : options; + return new DbCommand(db, db_name, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, command_hash, null, options); +}; + +DbCommand.createAdminDbCommand = function(db, command_hash) { + return new DbCommand(db, "admin." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, command_hash, null); +}; + +DbCommand.createAdminDbCommandSlaveOk = function(db, command_hash) { + return new DbCommand(db, "admin." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT | QueryCommand.OPTS_SLAVE, 0, -1, command_hash, null); +}; + +DbCommand.createDbSlaveOkCommand = function(db, command_hash, options) { + options = options == null ? {checkKeys: false} : options; + var dbName = options.dbName ? options.dbName : db.databaseName; + var flags = options.slaveOk ? QueryCommand.OPTS_NO_CURSOR_TIMEOUT | QueryCommand.OPTS_SLAVE : QueryCommand.OPTS_NO_CURSOR_TIMEOUT; + return new DbCommand(db, dbName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, flags, 0, -1, command_hash, null, options); +}; diff --git a/node_modules/mongodb/lib/mongodb/commands/delete_command.js b/node_modules/mongodb/lib/mongodb/commands/delete_command.js new file mode 100644 index 0000000..61a37ed --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/commands/delete_command.js @@ -0,0 +1,129 @@ +var BaseCommand = require('./base_command').BaseCommand, + inherits = require('util').inherits; + +/** + Insert Document Command +**/ +var DeleteCommand = exports.DeleteCommand = function(db, collectionName, selector, flags) { + BaseCommand.call(this); + + // Validate correctness off the selector + var object = selector; + if(Buffer.isBuffer(object)) { + var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24; + if(object_size != object.length) { + var error = new Error("delete raw message size does not match message header size [" + object.length + "] != [" + object_size + "]"); + error.name = 'MongoError'; + throw error; + } + } + + this.flags = flags; + this.collectionName = collectionName; + this.selector = selector; + this.db = db; +}; + +inherits(DeleteCommand, BaseCommand); + +DeleteCommand.OP_DELETE = 2006; + +/* +struct { + MsgHeader header; // standard message header + int32 ZERO; // 0 - reserved for future use + cstring fullCollectionName; // "dbname.collectionname" + int32 ZERO; // 0 - reserved for future use + mongo.BSON selector; // query object. See below for details. +} +*/ +DeleteCommand.prototype.toBinary = function(bsonSettings) { + // Validate that we are not passing 0x00 in the colletion name + if(!!~this.collectionName.indexOf("\x00")) { + throw new Error("namespace cannot contain a null character"); + } + + // Calculate total length of the document + var totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + 4 + this.db.bson.calculateObjectSize(this.selector, false, true) + (4 * 4); + + // Enforce maximum bson size + if(!bsonSettings.disableDriverBSONSizeCheck + && totalLengthOfCommand > bsonSettings.maxBsonSize) + throw new Error("Document exceeds maximum allowed bson size of " + bsonSettings.maxBsonSize + " bytes"); + + if(bsonSettings.disableDriverBSONSizeCheck + && totalLengthOfCommand > bsonSettings.maxMessageSizeBytes) + throw new Error("Command exceeds maximum message size of " + bsonSettings.maxMessageSizeBytes + " bytes"); + + // Let's build the single pass buffer command + var _index = 0; + var _command = new Buffer(totalLengthOfCommand); + // Write the header information to the buffer + _command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff; + _command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff; + _command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff; + _command[_index] = totalLengthOfCommand & 0xff; + // Adjust index + _index = _index + 4; + // Write the request ID + _command[_index + 3] = (this.requestId >> 24) & 0xff; + _command[_index + 2] = (this.requestId >> 16) & 0xff; + _command[_index + 1] = (this.requestId >> 8) & 0xff; + _command[_index] = this.requestId & 0xff; + // Adjust index + _index = _index + 4; + // Write zero + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + // Write the op_code for the command + _command[_index + 3] = (DeleteCommand.OP_DELETE >> 24) & 0xff; + _command[_index + 2] = (DeleteCommand.OP_DELETE >> 16) & 0xff; + _command[_index + 1] = (DeleteCommand.OP_DELETE >> 8) & 0xff; + _command[_index] = DeleteCommand.OP_DELETE & 0xff; + // Adjust index + _index = _index + 4; + + // Write zero + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + + // Write the collection name to the command + _index = _index + _command.write(this.collectionName, _index, 'utf8') + 1; + _command[_index - 1] = 0; + + // Write the flags + _command[_index + 3] = (this.flags >> 24) & 0xff; + _command[_index + 2] = (this.flags >> 16) & 0xff; + _command[_index + 1] = (this.flags >> 8) & 0xff; + _command[_index] = this.flags & 0xff; + // Adjust index + _index = _index + 4; + + // Document binary length + var documentLength = 0 + + // Serialize the selector + // If we are passing a raw buffer, do minimal validation + if(Buffer.isBuffer(this.selector)) { + documentLength = this.selector.length; + // Copy the data into the current buffer + this.selector.copy(_command, _index); + } else { + documentLength = this.db.bson.serializeWithBufferAndIndex(this.selector, false, _command, _index) - _index + 1; + } + + // Write the length to the document + _command[_index + 3] = (documentLength >> 24) & 0xff; + _command[_index + 2] = (documentLength >> 16) & 0xff; + _command[_index + 1] = (documentLength >> 8) & 0xff; + _command[_index] = documentLength & 0xff; + // Update index in buffer + _index = _index + documentLength; + // Add terminating 0 for the object + _command[_index - 1] = 0; + return _command; +}; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/commands/get_more_command.js b/node_modules/mongodb/lib/mongodb/commands/get_more_command.js new file mode 100644 index 0000000..1b6b172 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/commands/get_more_command.js @@ -0,0 +1,88 @@ +var BaseCommand = require('./base_command').BaseCommand, + inherits = require('util').inherits, + binaryutils = require('../utils'); + +/** + Get More Document Command +**/ +var GetMoreCommand = exports.GetMoreCommand = function(db, collectionName, numberToReturn, cursorId) { + BaseCommand.call(this); + + this.collectionName = collectionName; + this.numberToReturn = numberToReturn; + this.cursorId = cursorId; + this.db = db; +}; + +inherits(GetMoreCommand, BaseCommand); + +GetMoreCommand.OP_GET_MORE = 2005; + +GetMoreCommand.prototype.toBinary = function() { + // Validate that we are not passing 0x00 in the colletion name + if(!!~this.collectionName.indexOf("\x00")) { + throw new Error("namespace cannot contain a null character"); + } + + // Calculate total length of the document + var totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + 4 + 8 + (4 * 4); + // Let's build the single pass buffer command + var _index = 0; + var _command = new Buffer(totalLengthOfCommand); + // Write the header information to the buffer + _command[_index++] = totalLengthOfCommand & 0xff; + _command[_index++] = (totalLengthOfCommand >> 8) & 0xff; + _command[_index++] = (totalLengthOfCommand >> 16) & 0xff; + _command[_index++] = (totalLengthOfCommand >> 24) & 0xff; + + // Write the request ID + _command[_index++] = this.requestId & 0xff; + _command[_index++] = (this.requestId >> 8) & 0xff; + _command[_index++] = (this.requestId >> 16) & 0xff; + _command[_index++] = (this.requestId >> 24) & 0xff; + + // Write zero + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + + // Write the op_code for the command + _command[_index++] = GetMoreCommand.OP_GET_MORE & 0xff; + _command[_index++] = (GetMoreCommand.OP_GET_MORE >> 8) & 0xff; + _command[_index++] = (GetMoreCommand.OP_GET_MORE >> 16) & 0xff; + _command[_index++] = (GetMoreCommand.OP_GET_MORE >> 24) & 0xff; + + // Write zero + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + + // Write the collection name to the command + _index = _index + _command.write(this.collectionName, _index, 'utf8') + 1; + _command[_index - 1] = 0; + + // Number of documents to return + _command[_index++] = this.numberToReturn & 0xff; + _command[_index++] = (this.numberToReturn >> 8) & 0xff; + _command[_index++] = (this.numberToReturn >> 16) & 0xff; + _command[_index++] = (this.numberToReturn >> 24) & 0xff; + + // Encode the cursor id + var low_bits = this.cursorId.getLowBits(); + // Encode low bits + _command[_index++] = low_bits & 0xff; + _command[_index++] = (low_bits >> 8) & 0xff; + _command[_index++] = (low_bits >> 16) & 0xff; + _command[_index++] = (low_bits >> 24) & 0xff; + + var high_bits = this.cursorId.getHighBits(); + // Encode high bits + _command[_index++] = high_bits & 0xff; + _command[_index++] = (high_bits >> 8) & 0xff; + _command[_index++] = (high_bits >> 16) & 0xff; + _command[_index++] = (high_bits >> 24) & 0xff; + // Return command + return _command; +}; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/commands/insert_command.js b/node_modules/mongodb/lib/mongodb/commands/insert_command.js new file mode 100644 index 0000000..c6e51e9 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/commands/insert_command.js @@ -0,0 +1,161 @@ +var BaseCommand = require('./base_command').BaseCommand, + inherits = require('util').inherits; + +/** + Insert Document Command +**/ +var InsertCommand = exports.InsertCommand = function(db, collectionName, checkKeys, options) { + BaseCommand.call(this); + + this.collectionName = collectionName; + this.documents = []; + this.checkKeys = checkKeys == null ? true : checkKeys; + this.db = db; + this.flags = 0; + this.serializeFunctions = false; + + // Ensure valid options hash + options = options == null ? {} : options; + + // Check if we have keepGoing set -> set flag if it's the case + if(options['keepGoing'] != null && options['keepGoing']) { + // This will finish inserting all non-index violating documents even if it returns an error + this.flags = 1; + } + + // Check if we have keepGoing set -> set flag if it's the case + if(options['continueOnError'] != null && options['continueOnError']) { + // This will finish inserting all non-index violating documents even if it returns an error + this.flags = 1; + } + + // Let us defined on a command basis if we want functions to be serialized or not + if(options['serializeFunctions'] != null && options['serializeFunctions']) { + this.serializeFunctions = true; + } +}; + +inherits(InsertCommand, BaseCommand); + +// OpCodes +InsertCommand.OP_INSERT = 2002; + +InsertCommand.prototype.add = function(document) { + if(Buffer.isBuffer(document)) { + var object_size = document[0] | document[1] << 8 | document[2] << 16 | document[3] << 24; + if(object_size != document.length) { + var error = new Error("insert raw message size does not match message header size [" + document.length + "] != [" + object_size + "]"); + error.name = 'MongoError'; + throw error; + } + } + + this.documents.push(document); + return this; +}; + +/* +struct { + MsgHeader header; // standard message header + int32 ZERO; // 0 - reserved for future use + cstring fullCollectionName; // "dbname.collectionname" + BSON[] documents; // one or more documents to insert into the collection +} +*/ +InsertCommand.prototype.toBinary = function(bsonSettings) { + // Validate that we are not passing 0x00 in the colletion name + if(!!~this.collectionName.indexOf("\x00")) { + throw new Error("namespace cannot contain a null character"); + } + + // Calculate total length of the document + var totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + (4 * 4); + // var docLength = 0 + for(var i = 0; i < this.documents.length; i++) { + if(Buffer.isBuffer(this.documents[i])) { + totalLengthOfCommand += this.documents[i].length; + } else { + // Calculate size of document + totalLengthOfCommand += this.db.bson.calculateObjectSize(this.documents[i], this.serializeFunctions, true); + } + } + + // Enforce maximum bson size + if(!bsonSettings.disableDriverBSONSizeCheck + && totalLengthOfCommand > bsonSettings.maxBsonSize) + throw new Error("Document exceeds maximum allowed bson size of " + bsonSettings.maxBsonSize + " bytes"); + + if(bsonSettings.disableDriverBSONSizeCheck + && totalLengthOfCommand > bsonSettings.maxMessageSizeBytes) + throw new Error("Command exceeds maximum message size of " + bsonSettings.maxMessageSizeBytes + " bytes"); + + // Let's build the single pass buffer command + var _index = 0; + var _command = new Buffer(totalLengthOfCommand); + // Write the header information to the buffer + _command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff; + _command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff; + _command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff; + _command[_index] = totalLengthOfCommand & 0xff; + // Adjust index + _index = _index + 4; + // Write the request ID + _command[_index + 3] = (this.requestId >> 24) & 0xff; + _command[_index + 2] = (this.requestId >> 16) & 0xff; + _command[_index + 1] = (this.requestId >> 8) & 0xff; + _command[_index] = this.requestId & 0xff; + // Adjust index + _index = _index + 4; + // Write zero + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + // Write the op_code for the command + _command[_index + 3] = (InsertCommand.OP_INSERT >> 24) & 0xff; + _command[_index + 2] = (InsertCommand.OP_INSERT >> 16) & 0xff; + _command[_index + 1] = (InsertCommand.OP_INSERT >> 8) & 0xff; + _command[_index] = InsertCommand.OP_INSERT & 0xff; + // Adjust index + _index = _index + 4; + // Write flags if any + _command[_index + 3] = (this.flags >> 24) & 0xff; + _command[_index + 2] = (this.flags >> 16) & 0xff; + _command[_index + 1] = (this.flags >> 8) & 0xff; + _command[_index] = this.flags & 0xff; + // Adjust index + _index = _index + 4; + // Write the collection name to the command + _index = _index + _command.write(this.collectionName, _index, 'utf8') + 1; + _command[_index - 1] = 0; + + // Write all the bson documents to the buffer at the index offset + for(var i = 0; i < this.documents.length; i++) { + // Document binary length + var documentLength = 0 + var object = this.documents[i]; + + // Serialize the selector + // If we are passing a raw buffer, do minimal validation + if(Buffer.isBuffer(object)) { + documentLength = object.length; + // Copy the data into the current buffer + object.copy(_command, _index); + } else { + // Serialize the document straight to the buffer + documentLength = this.db.bson.serializeWithBufferAndIndex(object, this.checkKeys, _command, _index, this.serializeFunctions) - _index + 1; + } + + // Write the length to the document + _command[_index + 3] = (documentLength >> 24) & 0xff; + _command[_index + 2] = (documentLength >> 16) & 0xff; + _command[_index + 1] = (documentLength >> 8) & 0xff; + _command[_index] = documentLength & 0xff; + // Update index in buffer + _index = _index + documentLength; + // Add terminating 0 for the object + _command[_index - 1] = 0; + } + + return _command; +}; diff --git a/node_modules/mongodb/lib/mongodb/commands/kill_cursor_command.js b/node_modules/mongodb/lib/mongodb/commands/kill_cursor_command.js new file mode 100644 index 0000000..d8ccb0c --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/commands/kill_cursor_command.js @@ -0,0 +1,98 @@ +var BaseCommand = require('./base_command').BaseCommand, + inherits = require('util').inherits, + binaryutils = require('../utils'); + +/** + Insert Document Command +**/ +var KillCursorCommand = exports.KillCursorCommand = function(db, cursorIds) { + BaseCommand.call(this); + + this.cursorIds = cursorIds; + this.db = db; +}; + +inherits(KillCursorCommand, BaseCommand); + +KillCursorCommand.OP_KILL_CURSORS = 2007; + +/* +struct { + MsgHeader header; // standard message header + int32 ZERO; // 0 - reserved for future use + int32 numberOfCursorIDs; // number of cursorIDs in message + int64[] cursorIDs; // array of cursorIDs to close +} +*/ +KillCursorCommand.prototype.toBinary = function() { + // Calculate total length of the document + var totalLengthOfCommand = 4 + 4 + (4 * 4) + (this.cursorIds.length * 8); + // Let's build the single pass buffer command + var _index = 0; + var _command = new Buffer(totalLengthOfCommand); + // Write the header information to the buffer + _command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff; + _command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff; + _command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff; + _command[_index] = totalLengthOfCommand & 0xff; + // Adjust index + _index = _index + 4; + // Write the request ID + _command[_index + 3] = (this.requestId >> 24) & 0xff; + _command[_index + 2] = (this.requestId >> 16) & 0xff; + _command[_index + 1] = (this.requestId >> 8) & 0xff; + _command[_index] = this.requestId & 0xff; + // Adjust index + _index = _index + 4; + // Write zero + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + // Write the op_code for the command + _command[_index + 3] = (KillCursorCommand.OP_KILL_CURSORS >> 24) & 0xff; + _command[_index + 2] = (KillCursorCommand.OP_KILL_CURSORS >> 16) & 0xff; + _command[_index + 1] = (KillCursorCommand.OP_KILL_CURSORS >> 8) & 0xff; + _command[_index] = KillCursorCommand.OP_KILL_CURSORS & 0xff; + // Adjust index + _index = _index + 4; + + // Write zero + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + + // Number of cursors to kill + var numberOfCursors = this.cursorIds.length; + _command[_index + 3] = (numberOfCursors >> 24) & 0xff; + _command[_index + 2] = (numberOfCursors >> 16) & 0xff; + _command[_index + 1] = (numberOfCursors >> 8) & 0xff; + _command[_index] = numberOfCursors & 0xff; + // Adjust index + _index = _index + 4; + + // Encode all the cursors + for(var i = 0; i < this.cursorIds.length; i++) { + // Encode the cursor id + var low_bits = this.cursorIds[i].getLowBits(); + // Encode low bits + _command[_index + 3] = (low_bits >> 24) & 0xff; + _command[_index + 2] = (low_bits >> 16) & 0xff; + _command[_index + 1] = (low_bits >> 8) & 0xff; + _command[_index] = low_bits & 0xff; + // Adjust index + _index = _index + 4; + + var high_bits = this.cursorIds[i].getHighBits(); + // Encode high bits + _command[_index + 3] = (high_bits >> 24) & 0xff; + _command[_index + 2] = (high_bits >> 16) & 0xff; + _command[_index + 1] = (high_bits >> 8) & 0xff; + _command[_index] = high_bits & 0xff; + // Adjust index + _index = _index + 4; + } + + return _command; +}; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/commands/query_command.js b/node_modules/mongodb/lib/mongodb/commands/query_command.js new file mode 100644 index 0000000..196c9f1 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/commands/query_command.js @@ -0,0 +1,296 @@ +var BaseCommand = require('./base_command').BaseCommand, + inherits = require('util').inherits; + +/** + Insert Document Command +**/ +var QueryCommand = exports.QueryCommand = function(db, collectionName, queryOptions, numberToSkip, numberToReturn, query, returnFieldSelector, options) { + BaseCommand.call(this); + + // Validate correctness off the selector + var object = query, + object_size; + if(Buffer.isBuffer(object)) { + object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24; + if(object_size != object.length) { + var error = new Error("query selector raw message size does not match message header size [" + object.length + "] != [" + object_size + "]"); + error.name = 'MongoError'; + throw error; + } + } + + object = returnFieldSelector; + if(Buffer.isBuffer(object)) { + object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24; + if(object_size != object.length) { + var error = new Error("query fields raw message size does not match message header size [" + object.length + "] != [" + object_size + "]"); + error.name = 'MongoError'; + throw error; + } + } + + // Make sure we don't get a null exception + options = options == null ? {} : options; + // Set up options + this.collectionName = collectionName; + this.queryOptions = queryOptions; + this.numberToSkip = numberToSkip; + this.numberToReturn = numberToReturn; + + // Ensure we have no null query + query = query == null ? {} : query; + // Wrap query in the $query parameter so we can add read preferences for mongos + this.query = query; + this.returnFieldSelector = returnFieldSelector; + this.db = db; + + // Force the slave ok flag to be set if we are not using primary read preference + if(this.db && this.db.slaveOk) { + this.queryOptions |= QueryCommand.OPTS_SLAVE; + } + + // If checkKeys set + this.checkKeys = typeof options.checkKeys == 'boolean' ? options.checkKeys : false; + + // Let us defined on a command basis if we want functions to be serialized or not + if(options['serializeFunctions'] != null && options['serializeFunctions']) { + this.serializeFunctions = true; + } +}; + +inherits(QueryCommand, BaseCommand); + +QueryCommand.OP_QUERY = 2004; + +/* + * Adds the read prefrence to the current command + */ +QueryCommand.prototype.setMongosReadPreference = function(readPreference, tags) { + // No read preference specified + if(readPreference == false) return; + // If we have readPreference set to true set to secondary prefered + if(readPreference == true) { + readPreference = 'secondaryPreferred'; + } else if(readPreference == 'false') { + readPreference = 'primary'; + } + + // If we have primary read preference ignore it + if(readPreference == 'primary' + || readPreference.mode == 'primary') return; + + // Force the slave ok flag to be set if we are not using primary read preference + if(readPreference != false && readPreference != 'primary') { + this.queryOptions |= QueryCommand.OPTS_SLAVE; + } + + // Backward compatibility, ensure $query only set on read preference so 1.8.X works + if((readPreference != null || tags != null) && this.query['$query'] == null) { + this.query = {'$query': this.query}; + } + + // If we have no readPreference set and no tags, check if the slaveOk bit is set + if(readPreference == null && tags == null) { + // If we have a slaveOk bit set the read preference for MongoS + if(this.queryOptions & QueryCommand.OPTS_SLAVE) { + this.query['$readPreference'] = {mode: 'secondary'} + } else { + this.query['$readPreference'] = {mode: 'primary'} + } + } + + // Build read preference object + if(typeof readPreference == 'object' && readPreference['_type'] == 'ReadPreference') { + this.query['$readPreference'] = readPreference.toObject(); + } else if(readPreference != null) { + // Add the read preference + this.query['$readPreference'] = {mode: readPreference}; + + // If we have tags let's add them + if(tags != null) { + this.query['$readPreference']['tags'] = tags; + } + } +} + +/* +struct { + MsgHeader header; // standard message header + int32 opts; // query options. See below for details. + cstring fullCollectionName; // "dbname.collectionname" + int32 numberToSkip; // number of documents to skip when returning results + int32 numberToReturn; // number of documents to return in the first OP_REPLY + BSON query ; // query object. See below for details. + [ BSON returnFieldSelector; ] // OPTIONAL : selector indicating the fields to return. See below for details. +} +*/ +QueryCommand.prototype.toBinary = function(bsonSettings) { + // Validate that we are not passing 0x00 in the colletion name + if(!!~this.collectionName.indexOf("\x00")) { + throw new Error("namespace cannot contain a null character"); + } + + // Total length of the command + var totalLengthOfCommand = 0; + // Calculate total length of the document + if(Buffer.isBuffer(this.query)) { + totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + 4 + 4 + this.query.length + (4 * 4); + } else { + totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + 4 + 4 + this.db.bson.calculateObjectSize(this.query, this.serializeFunctions, true) + (4 * 4); + } + + // Calculate extra fields size + if(this.returnFieldSelector != null && !(Buffer.isBuffer(this.returnFieldSelector))) { + if(Object.keys(this.returnFieldSelector).length > 0) { + totalLengthOfCommand += this.db.bson.calculateObjectSize(this.returnFieldSelector, this.serializeFunctions, true); + } + } else if(Buffer.isBuffer(this.returnFieldSelector)) { + totalLengthOfCommand += this.returnFieldSelector.length; + } + + // Enforce maximum bson size + if(!bsonSettings.disableDriverBSONSizeCheck + && totalLengthOfCommand > bsonSettings.maxBsonSize) + throw new Error("Document exceeds maximum allowed bson size of " + bsonSettings.maxBsonSize + " bytes"); + + if(bsonSettings.disableDriverBSONSizeCheck + && totalLengthOfCommand > bsonSettings.maxMessageSizeBytes) + throw new Error("Command exceeds maximum message size of " + bsonSettings.maxMessageSizeBytes + " bytes"); + + // Let's build the single pass buffer command + var _index = 0; + var _command = new Buffer(totalLengthOfCommand); + // Write the header information to the buffer + _command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff; + _command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff; + _command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff; + _command[_index] = totalLengthOfCommand & 0xff; + // Adjust index + _index = _index + 4; + // Write the request ID + _command[_index + 3] = (this.requestId >> 24) & 0xff; + _command[_index + 2] = (this.requestId >> 16) & 0xff; + _command[_index + 1] = (this.requestId >> 8) & 0xff; + _command[_index] = this.requestId & 0xff; + // Adjust index + _index = _index + 4; + // Write zero + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + // Write the op_code for the command + _command[_index + 3] = (QueryCommand.OP_QUERY >> 24) & 0xff; + _command[_index + 2] = (QueryCommand.OP_QUERY >> 16) & 0xff; + _command[_index + 1] = (QueryCommand.OP_QUERY >> 8) & 0xff; + _command[_index] = QueryCommand.OP_QUERY & 0xff; + // Adjust index + _index = _index + 4; + + // Write the query options + _command[_index + 3] = (this.queryOptions >> 24) & 0xff; + _command[_index + 2] = (this.queryOptions >> 16) & 0xff; + _command[_index + 1] = (this.queryOptions >> 8) & 0xff; + _command[_index] = this.queryOptions & 0xff; + // Adjust index + _index = _index + 4; + + // Write the collection name to the command + _index = _index + _command.write(this.collectionName, _index, 'utf8') + 1; + _command[_index - 1] = 0; + + // Write the number of documents to skip + _command[_index + 3] = (this.numberToSkip >> 24) & 0xff; + _command[_index + 2] = (this.numberToSkip >> 16) & 0xff; + _command[_index + 1] = (this.numberToSkip >> 8) & 0xff; + _command[_index] = this.numberToSkip & 0xff; + // Adjust index + _index = _index + 4; + + // Write the number of documents to return + _command[_index + 3] = (this.numberToReturn >> 24) & 0xff; + _command[_index + 2] = (this.numberToReturn >> 16) & 0xff; + _command[_index + 1] = (this.numberToReturn >> 8) & 0xff; + _command[_index] = this.numberToReturn & 0xff; + // Adjust index + _index = _index + 4; + + // Document binary length + var documentLength = 0 + var object = this.query; + + // Serialize the selector + if(Buffer.isBuffer(object)) { + documentLength = object.length; + // Copy the data into the current buffer + object.copy(_command, _index); + } else { + // If $query we need to check for a valid document + if(this.query['$query']) { + this.db.bson.serializeWithBufferAndIndex(object['$query'], this.checkKeys, _command, _index, this.serializeFunctions) - _index + 1; + // Cannot check keys due to $query + this.checkKeys = false; + } + + // Serialize the document straight to the buffer + documentLength = this.db.bson.serializeWithBufferAndIndex(object, this.checkKeys, _command, _index, this.serializeFunctions) - _index + 1; + } + + // Write the length to the document + _command[_index + 3] = (documentLength >> 24) & 0xff; + _command[_index + 2] = (documentLength >> 16) & 0xff; + _command[_index + 1] = (documentLength >> 8) & 0xff; + _command[_index] = documentLength & 0xff; + // Update index in buffer + _index = _index + documentLength; + // // Add terminating 0 for the object + _command[_index - 1] = 0; + + // Push field selector if available + if(this.returnFieldSelector != null && !(Buffer.isBuffer(this.returnFieldSelector))) { + if(Object.keys(this.returnFieldSelector).length > 0) { + var documentLength = this.db.bson.serializeWithBufferAndIndex(this.returnFieldSelector, this.checkKeys, _command, _index, this.serializeFunctions) - _index + 1; + // Write the length to the document + _command[_index + 3] = (documentLength >> 24) & 0xff; + _command[_index + 2] = (documentLength >> 16) & 0xff; + _command[_index + 1] = (documentLength >> 8) & 0xff; + _command[_index] = documentLength & 0xff; + // Update index in buffer + _index = _index + documentLength; + // Add terminating 0 for the object + _command[_index - 1] = 0; + } + } if(this.returnFieldSelector != null && Buffer.isBuffer(this.returnFieldSelector)) { + // Document binary length + var documentLength = 0 + var object = this.returnFieldSelector; + + // Serialize the selector + documentLength = object.length; + // Copy the data into the current buffer + object.copy(_command, _index); + + // Write the length to the document + _command[_index + 3] = (documentLength >> 24) & 0xff; + _command[_index + 2] = (documentLength >> 16) & 0xff; + _command[_index + 1] = (documentLength >> 8) & 0xff; + _command[_index] = documentLength & 0xff; + // Update index in buffer + _index = _index + documentLength; + // Add terminating 0 for the object + _command[_index - 1] = 0; + } + + // Return finished command + return _command; +}; + +// Constants +QueryCommand.OPTS_NONE = 0; +QueryCommand.OPTS_TAILABLE_CURSOR = 2; +QueryCommand.OPTS_SLAVE = 4; +QueryCommand.OPTS_OPLOG_REPLAY = 8; +QueryCommand.OPTS_NO_CURSOR_TIMEOUT = 16; +QueryCommand.OPTS_AWAIT_DATA = 32; +QueryCommand.OPTS_EXHAUST = 64; +QueryCommand.OPTS_PARTIAL = 128; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/commands/update_command.js b/node_modules/mongodb/lib/mongodb/commands/update_command.js new file mode 100644 index 0000000..daa3cba --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/commands/update_command.js @@ -0,0 +1,189 @@ +var BaseCommand = require('./base_command').BaseCommand, + inherits = require('util').inherits; + +/** + Update Document Command +**/ +var UpdateCommand = exports.UpdateCommand = function(db, collectionName, spec, document, options) { + BaseCommand.call(this); + + var object = spec; + if(Buffer.isBuffer(object)) { + var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24; + if(object_size != object.length) { + var error = new Error("update spec raw message size does not match message header size [" + object.length + "] != [" + object_size + "]"); + error.name = 'MongoError'; + throw error; + } + } + + var object = document; + if(Buffer.isBuffer(object)) { + var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24; + if(object_size != object.length) { + var error = new Error("update document raw message size does not match message header size [" + object.length + "] != [" + object_size + "]"); + error.name = 'MongoError'; + throw error; + } + } + + this.collectionName = collectionName; + this.spec = spec; + this.document = document; + this.db = db; + this.serializeFunctions = false; + this.checkKeys = typeof options.checkKeys != 'boolean' ? false : options.checkKeys; + + // Generate correct flags + var db_upsert = 0; + var db_multi_update = 0; + db_upsert = options != null && options['upsert'] != null ? (options['upsert'] == true ? 1 : 0) : db_upsert; + db_multi_update = options != null && options['multi'] != null ? (options['multi'] == true ? 1 : 0) : db_multi_update; + + // Flags + this.flags = parseInt(db_multi_update.toString() + db_upsert.toString(), 2); + // Let us defined on a command basis if we want functions to be serialized or not + if(options['serializeFunctions'] != null && options['serializeFunctions']) { + this.serializeFunctions = true; + } +}; + +inherits(UpdateCommand, BaseCommand); + +UpdateCommand.OP_UPDATE = 2001; + +/* +struct { + MsgHeader header; // standard message header + int32 ZERO; // 0 - reserved for future use + cstring fullCollectionName; // "dbname.collectionname" + int32 flags; // bit vector. see below + BSON spec; // the query to select the document + BSON document; // the document data to update with or insert +} +*/ +UpdateCommand.prototype.toBinary = function(bsonSettings) { + // Validate that we are not passing 0x00 in the colletion name + if(!!~this.collectionName.indexOf("\x00")) { + throw new Error("namespace cannot contain a null character"); + } + + // Calculate total length of the document + var totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + 4 + this.db.bson.calculateObjectSize(this.spec, false, true) + + this.db.bson.calculateObjectSize(this.document, this.serializeFunctions, true) + (4 * 4); + + // Enforce maximum bson size + if(!bsonSettings.disableDriverBSONSizeCheck + && totalLengthOfCommand > bsonSettings.maxBsonSize) + throw new Error("Document exceeds maximum allowed bson size of " + bsonSettings.maxBsonSize + " bytes"); + + if(bsonSettings.disableDriverBSONSizeCheck + && totalLengthOfCommand > bsonSettings.maxMessageSizeBytes) + throw new Error("Command exceeds maximum message size of " + bsonSettings.maxMessageSizeBytes + " bytes"); + + // Let's build the single pass buffer command + var _index = 0; + var _command = new Buffer(totalLengthOfCommand); + // Write the header information to the buffer + _command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff; + _command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff; + _command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff; + _command[_index] = totalLengthOfCommand & 0xff; + // Adjust index + _index = _index + 4; + // Write the request ID + _command[_index + 3] = (this.requestId >> 24) & 0xff; + _command[_index + 2] = (this.requestId >> 16) & 0xff; + _command[_index + 1] = (this.requestId >> 8) & 0xff; + _command[_index] = this.requestId & 0xff; + // Adjust index + _index = _index + 4; + // Write zero + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + // Write the op_code for the command + _command[_index + 3] = (UpdateCommand.OP_UPDATE >> 24) & 0xff; + _command[_index + 2] = (UpdateCommand.OP_UPDATE >> 16) & 0xff; + _command[_index + 1] = (UpdateCommand.OP_UPDATE >> 8) & 0xff; + _command[_index] = UpdateCommand.OP_UPDATE & 0xff; + // Adjust index + _index = _index + 4; + + // Write zero + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + _command[_index++] = 0; + + // Write the collection name to the command + _index = _index + _command.write(this.collectionName, _index, 'utf8') + 1; + _command[_index - 1] = 0; + + // Write the update flags + _command[_index + 3] = (this.flags >> 24) & 0xff; + _command[_index + 2] = (this.flags >> 16) & 0xff; + _command[_index + 1] = (this.flags >> 8) & 0xff; + _command[_index] = this.flags & 0xff; + // Adjust index + _index = _index + 4; + + // Document binary length + var documentLength = 0 + var object = this.spec; + + // Serialize the selector + // If we are passing a raw buffer, do minimal validation + if(Buffer.isBuffer(object)) { + var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24; + if(object_size != object.length) throw new Error("raw message size does not match message header size [" + object.length + "] != [" + object_size + "]"); + documentLength = object.length; + // Copy the data into the current buffer + object.copy(_command, _index); + } else { + documentLength = this.db.bson.serializeWithBufferAndIndex(object, this.checkKeys, _command, _index, false) - _index + 1; + } + + // Write the length to the document + _command[_index + 3] = (documentLength >> 24) & 0xff; + _command[_index + 2] = (documentLength >> 16) & 0xff; + _command[_index + 1] = (documentLength >> 8) & 0xff; + _command[_index] = documentLength & 0xff; + // Update index in buffer + _index = _index + documentLength; + // Add terminating 0 for the object + _command[_index - 1] = 0; + + // Document binary length + var documentLength = 0 + var object = this.document; + + // Serialize the document + // If we are passing a raw buffer, do minimal validation + if(Buffer.isBuffer(object)) { + var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24; + if(object_size != object.length) throw new Error("raw message size does not match message header size [" + object.length + "] != [" + object_size + "]"); + documentLength = object.length; + // Copy the data into the current buffer + object.copy(_command, _index); + } else { + documentLength = this.db.bson.serializeWithBufferAndIndex(object, false, _command, _index, this.serializeFunctions) - _index + 1; + } + + // Write the length to the document + _command[_index + 3] = (documentLength >> 24) & 0xff; + _command[_index + 2] = (documentLength >> 16) & 0xff; + _command[_index + 1] = (documentLength >> 8) & 0xff; + _command[_index] = documentLength & 0xff; + // Update index in buffer + _index = _index + documentLength; + // Add terminating 0 for the object + _command[_index - 1] = 0; + + return _command; +}; + +// Constants +UpdateCommand.DB_UPSERT = 0; +UpdateCommand.DB_MULTI_UPDATE = 1; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/connection/base.js b/node_modules/mongodb/lib/mongodb/connection/base.js new file mode 100644 index 0000000..b8c1343 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/connection/base.js @@ -0,0 +1,515 @@ +var EventEmitter = require('events').EventEmitter + , inherits = require('util').inherits + , utils = require('../utils') + , mongodb_cr_authenticate = require('../auth/mongodb_cr.js').authenticate + , mongodb_gssapi_authenticate = require('../auth/mongodb_gssapi.js').authenticate + , mongodb_sspi_authenticate = require('../auth/mongodb_sspi.js').authenticate + , mongodb_plain_authenticate = require('../auth/mongodb_plain.js').authenticate + , mongodb_x509_authenticate = require('../auth/mongodb_x509.js').authenticate + , mongodb_scram_authenticate = require('../auth/mongodb_scram.js').authenticate; + +var id = 0; + +/** + * Internal class for callback storage + * @ignore + */ +var CallbackStore = function() { + // Make class an event emitter + EventEmitter.call(this); + // Add a info about call variable + this._notReplied = {}; + this.id = id++; +} + +/** + * @ignore + */ +inherits(CallbackStore, EventEmitter); + +CallbackStore.prototype.notRepliedToIds = function() { + return Object.keys(this._notReplied); +} + +CallbackStore.prototype.callbackInfo = function(id) { + return this._notReplied[id]; +} + +/** + * Internal class for holding non-executed commands + * @ignore + */ +var NonExecutedOperationStore = function(config) { + var commands = { + read: [] + , write_reads: [] + , write: [] + }; + + // Execute all callbacks + var fireCallbacksWithError = function(error, commands) { + while(commands.length > 0) { + var command = commands.shift(); + if(typeof command.callback == 'function') { + command.callback(error); + } + } + } + + this.count = function() { + return commands.read.length + + commands.write_reads.length + + commands.write.length; + } + + this.write = function(op) { + commands.write.push(op); + } + + this.read_from_writer = function(op) { + commands.write_reads.push(op); + } + + this.read = function(op) { + commands.read.push(op); + } + + this.validateBufferLimit = function(numberToFailOn) { + if(numberToFailOn == -1 || numberToFailOn == null) + return true; + + // Error passed back + var error = utils.toError("No connection operations buffering limit of " + numberToFailOn + " reached"); + + // If we have passed the number of items to buffer we need to fail + if(numberToFailOn < this.count()) { + // Fail all of the callbacks + fireCallbacksWithError(error, commands.read); + fireCallbacksWithError(error, commands.write_reads); + fireCallbacksWithError(error, commands.write); + + // Report back that the buffer has been filled + return false; + } + + // There is still some room to go + return true; + } + + this.execute_queries = function(executeInsertCommand) { + var connection = config.checkoutReader(); + if(connection == null || connection instanceof Error) return; + + // Write out all the queries + while(commands.read.length > 0) { + // Get the next command + var command = commands.read.shift(); + command.options.connection = connection; + // Execute the next command + command.executeQueryCommand(command.db, command.db_command, command.options, command.callback); + } + } + + this.execute_writes = function() { + var connection = config.checkoutWriter(); + if(connection == null || connection instanceof Error) return; + + // Write out all the queries to the primary + while(commands.write_reads.length > 0) { + // Get the next command + var command = commands.write_reads.shift(); + command.options.connection = connection; + // Execute the next command + command.executeQueryCommand(command.db, command.db_command, command.options, command.callback); + } + + // Execute all write operations + while(commands.write.length > 0) { + // Get the next command + var command = commands.write.shift(); + // Set the connection + command.options.connection = connection; + // Execute the next command + command.executeInsertCommand(command.db, command.db_command, command.options, command.callback); + } + } +} + +/** + * Internal class for authentication storage + * @ignore + */ +var AuthStore = function() { + var _auths = []; + + this.add = function(authMechanism, dbName, username, password, authdbName, gssapiServiceName) { + // Check for duplicates + if(!this.contains(dbName)) { + // Base config + var config = { + 'username':username + , 'password':password + , 'db': dbName + , 'authMechanism': authMechanism + , 'gssapiServiceName': gssapiServiceName + }; + + // Add auth source if passed in + if(typeof authdbName == 'string') { + config['authdb'] = authdbName; + } + + // Push the config + _auths.push(config); + } + } + + this.contains = function(dbName) { + for(var i = 0; i < _auths.length; i++) { + if(_auths[i].db == dbName) return true; + } + + return false; + } + + this.remove = function(dbName) { + var newAuths = []; + + // Filter out all the login details + for(var i = 0; i < _auths.length; i++) { + if(_auths[i].db != dbName) newAuths.push(_auths[i]); + } + + // Set the filtered list + _auths = newAuths; + } + + this.get = function(index) { + return _auths[index]; + } + + this.length = function() { + return _auths.length; + } + + this.toArray = function() { + return _auths.slice(0); + } +} + +/** + * Internal class for storing db references + * @ignore + */ +var DbStore = function() { + var _dbs = []; + + this.add = function(db) { + var found = false; + + // Only add if it does not exist already + for(var i = 0; i < _dbs.length; i++) { + if(db.databaseName == _dbs[i].databaseName) found = true; + } + + // Only add if it does not already exist + if(!found) { + _dbs.push(db); + } + } + + this.reset = function() { + _dbs = []; + } + + this.db = function() { + return _dbs; + } + + this.fetch = function(databaseName) { + // Only add if it does not exist already + for(var i = 0; i < _dbs.length; i++) { + if(databaseName == _dbs[i].databaseName) + return _dbs[i]; + } + + return null; + } + + this.emit = function(event, message, object, reset, filterDb, rethrow_if_no_listeners) { + var emitted = false; + + // Not emitted and we have enabled rethrow, let process.uncaughtException + // deal with the issue + if(!emitted && rethrow_if_no_listeners) { + return process.nextTick(function() { + throw message; + }) + } + + // Emit the events + for(var i = 0; i < _dbs.length; i++) { + if(_dbs[i].listeners(event).length > 0) { + if(filterDb == null || filterDb.databaseName !== _dbs[i].databaseName + || filterDb.tag !== _dbs[i].tag) { + _dbs[i].emit(event, message, object == null ? _dbs[i] : object); + emitted = true; + } + } + } + + // Emit error message + if(message + && event == 'error' + && !emitted + && rethrow_if_no_listeners + && object && object.db) { + process.nextTick(function() { + object.db.emit(event, message, null); + }) + } + } +} + +var Base = function Base() { + EventEmitter.call(this); + + // Callback store is part of connection specification + if(Base._callBackStore == null) { + Base._callBackStore = new CallbackStore(); + } + + // Create a new auth store + var auth = new AuthStore(); + + Object.defineProperty(this, "auth", {enumerable: true + , get: function() { return auth; } + }); + + // Create a new callback store + this._callBackStore = new CallbackStore(); + // All commands not being executed + this._commandsStore = new NonExecutedOperationStore(this); + // Contains all the dbs attached to this server config + this._dbStore = new DbStore(); +} + +/** + * @ignore + */ +inherits(Base, EventEmitter); + +/** + * @ignore + */ +Base.prototype._apply_auths = function(db, callback) { + _apply_auths_serially(this, db, this.auth.toArray(), callback); +} + +var _apply_auths_serially = function(self, db, auths, callback) { + if(auths.length == 0) return callback(null, null); + // Get the first auth + var auth = auths.shift(); + var connections = self.allRawConnections(); + var connectionsLeft = connections.length; + var options = {}; + + if(auth.authMechanism == 'GSSAPI') { + // We have the kerberos library, execute auth process + if(process.platform == 'win32') { + mongodb_sspi_authenticate(db, auth.username, auth.password, auth.authdb, options, callback); + } else { + mongodb_gssapi_authenticate(db, auth.username, auth.password, auth.authdb, options, callback); + } + } else if(auth.authMechanism == 'MONGODB-CR') { + mongodb_cr_authenticate(db, auth.username, auth.password, auth.authdb, options, callback); + } else if(auth.authMechanism == 'SCRAM-SHA-1') { + mongodb_scram_authenticate(db, auth.username, auth.password, auth.authdb, options, callback); + } else if(auth.authMechanism == 'PLAIN') { + mongodb_plain_authenticate(db, auth.username, auth.password, options, callback); + } else if(auth.authMechanism == 'MONGODB-X509') { + mongodb_x509_authenticate(db, auth.username, auth.password, options, callback); + } +} + +/** + * Fire all the errors + * @ignore + */ +Base.prototype.__executeAllCallbacksWithError = function(err) { + // Check all callbacks + var keys = Object.keys(this._callBackStore._notReplied); + // For each key check if it's a callback that needs to be returned + for(var j = 0; j < keys.length; j++) { + var info = this._callBackStore._notReplied[keys[j]]; + // Execute callback with error + this._callBackStore.emit(keys[j], err, null); + // Remove the key + delete this._callBackStore._notReplied[keys[j]]; + // Force cleanup _events, node.js seems to set it as a null value + if(this._callBackStore._events) { + delete this._callBackStore._events[keys[j]]; + } + } +} + +/** + * Fire all the errors + * @ignore + */ +Base.prototype.__executeAllServerSpecificErrorCallbacks = function(host, port, err) { + // Check all callbacks + var keys = Object.keys(this._callBackStore._notReplied); + // For each key check if it's a callback that needs to be returned + for(var j = 0; j < keys.length; j++) { + var info = this._callBackStore._notReplied[keys[j]]; + + if(info && info.connection) { + // Unpack the connection settings + var _host = info.connection.socketOptions.host; + var _port = info.connection.socketOptions.port; + // If the server matches execute the callback with the error + if(_port == port && _host == host) { + this._callBackStore.emit(keys[j], err, null); + // Remove the key + delete this._callBackStore._notReplied[keys[j]]; + // Force cleanup _events, node.js seems to set it as a null value + if(this._callBackStore._events) { + delete this._callBackStore._events[keys[j]]; + } + } + } + } +} + +/** + * Register a handler + * @ignore + * @api private + */ +Base.prototype._registerHandler = function(db_command, raw, connection, exhaust, callback) { + // Check if we have exhausted + if(typeof exhaust == 'function') { + callback = exhaust; + exhaust = false; + } + + // Add the callback to the list of handlers + this._callBackStore.once(db_command.getRequestId(), callback); + // Add the information about the reply + this._callBackStore._notReplied[db_command.getRequestId().toString()] = {start: new Date().getTime(), 'raw': raw, connection:connection, exhaust:exhaust}; +} + +/** + * Re-Register a handler, on the cursor id f.ex + * @ignore + * @api private + */ +Base.prototype._reRegisterHandler = function(newId, object, callback) { + // Add the callback to the list of handlers + this._callBackStore.once(newId, object.callback.listener); + // Add the information about the reply + this._callBackStore._notReplied[newId] = object.info; +} + +/** + * + * @ignore + * @api private + */ +Base.prototype._flushAllCallHandlers = function(err) { + var keys = Object.keys(this._callBackStore._notReplied); + + for(var i = 0; i < keys.length; i++) { + this._callHandler(keys[i], null, err); + } +} + +/** + * + * @ignore + * @api private + */ +Base.prototype._callHandler = function(id, document, err) { + var self = this; + + // If there is a callback peform it + if(this._callBackStore.listeners(id).length >= 1) { + // Get info object + var info = this._callBackStore._notReplied[id]; + // Delete the current object + delete this._callBackStore._notReplied[id]; + // Call the handle directly don't emit + var callback = this._callBackStore.listeners(id)[0].listener; + // Remove the listeners + this._callBackStore.removeAllListeners(id); + // Force key deletion because it nulling it not deleting in 0.10.X + if(this._callBackStore._events) { + delete this._callBackStore._events[id]; + } + + try { + // Execute the callback if one was provided + if(typeof callback == 'function') callback(err, document, info.connection); + } catch(err) { + self._emitAcrossAllDbInstances(self, null, "error", utils.toError(err), self, true, true); + } + } +} + +/** + * + * @ignore + * @api private + */ +Base.prototype._hasHandler = function(id) { + return this._callBackStore.listeners(id).length >= 1; +} + +/** + * + * @ignore + * @api private + */ +Base.prototype._removeHandler = function(id) { + // Remove the information + if(this._callBackStore._notReplied[id] != null) delete this._callBackStore._notReplied[id]; + // Remove the callback if it's registered + this._callBackStore.removeAllListeners(id); + // Force cleanup _events, node.js seems to set it as a null value + if(this._callBackStore._events) { + delete this._callBackStore._events[id]; + } +} + +/** + * + * @ignore + * @api private + */ +Base.prototype._findHandler = function(id) { + var info = this._callBackStore._notReplied[id]; + // Return the callback + return {info:info, callback:(this._callBackStore.listeners(id).length >= 1) ? this._callBackStore.listeners(id)[0] : null} +} + +/** + * + * @ignore + * @api private + */ +Base.prototype._emitAcrossAllDbInstances = function(server, filterDb, event, message, object, resetConnection, rethrow_if_no_listeners) { + if(resetConnection) { + var dbs = this._dbStore.db(); + + for(var i = 0; i < dbs.length; i++) { + if(typeof dbs[i].openCalled != 'undefined') + dbs[i].openCalled = false; + } + } + + // Fire event + this._dbStore.emit(event, message, object, resetConnection, filterDb, rethrow_if_no_listeners); +} + +exports.Base = Base; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/connection/connection.js b/node_modules/mongodb/lib/mongodb/connection/connection.js new file mode 100644 index 0000000..d1e4835 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/connection/connection.js @@ -0,0 +1,563 @@ +var utils = require('./connection_utils'), + inherits = require('util').inherits, + net = require('net'), + EventEmitter = require('events').EventEmitter, + inherits = require('util').inherits, + binaryutils = require('../utils'), + tls = require('tls'); + +var Connection = exports.Connection = function(id, socketOptions) { + var self = this; + // Set up event emitter + EventEmitter.call(this); + // Store all socket options + this.socketOptions = socketOptions ? socketOptions : {host:'localhost', port:27017, domainSocket:false}; + // Set keep alive default if not overriden + if(this.socketOptions.keepAlive == null && (process.platform !== "sunos" || process.platform !== "win32")) this.socketOptions.keepAlive = 100; + // Id for the connection + this.id = id; + // State of the connection + this.connected = false; + // Set if this is a domain socket + this.domainSocket = this.socketOptions.domainSocket; + + // Supported min and max wire protocol + this.minWireVersion = 0; + this.maxWireVersion = 3; + + // + // Connection parsing state + // + this.maxBsonSize = socketOptions.maxBsonSize ? socketOptions.maxBsonSize : Connection.DEFAULT_MAX_BSON_SIZE; + this.maxMessageSizeBytes = socketOptions.maxMessageSizeBytes ? socketOptions.maxMessageSizeBytes : Connection.DEFAULT_MAX_MESSAGE_SIZE; + this.maxNumberOfDocsInBatch = socketOptions.maxWriteBatchSize ? socketOptions.maxWriteBatchSize : Connection.DEFAULT_MAX_WRITE_BATCH_SIZE; + // Contains the current message bytes + this.buffer = null; + // Contains the current message size + this.sizeOfMessage = 0; + // Contains the readIndex for the messaage + this.bytesRead = 0; + // Contains spill over bytes from additional messages + this.stubBuffer = 0; + + // Just keeps list of events we allow + this.eventHandlers = {error:[], parseError:[], poolReady:[], message:[], close:[], timeout:[], end:[]}; + + // Just keeps list of events we allow + resetHandlers(this, false); + + // Bson object + this.maxBsonSettings = { + disableDriverBSONSizeCheck: this.socketOptions['disableDriverBSONSizeCheck'] || false + , maxBsonSize: this.maxBsonSize + , maxMessageSizeBytes: this.maxMessageSizeBytes + } + + // Allow setting the socketTimeoutMS on all connections + // to work around issues such as secondaries blocking due to compaction + Object.defineProperty(this, "socketTimeoutMS", { + enumerable: true + , get: function () { return self.socketOptions.socketTimeoutMS; } + , set: function (value) { + // Set the socket timeoutMS value + self.socketOptions.socketTimeoutMS = value; + // Set the physical connection timeout + self.connection.setTimeout(self.socketOptions.socketTimeoutMS); + } + }); +} + +// Set max bson size +Connection.DEFAULT_MAX_BSON_SIZE = 1024 * 1024 * 4; +// Set default to max bson to avoid overflow or bad guesses +Connection.DEFAULT_MAX_MESSAGE_SIZE = Connection.DEFAULT_MAX_BSON_SIZE; +// Max default write bulk ops +Connection.DEFAULT_MAX_WRITE_BATCH_SIZE = 2000; + +// Inherit event emitter so we can emit stuff wohoo +inherits(Connection, EventEmitter); + +Connection.prototype.start = function() { + var self = this; + + // If we have a normal connection + if(this.socketOptions.ssl) { + // Create new connection instance + if(this.domainSocket) { + this.connection = net.createConnection(this.socketOptions.host); + } else { + this.connection = net.createConnection(this.socketOptions.port, this.socketOptions.host); + } + if(this.logger != null && this.logger.doDebug){ + this.logger.debug("opened connection", this.socketOptions); + } + + // Set options on the socket + this.connection.setTimeout(this.socketOptions.connectTimeoutMS != null ? this.socketOptions.connectTimeoutMS : this.socketOptions.timeout); + // Work around for 0.4.X + if(process.version.indexOf("v0.4") == -1) this.connection.setNoDelay(this.socketOptions.noDelay); + // Set keep alive if defined + if(process.version.indexOf("v0.4") == -1) { + if(this.socketOptions.keepAlive > 0) { + this.connection.setKeepAlive(true, this.socketOptions.keepAlive); + } else { + this.connection.setKeepAlive(false); + } + } + + // Check if the driver should validate the certificate + var validate_certificates = this.socketOptions.sslValidate == true ? true : false; + + // Create options for the tls connection + var tls_options = { + socket: this.connection + , rejectUnauthorized: false + } + + // If we wish to validate the certificate we have provided a ca store + if(validate_certificates) { + tls_options.ca = this.socketOptions.sslCA; + } + + // If we have a certificate to present + if(this.socketOptions.sslCert) { + tls_options.cert = this.socketOptions.sslCert; + tls_options.key = this.socketOptions.sslKey; + } + + // If the driver has been provided a private key password + if(this.socketOptions.sslPass) { + tls_options.passphrase = this.socketOptions.sslPass; + } + + // Contains the cleartext stream + var cleartext = null; + // Attempt to establish a TLS connection to the server + try { + cleartext = tls.connect(this.socketOptions.port, this.socketOptions.host, tls_options, function() { + // If we have a ssl certificate validation error return an error + if(cleartext.authorizationError && validate_certificates) { + // Emit an error + return self.emit("error", cleartext.authorizationError, self, {ssl:true}); + } + + // Connect to the server + connectHandler(self)(); + }) + } catch(err) { + return self.emit("error", "SSL connection failed", self, {ssl:true}); + } + + // Save the output stream + this.writeSteam = cleartext; + + // Set up data handler for the clear stream + cleartext.on("data", createDataHandler(this)); + // Do any handling of end event of the stream + cleartext.on("end", endHandler(this)); + cleartext.on("error", errorHandler(this)); + + // Handle any errors + this.connection.on("error", errorHandler(this)); + // Handle timeout + this.connection.on("timeout", timeoutHandler(this)); + // Handle drain event + this.connection.on("drain", drainHandler(this)); + // Handle the close event + this.connection.on("close", closeHandler(this)); + } else { + // Create new connection instance + if(this.domainSocket) { + this.connection = net.createConnection(this.socketOptions.host); + } else { + this.connection = net.createConnection(this.socketOptions.port, this.socketOptions.host); + } + if(this.logger != null && this.logger.doDebug){ + this.logger.debug("opened connection", this.socketOptions); + } + + // Set options on the socket + this.connection.setTimeout(this.socketOptions.connectTimeoutMS != null ? this.socketOptions.connectTimeoutMS : this.socketOptions.timeout); + // Work around for 0.4.X + if(process.version.indexOf("v0.4") == -1) this.connection.setNoDelay(this.socketOptions.noDelay); + // Set keep alive if defined + if(process.version.indexOf("v0.4") == -1) { + if(this.socketOptions.keepAlive > 0) { + this.connection.setKeepAlive(true, this.socketOptions.keepAlive); + } else { + this.connection.setKeepAlive(false); + } + } + + // Set up write stream + this.writeSteam = this.connection; + // Add handlers + this.connection.on("error", errorHandler(this)); + // Add all handlers to the socket to manage it + this.connection.on("connect", connectHandler(this)); + // this.connection.on("end", endHandler(this)); + this.connection.on("data", createDataHandler(this)); + this.connection.on("timeout", timeoutHandler(this)); + this.connection.on("drain", drainHandler(this)); + this.connection.on("close", closeHandler(this)); + } +} + +/** + * @ignore + */ +Connection.prototype.setSocketOptions = function(options) { + options = options || {}; + + if(typeof options.connectTimeoutMS == 'number') { + this.socketOptions.connectTimeoutMS = options.connectTimeoutMS; + } + + if(typeof options.socketTimeoutMS == 'number') { + this.socketOptions.socketTimeoutMS = options.socketTimeoutMS; + // Set the current socket timeout + this.connection.setTimeout(options.socketTimeoutMS); + } +} + +// Check if the sockets are live +Connection.prototype.isConnected = function() { + return this.connected && !this.connection.destroyed && this.connection.writable; +} + +// Validate if the driver supports this server +Connection.prototype.isCompatible = function() { + if(this.serverCapabilities == null) return true; + + // Is compatible with backward server + if(this.serverCapabilities.minWireVersion == 0 + && this.serverCapabilities.maxWireVersion ==0) return true; + + // Check if we overlap + if(this.serverCapabilities.minWireVersion >= this.minWireVersion + && this.serverCapabilities.maxWireVersion <= this.maxWireVersion) return true; + + // Not compatible + return false; +} + +// Write the data out to the socket +Connection.prototype.write = function(command, callback) { + try { + // If we have a list off commands to be executed on the same socket + if(Array.isArray(command)) { + for(var i = 0; i < command.length; i++) { + try { + // Pass in the bson validation settings (validate early) + var binaryCommand = command[i].toBinary(this.maxBsonSettings); + + if(this.logger != null && this.logger.doDebug) + this.logger.debug("writing command to mongodb", {binary: binaryCommand, json: command[i]}); + + this.writeSteam.write(binaryCommand); + } catch(err) { + return callback(err, null); + } + } + } else { + try { + // Pass in the bson validation settings (validate early) + var binaryCommand = command.toBinary(this.maxBsonSettings); + // Do we have a logger active log the event + if(this.logger != null && this.logger.doDebug) + this.logger.debug("writing command to mongodb", {binary: binaryCommand, json: command}); + // Write the binary command out to socket + this.writeSteam.write(binaryCommand); + } catch(err) { + return callback(err, null); + } + } + } catch (err) { + if(typeof callback === 'function') callback(err); + } +} + +// Force the closure of the connection +Connection.prototype.close = function() { + // clear out all the listeners + resetHandlers(this, true); + // Add a dummy error listener to catch any weird last moment errors (and ignore them) + this.connection.on("error", function() {}) + // destroy connection + this.connection.destroy(); + if(this.logger != null && this.logger.doDebug){ + this.logger.debug("closed connection", this.connection); + } +} + +// Reset all handlers +var resetHandlers = function(self, clearListeners) { + self.eventHandlers = {error:[], connect:[], close:[], end:[], timeout:[], parseError:[], message:[]}; + + // If we want to clear all the listeners + if(clearListeners && self.connection != null) { + var keys = Object.keys(self.eventHandlers); + // Remove all listeners + for(var i = 0; i < keys.length; i++) { + self.connection.removeAllListeners(keys[i]); + } + } +} + +// +// Handlers +// + +// Connect handler +var connectHandler = function(self) { + return function(data) { + // Set connected + self.connected = true; + // Now that we are connected set the socket timeout + self.connection.setTimeout(self.socketOptions.socketTimeoutMS != null ? self.socketOptions.socketTimeoutMS : self.socketOptions.timeout); + // Emit the connect event with no error + self.emit("connect", null, self); + } +} + +var createDataHandler = exports.Connection.createDataHandler = function(self) { + // We need to handle the parsing of the data + // and emit the messages when there is a complete one + return function(data) { + // Parse until we are done with the data + while(data.length > 0) { + // If we still have bytes to read on the current message + if(self.bytesRead > 0 && self.sizeOfMessage > 0) { + // Calculate the amount of remaining bytes + var remainingBytesToRead = self.sizeOfMessage - self.bytesRead; + // Check if the current chunk contains the rest of the message + if(remainingBytesToRead > data.length) { + // Copy the new data into the exiting buffer (should have been allocated when we know the message size) + data.copy(self.buffer, self.bytesRead); + // Adjust the number of bytes read so it point to the correct index in the buffer + self.bytesRead = self.bytesRead + data.length; + + // Reset state of buffer + data = new Buffer(0); + } else { + // Copy the missing part of the data into our current buffer + data.copy(self.buffer, self.bytesRead, 0, remainingBytesToRead); + // Slice the overflow into a new buffer that we will then re-parse + data = data.slice(remainingBytesToRead); + + // Emit current complete message + try { + var emitBuffer = self.buffer; + // Reset state of buffer + self.buffer = null; + self.sizeOfMessage = 0; + self.bytesRead = 0; + self.stubBuffer = null; + // Emit the buffer + self.emit("message", emitBuffer, self); + } catch(err) { + var errorObject = {err:"socketHandler", trace:err, bin:self.buffer, parseState:{ + sizeOfMessage:self.sizeOfMessage, + bytesRead:self.bytesRead, + stubBuffer:self.stubBuffer}}; + if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject); + // We got a parse Error fire it off then keep going + self.emit("parseError", errorObject, self); + } + } + } else { + // Stub buffer is kept in case we don't get enough bytes to determine the + // size of the message (< 4 bytes) + if(self.stubBuffer != null && self.stubBuffer.length > 0) { + + // If we have enough bytes to determine the message size let's do it + if(self.stubBuffer.length + data.length > 4) { + // Prepad the data + var newData = new Buffer(self.stubBuffer.length + data.length); + self.stubBuffer.copy(newData, 0); + data.copy(newData, self.stubBuffer.length); + // Reassign for parsing + data = newData; + + // Reset state of buffer + self.buffer = null; + self.sizeOfMessage = 0; + self.bytesRead = 0; + self.stubBuffer = null; + + } else { + + // Add the the bytes to the stub buffer + var newStubBuffer = new Buffer(self.stubBuffer.length + data.length); + // Copy existing stub buffer + self.stubBuffer.copy(newStubBuffer, 0); + // Copy missing part of the data + data.copy(newStubBuffer, self.stubBuffer.length); + // Exit parsing loop + data = new Buffer(0); + } + } else { + if(data.length > 4) { + // Retrieve the message size + var sizeOfMessage = binaryutils.decodeUInt32(data, 0); + // If we have a negative sizeOfMessage emit error and return + if(sizeOfMessage < 0 || sizeOfMessage > self.maxMessageSizeBytes) { + var errorObject = {err:"socketHandler", trace:'', bin:self.buffer, parseState:{ + sizeOfMessage: sizeOfMessage, + bytesRead: self.bytesRead, + stubBuffer: self.stubBuffer}}; + if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject); + // We got a parse Error fire it off then keep going + self.emit("parseError", errorObject, self); + return; + } + + // Ensure that the size of message is larger than 0 and less than the max allowed + if(sizeOfMessage > 4 && sizeOfMessage < self.maxMessageSizeBytes && sizeOfMessage > data.length) { + self.buffer = new Buffer(sizeOfMessage); + // Copy all the data into the buffer + data.copy(self.buffer, 0); + // Update bytes read + self.bytesRead = data.length; + // Update sizeOfMessage + self.sizeOfMessage = sizeOfMessage; + // Ensure stub buffer is null + self.stubBuffer = null; + // Exit parsing loop + data = new Buffer(0); + + } else if(sizeOfMessage > 4 && sizeOfMessage < self.maxMessageSizeBytes && sizeOfMessage == data.length) { + try { + var emitBuffer = data; + // Reset state of buffer + self.buffer = null; + self.sizeOfMessage = 0; + self.bytesRead = 0; + self.stubBuffer = null; + // Exit parsing loop + data = new Buffer(0); + // Emit the message + self.emit("message", emitBuffer, self); + } catch (err) { + var errorObject = {err:"socketHandler", trace:err, bin:self.buffer, parseState:{ + sizeOfMessage:self.sizeOfMessage, + bytesRead:self.bytesRead, + stubBuffer:self.stubBuffer}}; + if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject); + // We got a parse Error fire it off then keep going + self.emit("parseError", errorObject, self); + } + } else if(sizeOfMessage <= 4 || sizeOfMessage > self.maxMessageSizeBytes) { + var errorObject = {err:"socketHandler", trace:null, bin:data, parseState:{ + sizeOfMessage:sizeOfMessage, + bytesRead:0, + buffer:null, + stubBuffer:null}}; + if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject); + // We got a parse Error fire it off then keep going + self.emit("parseError", errorObject, self); + + // Clear out the state of the parser + self.buffer = null; + self.sizeOfMessage = 0; + self.bytesRead = 0; + self.stubBuffer = null; + // Exit parsing loop + data = new Buffer(0); + + } else { + try { + var emitBuffer = data.slice(0, sizeOfMessage); + // Reset state of buffer + self.buffer = null; + self.sizeOfMessage = 0; + self.bytesRead = 0; + self.stubBuffer = null; + // Copy rest of message + data = data.slice(sizeOfMessage); + // Emit the message + self.emit("message", emitBuffer, self); + } catch (err) { + var errorObject = {err:"socketHandler", trace:err, bin:self.buffer, parseState:{ + sizeOfMessage:sizeOfMessage, + bytesRead:self.bytesRead, + stubBuffer:self.stubBuffer}}; + if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject); + // We got a parse Error fire it off then keep going + self.emit("parseError", errorObject, self); + } + + } + } else { + // Create a buffer that contains the space for the non-complete message + self.stubBuffer = new Buffer(data.length) + // Copy the data to the stub buffer + data.copy(self.stubBuffer, 0); + // Exit parsing loop + data = new Buffer(0); + } + } + } + } + } +} + +var endHandler = function(self) { + return function() { + // Set connected to false + self.connected = false; + // Emit end event + self.emit("end", {err: 'connection received Fin packet from [' + self.socketOptions.host + ':' + self.socketOptions.port + ']'}, self); + } +} + +var timeoutHandler = function(self) { + return function() { + // Set connected to false + self.connected = false; + // Emit timeout event + self.emit("timeout", {err: 'connection to [' + self.socketOptions.host + ':' + self.socketOptions.port + '] timed out'}, self); + } +} + +var drainHandler = function(self) { + return function() { + } +} + +var errorHandler = function(self) { + return function(err) { + self.connection.destroy(); + // Set connected to false + self.connected = false; + // Emit error + self.emit("error", {err: 'failed to connect to [' + self.socketOptions.host + ':' + self.socketOptions.port + ']'}, self); + } +} + +var closeHandler = function(self) { + return function(hadError) { + // If we have an error during the connection phase + if(hadError && !self.connected) { + // Set disconnected + self.connected = false; + // Emit error + self.emit("error", {err: 'failed to connect to [' + self.socketOptions.host + ':' + self.socketOptions.port + ']'}, self); + } else { + // Set disconnected + self.connected = false; + // Emit close + self.emit("close", {err: 'connection closed to [' + self.socketOptions.host + ':' + self.socketOptions.port + ']'}, self); + } + } +} + +// Some basic defaults +Connection.DEFAULT_PORT = 27017; + + + + + + + diff --git a/node_modules/mongodb/lib/mongodb/connection/connection_pool.js b/node_modules/mongodb/lib/mongodb/connection/connection_pool.js new file mode 100644 index 0000000..e669354 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/connection/connection_pool.js @@ -0,0 +1,305 @@ +var utils = require('./connection_utils'), + inherits = require('util').inherits, + net = require('net'), + timers = require('timers'), + EventEmitter = require('events').EventEmitter, + inherits = require('util').inherits, + MongoReply = require("../responses/mongo_reply").MongoReply, + Connection = require("./connection").Connection; + +// Set processor, setImmediate if 0.10 otherwise nextTick +var processor = require('../utils').processor(); + +var ConnectionPool = exports.ConnectionPool = function(host, port, poolSize, bson, socketOptions) { + if(typeof host !== 'string') { + throw new Error("host must be specified [" + host + "]"); + } + + // Set up event emitter + EventEmitter.call(this); + + // Keep all options for the socket in a specific collection allowing the user to specify the + // Wished upon socket connection parameters + this.socketOptions = typeof socketOptions === 'object' ? socketOptions : {}; + this.socketOptions.host = host; + this.socketOptions.port = port; + this.socketOptions.domainSocket = false; + this.bson = bson; + // PoolSize is always + 1 for special reserved "measurment" socket (like ping, stats etc) + this.poolSize = poolSize; + this.minPoolSize = Math.floor(this.poolSize / 2) + 1; + + // Check if the host is a socket + if(host.match(/^\//)) { + this.socketOptions.domainSocket = true; + } else if(typeof port === 'string') { + try { + port = parseInt(port, 10); + } catch(err) { + new Error("port must be specified or valid integer[" + port + "]"); + } + } else if(typeof port !== 'number') { + throw new Error("port must be specified [" + port + "]"); + } + + // Set default settings for the socket options + utils.setIntegerParameter(this.socketOptions, 'timeout', 0); + // Delay before writing out the data to the server + utils.setBooleanParameter(this.socketOptions, 'noDelay', true); + // Delay before writing out the data to the server + utils.setIntegerParameter(this.socketOptions, 'keepAlive', 0); + // Set the encoding of the data read, default is binary == null + utils.setStringParameter(this.socketOptions, 'encoding', null); + // Allows you to set a throttling bufferSize if you need to stop overflows + utils.setIntegerParameter(this.socketOptions, 'bufferSize', 0); + + // Internal structures + this.openConnections = []; + // Assign connection id's + this.connectionId = 0; + + // Current index for selection of pool connection + this.currentConnectionIndex = 0; + // The pool state + this._poolState = 'disconnected'; + // timeout control + this._timeout = false; + // Time to wait between connections for the pool + this._timeToWait = 10; +} + +inherits(ConnectionPool, EventEmitter); + +ConnectionPool.prototype.setMaxBsonSize = function(maxBsonSize) { + if(maxBsonSize == null){ + maxBsonSize = Connection.DEFAULT_MAX_BSON_SIZE; + } + + for(var i = 0; i < this.openConnections.length; i++) { + this.openConnections[i].maxBsonSize = maxBsonSize; + this.openConnections[i].maxBsonSettings.maxBsonSize = maxBsonSize; + } +} + +ConnectionPool.prototype.setMaxMessageSizeBytes = function(maxMessageSizeBytes) { + if(maxMessageSizeBytes == null){ + maxMessageSizeBytes = Connection.DEFAULT_MAX_MESSAGE_SIZE; + } + + for(var i = 0; i < this.openConnections.length; i++) { + this.openConnections[i].maxMessageSizeBytes = maxMessageSizeBytes; + this.openConnections[i].maxBsonSettings.maxMessageSizeBytes = maxMessageSizeBytes; + } +} + +ConnectionPool.prototype.setMaxWriteBatchSize = function(maxWriteBatchSize) { + if(maxWriteBatchSize == null){ + maxWriteBatchSize = Connection.DEFAULT_MAX_WRITE_BATCH_SIZE; + } + + for(var i = 0; i < this.openConnections.length; i++) { + this.openConnections[i].maxWriteBatchSize = maxWriteBatchSize; + } +} + +// Start a function +var _connect = function(_self) { + // return new function() { + // Create a new connection instance + var connection = new Connection(_self.connectionId++, _self.socketOptions); + // Set logger on pool + connection.logger = _self.logger; + // Connect handler + connection.on("connect", function(err, connection) { + // Add connection to list of open connections + _self.openConnections.push(connection); + // If the number of open connections is equal to the poolSize signal ready pool + if(_self.openConnections.length === _self.poolSize && _self._poolState !== 'disconnected') { + // Set connected + _self._poolState = 'connected'; + // Emit pool ready + _self.emit("poolReady"); + } else if(_self.openConnections.length < _self.poolSize) { + // Wait a little bit of time to let the close event happen if the server closes the connection + // so we don't leave hanging connections around + if(typeof _self._timeToWait == 'number') { + setTimeout(function() { + // If we are still connecting (no close events fired in between start another connection) + if(_self._poolState == 'connecting') { + _connect(_self); + } + }, _self._timeToWait); + } else { + processor(function() { + // If we are still connecting (no close events fired in between start another connection) + if(_self._poolState == 'connecting') { + _connect(_self); + } + }); + } + } + }); + + var numberOfErrors = 0 + + // Error handler + connection.on("error", function(err, connection, error_options) { + numberOfErrors++; + // If we are already disconnected ignore the event + if(_self._poolState != 'disconnected' && _self.listeners("error").length > 0) { + _self.emit("error", err, connection, error_options); + } + + // Close the connection + connection.close(); + // Set pool as disconnected + _self._poolState = 'disconnected'; + // Stop the pool + _self.stop(); + }); + + // Close handler + connection.on("close", function() { + // If we are already disconnected ignore the event + if(_self._poolState !== 'disconnected' && _self.listeners("close").length > 0) { + _self.emit("close"); + } + + // Set disconnected + _self._poolState = 'disconnected'; + // Stop + _self.stop(); + }); + + // Timeout handler + connection.on("timeout", function(err, connection) { + // If we are already disconnected ignore the event + if(_self._poolState !== 'disconnected' && _self.listeners("timeout").length > 0) { + _self.emit("timeout", err); + } + + // Close the connection + connection.close(); + // Set disconnected + _self._poolState = 'disconnected'; + _self.stop(); + }); + + // Parse error, needs a complete shutdown of the pool + connection.on("parseError", function() { + // If we are already disconnected ignore the event + if(_self._poolState !== 'disconnected' && _self.listeners("parseError").length > 0) { + _self.emit("parseError", new Error("parseError occured")); + } + + // Set disconnected + _self._poolState = 'disconnected'; + _self.stop(); + }); + + connection.on("message", function(message) { + _self.emit("message", message); + }); + + // Start connection in the next tick + connection.start(); + // }(); +} + + +// Start method, will throw error if no listeners are available +// Pass in an instance of the listener that contains the api for +// finding callbacks for a given message etc. +ConnectionPool.prototype.start = function() { + var markerDate = new Date().getTime(); + var self = this; + + if(this.listeners("poolReady").length == 0) { + throw "pool must have at least one listener ready that responds to the [poolReady] event"; + } + + // Set pool state to connecting + this._poolState = 'connecting'; + this._timeout = false; + + _connect(self); +} + +// Restart a connection pool (on a close the pool might be in a wrong state) +ConnectionPool.prototype.restart = function() { + // Close all connections + this.stop(false); + // Now restart the pool + this.start(); +} + +// Stop the connections in the pool +ConnectionPool.prototype.stop = function(removeListeners) { + removeListeners = removeListeners == null ? true : removeListeners; + // Set disconnected + this._poolState = 'disconnected'; + + // Clear all listeners if specified + if(removeListeners) { + this.removeAllEventListeners(); + } + + // Close all connections + for(var i = 0; i < this.openConnections.length; i++) { + this.openConnections[i].close(); + } + + // Clean up + this.openConnections = []; +} + +// Check the status of the connection +ConnectionPool.prototype.isConnected = function() { + // return this._poolState === 'connected'; + return this.openConnections.length > 0 && this.openConnections[0].isConnected(); +} + +// Checkout a connection from the pool for usage, or grab a specific pool instance +ConnectionPool.prototype.checkoutConnection = function(id) { + var index = (this.currentConnectionIndex++ % (this.openConnections.length)); + var connection = this.openConnections[index]; + return connection; +} + +ConnectionPool.prototype.getAllConnections = function() { + return this.openConnections; +} + +// Remove all non-needed event listeners +ConnectionPool.prototype.removeAllEventListeners = function() { + this.removeAllListeners("close"); + this.removeAllListeners("error"); + this.removeAllListeners("timeout"); + this.removeAllListeners("connect"); + this.removeAllListeners("end"); + this.removeAllListeners("parseError"); + this.removeAllListeners("message"); + this.removeAllListeners("poolReady"); +} + + + + + + + + + + + + + + + + + + + + + + diff --git a/node_modules/mongodb/lib/mongodb/connection/connection_utils.js b/node_modules/mongodb/lib/mongodb/connection/connection_utils.js new file mode 100644 index 0000000..5910924 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/connection/connection_utils.js @@ -0,0 +1,23 @@ +exports.setIntegerParameter = function(object, field, defaultValue) { + if(object[field] == null) { + object[field] = defaultValue; + } else if(typeof object[field] !== "number" && object[field] !== parseInt(object[field], 10)) { + throw "object field [" + field + "] must be a numeric integer value, attempted to set to [" + object[field] + "] type of [" + typeof object[field] + "]"; + } +} + +exports.setBooleanParameter = function(object, field, defaultValue) { + if(object[field] == null) { + object[field] = defaultValue; + } else if(typeof object[field] !== "boolean") { + throw "object field [" + field + "] must be a boolean value, attempted to set to [" + object[field] + "] type of [" + typeof object[field] + "]"; + } +} + +exports.setStringParameter = function(object, field, defaultValue) { + if(object[field] == null) { + object[field] = defaultValue; + } else if(typeof object[field] !== "string") { + throw "object field [" + field + "] must be a string value, attempted to set to [" + object[field] + "] type of [" + typeof object[field] + "]"; + } +} \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/connection/mongos.js b/node_modules/mongodb/lib/mongodb/connection/mongos.js new file mode 100644 index 0000000..47c3361 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/connection/mongos.js @@ -0,0 +1,578 @@ +var ReadPreference = require('./read_preference').ReadPreference + , Base = require('./base').Base + , Server = require('./server').Server + , format = require('util').format + , timers = require('timers') + , utils = require('../utils') + , inherits = require('util').inherits; + +// Set processor, setImmediate if 0.10 otherwise nextTick +var processor = require('../utils').processor(); + +/** + * Mongos constructor provides a connection to a mongos proxy including failover to additional servers + * + * Options + * - **socketOptions** {Object, default:null}, an object containing socket options to use (noDelay:(boolean), keepAlive:(number), connectTimeoutMS:(number), socketTimeoutMS:(number)) + * - **ha** {Boolean, default:true}, turn on high availability, attempts to reconnect to down proxies + * - **haInterval** {Number, default:2000}, time between each replicaset status check. + * + * @class Represents a Mongos connection with failover to backup proxies + * @param {Array} list of mongos server objects + * @param {Object} [options] additional options for the mongos connection + */ +var Mongos = function Mongos(servers, options) { + // Set up basic + if(!(this instanceof Mongos)) + return new Mongos(servers, options); + + // Set up event emitter + Base.call(this); + + // Throw error on wrong setup + if(servers == null || !Array.isArray(servers) || servers.length == 0) + throw new Error("At least one mongos proxy must be in the array"); + + // Ensure we have at least an empty options object + this.options = options == null ? {} : options; + // Set default connection pool options + this.socketOptions = this.options.socketOptions != null ? this.options.socketOptions : {}; + // Enabled ha + this.haEnabled = this.options['ha'] == null ? true : this.options['ha']; + this._haInProgress = false; + // How often are we checking for new servers in the replicaset + this.mongosStatusCheckInterval = this.options['haInterval'] == null ? 1000 : this.options['haInterval']; + // Save all the server connections + this.servers = servers; + // Servers we need to attempt reconnect with + this.downServers = {}; + // Servers that are up + this.upServers = {}; + // Up servers by ping time + this.upServersByUpTime = {}; + // Set poolsize or default + this.poolSize = this.options.poolSize || 5; + // Emit open setup + this.emitOpen = this.options.emitOpen || true; + // Just contains the current lowest ping time and server + this.lowestPingTimeServer = null; + this.lowestPingTime = 0; + // Connection timeout + this._connectTimeoutMS = this.socketOptions.connectTimeoutMS + ? this.socketOptions.connectTimeoutMS + : 1000; + + // Add options to servers + for(var i = 0; i < this.servers.length; i++) { + var server = this.servers[i]; + server._callBackStore = this._callBackStore; + server.auto_reconnect = false; + + // Override pool size + if(typeof this.poolSize == 'number') { + server.poolSize = this.poolSize + } + + // Default empty socket options object + var socketOptions = {host: server.host, port: server.port}; + // If a socket option object exists clone it + if(this.socketOptions != null) { + var keys = Object.keys(this.socketOptions); + for(var k = 0; k < keys.length;k++) socketOptions[keys[i]] = this.socketOptions[keys[i]]; + } + + // Set socket options + server.socketOptions = socketOptions; + } + + // Allow setting the socketTimeoutMS on all connections + // to work around issues such as secondaries blocking due to compaction + utils.setSocketTimeoutProperty(this, this.socketOptions); +} + +/** + * @ignore + */ +inherits(Mongos, Base); + +/** + * @ignore + */ +Mongos.prototype.isMongos = function() { + return true; +} + +/** + * @ignore + */ +Mongos.prototype.connect = function(db, options, callback) { + if('function' === typeof options) callback = options, options = {}; + if(options == null) options = {}; + if(!('function' === typeof callback)) callback = null; + var self = this; + + // Keep reference to parent + this.db = db; + // Set server state to connecting + this._serverState = 'connecting'; + // Number of total servers that need to initialized (known servers) + this._numberOfServersLeftToInitialize = this.servers.length; + // Connect handler + var connectHandler = function(_server) { + return function(err, result) { + self._numberOfServersLeftToInitialize = self._numberOfServersLeftToInitialize - 1; + + // Add the server to the list of servers that are up + if(!err) { + self.upServers[format("%s:%s", _server.host, _server.port)] = _server; + } + + // We are done connecting + if(self._numberOfServersLeftToInitialize == 0) { + // If we have no valid mongos server instances error out + if(Object.keys(self.upServers).length == 0) { + // return self.emit("connectionError", new Error("No valid mongos instances found")); + return callback(new Error("No valid mongos instances found"), null); + } + + // Start ha function if it exists + if(self.haEnabled) { + // Setup the ha process + if(self._replicasetTimeoutId != null) clearInterval(self._replicasetTimeoutId); + self._replicasetTimeoutId = setInterval(self.mongosCheckFunction, self.mongosStatusCheckInterval); + } + + // Set the mongos to connected + self._serverState = "connected"; + + // Emit the open event + if(self.emitOpen) + self._emitAcrossAllDbInstances(self, null, "open", null, null, null); + + self._emitAcrossAllDbInstances(self, null, "fullsetup", null, null, null); + // Callback + callback(null, self.db); + } + } + }; + + // Error handler + var errorOrCloseHandler = function(_server) { + return function(err, result) { + // Emit left event, signaling mongos left the ha + self.emit('left', 'mongos', _server); + // Execute all the callbacks with errors + self.__executeAllCallbacksWithError(err); + // Check if we have the server + var found = false; + + // Get the server name + var server_name = format("%s:%s", _server.host, _server.port); + // Add the downed server + self.downServers[server_name] = _server; + // Remove the current server from the list + delete self.upServers[server_name]; + + // Emit close across all the attached db instances + if(Object.keys(self.upServers).length == 0) { + self._emitAcrossAllDbInstances(self, null, "close", new Error("mongos disconnected, no valid proxies contactable over tcp"), null, null); + } + } + } + + // Mongo function + this.mongosCheckFunction = function() { + // Set as not waiting for check event + self._haInProgress = true; + + // Servers down + var numberOfServersLeft = Object.keys(self.downServers).length; + + // Check downed servers + if(numberOfServersLeft > 0) { + for(var name in self.downServers) { + // Pop a downed server + var downServer = self.downServers[name]; + // Set up the connection options for a Mongos + var options = { + auto_reconnect: false, + returnIsMasterResults: true, + slaveOk: true, + poolSize: self.poolSize, + socketOptions: { + connectTimeoutMS: self._connectTimeoutMS, + socketTimeoutMS: self._socketTimeoutMS + } + } + + // Create a new server object + var newServer = new Server(downServer.host, downServer.port, options); + // Setup the connection function + var connectFunction = function(_db, _server, _options, _callback) { + return function() { + // Attempt to connect + _server.connect(_db, _options, function(err, result) { + numberOfServersLeft = numberOfServersLeft - 1; + + if(err) { + return _callback(err, _server); + } else { + // Set the new server settings + _server._callBackStore = self._callBackStore; + + // Add server event handlers + _server.on("close", errorOrCloseHandler(_server)); + _server.on("timeout", errorOrCloseHandler(_server)); + _server.on("error", errorOrCloseHandler(_server)); + + // Get a read connection + var _connection = _server.checkoutReader(); + // Get the start time + var startTime = new Date().getTime(); + + // Execute ping command to mark each server with the expected times + self.db.command({ping:1} + , {failFast:true, connection:_connection}, function(err, result) { + // Get the start time + var endTime = new Date().getTime(); + // Mark the server with the ping time + _server.runtimeStats['pingMs'] = endTime - startTime; + + // If we have any buffered commands let's signal reconnect event + if(self._commandsStore.count() > 0) { + self.emit('reconnect'); + } + + // Execute any waiting reads + self._commandsStore.execute_writes(); + self._commandsStore.execute_queries(); + // Callback + return _callback(null, _server); + }); + } + }); + } + } + + // Attempt to connect to the database + connectFunction(self.db, newServer, options, function(err, _server) { + // If we have an error + if(err) { + self.downServers[format("%s:%s", _server.host, _server.port)] = _server; + } + + // Connection function + var connectionFunction = function(_auth, _connection, _callback) { + var pending = _auth.length(); + + for(var j = 0; j < pending; j++) { + // Get the auth object + var _auth = _auth.get(j); + // Unpack the parameter + var username = _auth.username; + var password = _auth.password; + var options = { + authMechanism: _auth.authMechanism + , authSource: _auth.authdb + , connection: _connection + }; + + // If we have changed the service name + if(_auth.gssapiServiceName) + options.gssapiServiceName = _auth.gssapiServiceName; + + // Hold any error + var _error = null; + // Authenticate against the credentials + self.db.authenticate(username, password, options, function(err, result) { + _error = err != null ? err : _error; + // Adjust the pending authentication + pending = pending - 1; + // Finished up + if(pending == 0) _callback(_error ? _error : null, _error ? false : true); + }); + } + } + + // Run auths against the connections + if(self.auth.length() > 0) { + var connections = _server.allRawConnections(); + var pendingAuthConn = connections.length; + + // No connections we are done + if(connections.length == 0) { + // Set ha done + if(numberOfServersLeft == 0) { + self._haInProgress = false; + } + } + + // Final error object + var finalError = null; + // Go over all the connections + for(var j = 0; j < connections.length; j++) { + + // Execute against all the connections + connectionFunction(self.auth, connections[j], function(err, result) { + // Pending authentication + pendingAuthConn = pendingAuthConn - 1 ; + + // Save error if any + finalError = err ? err : finalError; + + // If we are done let's finish up + if(pendingAuthConn == 0) { + // Set ha done + if(numberOfServersLeft == 0) { + self._haInProgress = false; + } + + if(!err) { + add_server(self, _server); + } + + // If we have any buffered commands let's signal reconnect event + if(self._commandsStore.count() > 0) { + self.emit('reconnect'); + } + + // Execute any waiting reads + self._commandsStore.execute_writes(); + self._commandsStore.execute_queries(); + } + }); + } + } else { + if(!err) { + add_server(self, _server); + } + + // Set ha done + if(numberOfServersLeft == 0) { + self._haInProgress = false; + + // If we have any buffered commands let's signal reconnect event + if(self._commandsStore.count() > 0) { + self.emit('reconnect'); + } + + // Execute any waiting reads + self._commandsStore.execute_writes(); + self._commandsStore.execute_queries(); + } + } + })(); + } + } else { + self._haInProgress = false; + } + } + + // Connect all the server instances + for(var i = 0; i < this.servers.length; i++) { + // Get the connection + var server = this.servers[i]; + server.mongosInstance = this; + // Add server event handlers + server.on("close", errorOrCloseHandler(server)); + server.on("timeout", errorOrCloseHandler(server)); + server.on("error", errorOrCloseHandler(server)); + + // Configuration + var options = { + slaveOk: true, + poolSize: this.poolSize || server.poolSize, + socketOptions: { connectTimeoutMS: self._connectTimeoutMS }, + returnIsMasterResults: true + } + + // Connect the instance + server.connect(self.db, options, connectHandler(server)); + } +} + +/** + * @ignore + * Add a server to the list of up servers and sort them by ping time + */ +var add_server = function(self, _server) { + // Emit a new server joined + self.emit('joined', "mongos", null, _server); + // Get the server url + var server_key = format("%s:%s", _server.host, _server.port); + // Push to list of valid server + self.upServers[server_key] = _server; + // Remove the server from the list of downed servers + delete self.downServers[server_key]; + + // Sort the keys by ping time + var keys = Object.keys(self.upServers); + var _upServersSorted = {}; + var _upServers = [] + + // Get all the servers + for(var name in self.upServers) { + _upServers.push(self.upServers[name]); + } + + // Sort all the server + _upServers.sort(function(a, b) { + return a.runtimeStats['pingMs'] > b.runtimeStats['pingMs']; + }); + + // Rebuild the upServer + for(var i = 0; i < _upServers.length; i++) { + _upServersSorted[format("%s:%s", _upServers[i].host, _upServers[i].port)] = _upServers[i]; + } + + // Set the up servers + self.upServers = _upServersSorted; +} + +/** + * @ignore + * Just return the currently picked active connection + */ +Mongos.prototype.allServerInstances = function() { + return this.servers; +} + +/** + * @ignore + */ +Mongos.prototype.setSocketOptions = function(options) { + var servers = this.allServerInstances(); + for(var i = 0; i < servers.length; i++) { + servers[i].setSocketOptions(options); + } +} + +/** + * Always ourselves + * @ignore + */ +Mongos.prototype.setReadPreference = function() {} + +/** + * @ignore + */ +Mongos.prototype.allRawConnections = function() { + // Neeed to build a complete list of all raw connections, start with master server + var allConnections = []; + // Get all connected connections + for(var name in this.upServers) { + allConnections = allConnections.concat(this.upServers[name].allRawConnections()); + } + // Return all the conections + return allConnections; +} + +/** + * @ignore + */ +Mongos.prototype.isConnected = function() { + return Object.keys(this.upServers).length > 0; +} + +/** + * @ignore + */ +Mongos.prototype.isAutoReconnect = function() { + return true; +} + +/** + * @ignore + */ +Mongos.prototype.canWrite = Mongos.prototype.isConnected; + +/** + * @ignore + */ +Mongos.prototype.canRead = Mongos.prototype.isConnected; + +/** + * @ignore + */ +Mongos.prototype.isDestroyed = function() { + return this._serverState == 'destroyed'; +} + +/** + * @ignore + */ +Mongos.prototype.checkoutWriter = function() { + // Checkout a writer + var keys = Object.keys(this.upServers); + if(keys.length == 0) return null; + return this.upServers[keys[0]].checkoutWriter(); +} + +/** + * @ignore + */ +Mongos.prototype.checkoutReader = function(read) { + // If read is set to null default to primary + read = read || 'primary' + // If we have a read preference object unpack it + if(read != null && typeof read == 'object' && read['_type'] == 'ReadPreference') { + // Validate if the object is using a valid mode + if(!read.isValid()) throw new Error("Illegal readPreference mode specified, " + JSON.stringify(read)); + } else if(!ReadPreference.isValid(read)) { + throw new Error("Illegal readPreference mode specified, " + JSON.stringify(read)); + } + + // Checkout a writer + var keys = Object.keys(this.upServers); + if(keys.length == 0) return null; + return this.upServers[keys[0]].checkoutWriter(); +} + +/** + * @ignore + */ +Mongos.prototype.close = function(callback) { + var self = this; + // Set server status as disconnected + this._serverState = 'destroyed'; + // Number of connections to close + var numberOfConnectionsToClose = self.servers.length; + // If we have a ha process running kill it + if(self._replicasetTimeoutId != null) clearInterval(self._replicasetTimeoutId); + self._replicasetTimeoutId = null; + + // Emit close event + processor(function() { + self._emitAcrossAllDbInstances(self, null, "close", null, null, true) + }); + + // Flush out any remaining call handlers + self._flushAllCallHandlers(utils.toError("Connection Closed By Application")); + + // No up servers just return + if(Object.keys(this.upServers) == 0) { + return callback(null); + } + + // Close all the up servers + for(var name in this.upServers) { + this.upServers[name].close(function(err, result) { + numberOfConnectionsToClose = numberOfConnectionsToClose - 1; + + // Callback if we have one defined + if(numberOfConnectionsToClose == 0 && typeof callback == 'function') { + callback(null); + } + }); + } +} + +/** + * @ignore + * Return the used state + */ +Mongos.prototype._isUsed = function() { + return this._used; +} + +exports.Mongos = Mongos; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/connection/read_preference.js b/node_modules/mongodb/lib/mongodb/connection/read_preference.js new file mode 100644 index 0000000..6caafa9 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/connection/read_preference.js @@ -0,0 +1,67 @@ +/** + * A class representation of the Read Preference. + * + * Read Preferences + * - **ReadPreference.PRIMARY**, Read from primary only. All operations produce an error (throw an exception where applicable) if primary is unavailable. Cannot be combined with tags (This is the default.). + * - **ReadPreference.PRIMARY_PREFERRED**, Read from primary if available, otherwise a secondary. + * - **ReadPreference.SECONDARY**, Read from secondary if available, otherwise error. + * - **ReadPreference.SECONDARY_PREFERRED**, Read from a secondary if available, otherwise read from the primary. + * - **ReadPreference.NEAREST**, All modes read from among the nearest candidates, but unlike other modes, NEAREST will include both the primary and all secondaries in the random selection. + * + * @class Represents a Read Preference. + * @param {String} the read preference type + * @param {Object} tags + * @return {ReadPreference} + */ +var ReadPreference = function(mode, tags) { + if(!(this instanceof ReadPreference)) + return new ReadPreference(mode, tags); + this._type = 'ReadPreference'; + this.mode = mode; + this.tags = tags; +} + +/** + * @ignore + */ +ReadPreference.isValid = function(_mode) { + return (_mode == ReadPreference.PRIMARY || _mode == ReadPreference.PRIMARY_PREFERRED + || _mode == ReadPreference.SECONDARY || _mode == ReadPreference.SECONDARY_PREFERRED + || _mode == ReadPreference.NEAREST + || _mode == true || _mode == false || _mode == null); +} + +/** + * @ignore + */ +ReadPreference.prototype.isValid = function(mode) { + var _mode = typeof mode == 'string' ? mode : this.mode; + return ReadPreference.isValid(_mode); +} + +/** + * @ignore + */ +ReadPreference.prototype.toObject = function() { + var object = {mode:this.mode}; + + if(this.tags != null) { + object['tags'] = this.tags; + } + + return object; +} + +/** + * @ignore + */ +ReadPreference.PRIMARY = 'primary'; +ReadPreference.PRIMARY_PREFERRED = 'primaryPreferred'; +ReadPreference.SECONDARY = 'secondary'; +ReadPreference.SECONDARY_PREFERRED = 'secondaryPreferred'; +ReadPreference.NEAREST = 'nearest' + +/** + * @ignore + */ +exports.ReadPreference = ReadPreference; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/connection/repl_set/ha.js b/node_modules/mongodb/lib/mongodb/connection/repl_set/ha.js new file mode 100644 index 0000000..63f270d --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/connection/repl_set/ha.js @@ -0,0 +1,448 @@ +var DbCommand = require('../../commands/db_command').DbCommand + , format = require('util').format; + +var HighAvailabilityProcess = function(replset, options) { + this.replset = replset; + this.options = options; + this.server = null; + this.state = HighAvailabilityProcess.INIT; + this.selectedIndex = 0; +} + +HighAvailabilityProcess.INIT = 'init'; +HighAvailabilityProcess.RUNNING = 'running'; +HighAvailabilityProcess.STOPPED = 'stopped'; + +HighAvailabilityProcess.prototype.start = function() { + var self = this; + if(this.replset._state + && Object.keys(this.replset._state.addresses).length == 0) { + if(this.server) this.server.close(); + this.state = HighAvailabilityProcess.STOPPED; + return; + } + + if(this.server) this.server.close(); + // Start the running + this._haProcessInProcess = false; + this.state = HighAvailabilityProcess.RUNNING; + + // Get all possible reader servers + var candidate_servers = this.replset._state.getAllReadServers(); + if(candidate_servers.length == 0) { + return; + } + + // Select a candidate server for the connection + var server = candidate_servers[this.selectedIndex % candidate_servers.length]; + this.selectedIndex = this.selectedIndex + 1; + + // Unpack connection options + var connectTimeoutMS = self.options.connectTimeoutMS || 10000; + var socketTimeoutMS = self.options.socketTimeoutMS || 30000; + + // Just ensure we don't have a full cycle dependency + var Db = require('../../db').Db + var Server = require('../server').Server; + + // Set up a new server instance + var newServer = new Server(server.host, server.port, { + auto_reconnect: false + , returnIsMasterResults: true + , poolSize: 1 + , socketOptions: { + connectTimeoutMS: connectTimeoutMS, + socketTimeoutMS: socketTimeoutMS, + keepAlive: 100 + } + , ssl: self.replset.options.ssl + , sslValidate: self.replset.options.sslValidate + , sslCA: self.replset.options.sslCA + , sslCert: self.replset.options.sslCert + , sslKey: self.replset.options.sslKey + , sslPass: self.replset.options.sslPass + }); + + // Create new dummy db for app + self.db = new Db('local', newServer, {w:1}); + + // Set up the event listeners + newServer.once("error", _handle(this, newServer)); + newServer.once("close", _handle(this, newServer)); + newServer.once("timeout", _handle(this, newServer)); + newServer.name = format("%s:%s", server.host, server.port); + + // Let's attempt a connection over here + newServer.connect(self.db, function(err, result, _server) { + // Emit ha_connect + self.replset.emit("ha_connect", err, result, _server); + + if(self.state == HighAvailabilityProcess.STOPPED) { + _server.close(); + } + + if(err) { + // Close the server + _server.close(); + // Check if we can even do HA (is there anything running) + if(Object.keys(self.replset._state.addresses).length == 0) { + return; + } + + // Let's boot the ha timeout settings + setTimeout(function() { + self.start(); + }, self.options.haInterval); + } else { + self.server = _server; + // Let's boot the ha timeout settings + setTimeout(_timeoutHandle(self), self.options.haInterval); + } + }); +} + +HighAvailabilityProcess.prototype.stop = function() { + this.state = HighAvailabilityProcess.STOPPED; + if(this.server) this.server.close(); +} + +var _timeoutHandle = function(self) { + return function() { + if(self.state == HighAvailabilityProcess.STOPPED) { + // Stop all server instances + for(var name in self.replset._state.addresses) { + self.replset._state.addresses[name].close(); + delete self.replset._state.addresses[name]; + } + + // Finished pinging + return; + } + + // If the server is connected + if(self.server.isConnected() && !self._haProcessInProcess) { + // Start HA process + self._haProcessInProcess = true; + // Execute is master command + self.db._executeQueryCommand(DbCommand.createIsMasterCommand(self.db), + {failFast:true, connection: self.server.checkoutReader()} + , function(err, res) { + // Emit ha event + self.replset.emit("ha_ismaster", err, res); + + // If we have an error close + if(err) { + self.server.close(); + // Re-run loop + return setTimeout(_timeoutHandle(self), self.options.haInterval); + } + + // Master document + var master = res.documents[0]; + var hosts = master.hosts || []; + var reconnect_servers = []; + var state = self.replset._state; + + // We are in recovery mode, let's remove the current server + if(!master.ismaster + && !master.secondary + && state.addresses[master.me]) { + self.server.close(); + state.addresses[master.me].close(); + delete state.secondaries[master.me]; + // Re-run loop + return setTimeout(_timeoutHandle(self), self.options.haInterval); + } + + // We have a new master different front he current one + if((master.primary && state.master == null) + || (master.primary && state.master.name != master.primary)) { + + // Locate the primary and set it + if(state.addresses[master.primary]) { + if(state.master) state.master.close(); + delete state.secondaries[master.primary]; + state.master = state.addresses[master.primary]; + } + + // Emit joined event due to primary change + self.replset.emit('joined', "primary", master, state.master); + + // Set up the changes + if(state.master != null && state.master.isMasterDoc != null) { + state.master.isMasterDoc.ismaster = true; + state.master.isMasterDoc.secondary = false; + } else if(state.master != null) { + state.master.isMasterDoc = master; + state.master.isMasterDoc.ismaster = true; + state.master.isMasterDoc.secondary = false; + } + + // If we have any buffered commands let's signal reconnect event + if(self.replset._commandsStore.count() > 0) { + self.replset.emit('reconnect'); + } + + // Execute any waiting commands (queries or writes) + self.replset._commandsStore.execute_queries(); + self.replset._commandsStore.execute_writes(); + } + + // For all the hosts let's check that we have connections + for(var i = 0; i < hosts.length; i++) { + var host = hosts[i]; + + // Check if we need to reconnect to a server + if(state.addresses[host] == null) { + reconnect_servers.push(host); + } else if(state.addresses[host] && !state.addresses[host].isConnected()) { + state.addresses[host].close(); + delete state.secondaries[host]; + reconnect_servers.push(host); + } + } + + // Let's reconnect to any server needed + if(reconnect_servers.length > 0) { + _reconnect_servers(self, reconnect_servers); + } else { + self._haProcessInProcess = false + return setTimeout(_timeoutHandle(self), self.options.haInterval); + } + }); + } else if(!self.server.isConnected()) { + setTimeout(function() { + return self.start(); + }, self.options.haInterval); + } else { + setTimeout(_timeoutHandle(self), self.options.haInterval); + } + } +} + +var _reconnect_servers = function(self, reconnect_servers) { + if(reconnect_servers.length == 0) { + self._haProcessInProcess = false + return setTimeout(_timeoutHandle(self), self.options.haInterval); + } + + // Unpack connection options + var connectTimeoutMS = self.options.connectTimeoutMS || 10000; + var socketTimeoutMS = self.options.socketTimeoutMS || 0; + + // Server class + var Db = require('../../db').Db + var Server = require('../server').Server; + // Get the host + var host = reconnect_servers.shift(); + // Split it up + var _host = host.split(":")[0]; + var _port = parseInt(host.split(":")[1], 10); + + // Set up a new server instance + var newServer = new Server(_host, _port, { + auto_reconnect: false + , returnIsMasterResults: true + , poolSize: self.options.poolSize + , socketOptions: { + connectTimeoutMS: connectTimeoutMS, + socketTimeoutMS: socketTimeoutMS + } + , ssl: self.replset.options.ssl + , sslValidate: self.replset.options.sslValidate + , sslCA: self.replset.options.sslCA + , sslCert: self.replset.options.sslCert + , sslKey: self.replset.options.sslKey + , sslPass: self.replset.options.sslPass + }); + + // Create new dummy db for app + var db = new Db('local', newServer, {w:1}); + var state = self.replset._state; + + // Set up the event listeners + newServer.once("error", _repl_set_handler("error", self.replset, newServer)); + newServer.once("close", _repl_set_handler("close", self.replset, newServer)); + newServer.once("timeout", _repl_set_handler("timeout", self.replset, newServer)); + + // Set shared state + newServer.name = host; + newServer._callBackStore = self.replset._callBackStore; + newServer.replicasetInstance = self.replset; + newServer.enableRecordQueryStats(self.replset.recordQueryStats); + + // Let's attempt a connection over here + newServer.connect(db, function(err, result, _server) { + // Emit ha_connect + self.replset.emit("ha_connect", err, result, _server); + + if(self.state == HighAvailabilityProcess.STOPPED) { + _server.close(); + } + + // If we connected let's check what kind of server we have + if(!err) { + _apply_auths(self, db, _server, function(err, result) { + if(err) { + _server.close(); + // Process the next server + return setTimeout(function() { + _reconnect_servers(self, reconnect_servers); + }, self.options.haInterval); + } + + var doc = _server.isMasterDoc; + // Fire error on any unknown callbacks for this server + self.replset.__executeAllServerSpecificErrorCallbacks(_server.socketOptions.host, _server.socketOptions.port, err); + + if(doc.ismaster) { + // Emit primary added + self.replset.emit('joined', "primary", doc, _server); + + // If it was a secondary remove it + if(state.secondaries[doc.me]) { + delete state.secondaries[doc.me]; + } + + // Override any server in list of addresses + state.addresses[doc.me] = _server; + // Set server as master + state.master = _server; + + // If we have any buffered commands let's signal reconnect event + if(self.replset._commandsStore.count() > 0) { + self.replset.emit('reconnect'); + } + + // Execute any waiting writes + self.replset._commandsStore.execute_writes(); + } else if(doc.secondary) { + // Emit secondary added + self.replset.emit('joined', "secondary", doc, _server); + // Add the secondary to the state + state.secondaries[doc.me] = _server; + // Override any server in list of addresses + state.addresses[doc.me] = _server; + + // If we have any buffered commands let's signal reconnect event + if(self.replset._commandsStore.count() > 0) { + self.replset.emit('reconnect'); + } + + // Execute any waiting reads + self.replset._commandsStore.execute_queries(); + } else { + _server.close(); + } + + // Set any tags on the instance server + _server.name = doc.me; + _server.tags = doc.tags; + // Process the next server + setTimeout(function() { + _reconnect_servers(self, reconnect_servers); + }, self.options.haInterval); + }); + } else { + _server.close(); + self.replset.__executeAllServerSpecificErrorCallbacks(_server.socketOptions.host, _server.socketOptions.port, err); + + setTimeout(function() { + _reconnect_servers(self, reconnect_servers); + }, self.options.haInterval); + } + }); +} + +var _apply_auths = function(self, _db, _server, _callback) { + if(self.replset.auth.length() == 0) return _callback(null); + // Apply any authentication needed + if(self.replset.auth.length() > 0) { + var pending = self.replset.auth.length(); + var connections = _server.allRawConnections(); + var pendingAuthConn = connections.length; + // Connection function + var connectionFunction = function(auth, _connection, __callback) { + var pending = auth.length(); + + for(var j = 0; j < pending; j++) { + // Get the auth object + var _auth = auth.get(j); + // Unpack the parameter + var username = _auth.username; + var password = _auth.password; + var options = { + authMechanism: _auth.authMechanism + , authSource: _auth.authdb + , connection: _connection + }; + + // If we have changed the service name + if(_auth.gssapiServiceName) + options.gssapiServiceName = _auth.gssapiServiceName; + + // Hold any error + var _error = null; + + // Authenticate against the credentials + _db.authenticate(username, password, options, function(err, result) { + _error = err != null ? err : _error; + // Adjust the pending authentication + pending = pending - 1; + // Finished up + if(pending == 0) __callback(_error ? _error : null, _error ? false : true); + }); + } + } + + // Final error object + var finalError = null; + // Iterate over all the connections + for(var i = 0; i < connections.length; i++) { + connectionFunction(self.replset.auth, connections[i], function(err, result) { + // Pending authentication + pendingAuthConn = pendingAuthConn - 1 ; + + // Save error if any + finalError = err ? err : finalError; + + // If we are done let's finish up + if(pendingAuthConn == 0) { + _callback(null); + } + }); + } + } +} + +var _handle = function(self, server) { + return function(err) { + server.close(); + } +} + +var _repl_set_handler = function(event, self, server) { + var ReplSet = require('./repl_set').ReplSet; + + return function(err, doc) { + server.close(); + + // The event happened to a primary + // Remove it from play + if(self._state.isPrimary(server)) { + self._state.master == null; + self._serverState = ReplSet.REPLSET_READ_ONLY; + } else if(self._state.isSecondary(server)) { + delete self._state.secondaries[server.name]; + } + + // Unpack variables + var host = server.socketOptions.host; + var port = server.socketOptions.port; + + // Fire error on any unknown callbacks + self.__executeAllServerSpecificErrorCallbacks(host, port, err); + } +} + +exports.HighAvailabilityProcess = HighAvailabilityProcess; diff --git a/node_modules/mongodb/lib/mongodb/connection/repl_set/options.js b/node_modules/mongodb/lib/mongodb/connection/repl_set/options.js new file mode 100644 index 0000000..8b3d72b --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/connection/repl_set/options.js @@ -0,0 +1,126 @@ +var PingStrategy = require('./strategies/ping_strategy').PingStrategy + , StatisticsStrategy = require('./strategies/statistics_strategy').StatisticsStrategy + , ReadPreference = require('../read_preference').ReadPreference; + +var Options = function(options) { + options = options || {}; + this._options = options; + this.ha = options.ha || true; + this.haInterval = options.haInterval || 2000; + this.reconnectWait = options.reconnectWait || 1000; + this.retries = options.retries || 30; + this.rs_name = options.rs_name; + this.socketOptions = options.socketOptions || {}; + this.readPreference = options.readPreference; + this.readSecondary = options.read_secondary; + this.poolSize = options.poolSize == null ? 5 : options.poolSize; + this.strategy = options.strategy || 'ping'; + this.secondaryAcceptableLatencyMS = options.secondaryAcceptableLatencyMS || 15; + this.connectArbiter = options.connectArbiter || false; + this.connectWithNoPrimary = options.connectWithNoPrimary || false; + this.logger = options.logger; + this.ssl = options.ssl || false; + this.sslValidate = options.sslValidate || false; + this.sslCA = options.sslCA; + this.sslCert = options.sslCert; + this.sslKey = options.sslKey; + this.sslPass = options.sslPass; + this.emitOpen = options.emitOpen || true; +} + +Options.prototype.init = function() { + if(this.sslValidate && (!Array.isArray(this.sslCA) || this.sslCA.length == 0)) { + throw new Error("The driver expects an Array of CA certificates in the sslCA parameter when enabling sslValidate"); + } + + // Make sure strategy is one of the two allowed + if(this.strategy != null && (this.strategy != 'ping' && this.strategy != 'statistical' && this.strategy != 'none')) + throw new Error("Only ping or statistical strategies allowed"); + + if(this.strategy == null) this.strategy = 'ping'; + + // Set logger if strategy exists + if(this.strategyInstance) this.strategyInstance.logger = this.logger; + + // Unpack read Preference + var readPreference = this.readPreference; + // Validate correctness of Read preferences + if(readPreference != null) { + if(readPreference != ReadPreference.PRIMARY && readPreference != ReadPreference.PRIMARY_PREFERRED + && readPreference != ReadPreference.SECONDARY && readPreference != ReadPreference.SECONDARY_PREFERRED + && readPreference != ReadPreference.NEAREST && typeof readPreference != 'object' && readPreference['_type'] != 'ReadPreference') { + throw new Error("Illegal readPreference mode specified, " + JSON.stringify(readPreference)); + } + + this.readPreference = readPreference; + } else { + this.readPreference = null; + } + + // Ensure read_secondary is set correctly + if(this.readSecondary != null) + this.readSecondary = this.readPreference == ReadPreference.PRIMARY + || this.readPreference == false + || this.readPreference == null ? false : true; + + // Ensure correct slave set + if(this.readSecondary) this.slaveOk = true; + + // Set up logger if any set + this.logger = this.logger != null + && (typeof this.logger.debug == 'function') + && (typeof this.logger.error == 'function') + && (typeof this.logger.debug == 'function') + ? this.logger : {error:function(message, object) {}, log:function(message, object) {}, debug:function(message, object) {}}; + + // Connection timeout + this.connectTimeoutMS = typeof this.socketOptions.connectTimeoutMS == 'number' + ? this.socketOptions.connectTimeoutMS + : 1000; + + // Socket connection timeout + this.socketTimeoutMS = typeof this.socketOptions.socketTimeoutMS == 'number' + ? this.socketOptions.socketTimeoutMS + : 30000; +} + +Options.prototype.decorateAndClean = function(servers, callBackStore) { + var self = this; + + // var de duplicate list + var uniqueServers = {}; + // De-duplicate any servers in the seed list + for(var i = 0; i < servers.length; i++) { + var server = servers[i]; + // If server does not exist set it + if(uniqueServers[server.host + ":" + server.port] == null) { + uniqueServers[server.host + ":" + server.port] = server; + } + } + + // Let's set the deduplicated list of servers + var finalServers = []; + // Add the servers + for(var key in uniqueServers) { + finalServers.push(uniqueServers[key]); + } + + finalServers.forEach(function(server) { + // Ensure no server has reconnect on + server.options.auto_reconnect = false; + // Set up ssl options + server.ssl = self.ssl; + server.sslValidate = self.sslValidate; + server.sslCA = self.sslCA; + server.sslCert = self.sslCert; + server.sslKey = self.sslKey; + server.sslPass = self.sslPass; + server.poolSize = self.poolSize; + // Set callback store + server._callBackStore = callBackStore; + }); + + return finalServers; +} + +exports.Options = Options; diff --git a/node_modules/mongodb/lib/mongodb/connection/repl_set/repl_set.js b/node_modules/mongodb/lib/mongodb/connection/repl_set/repl_set.js new file mode 100644 index 0000000..0e95cfa --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/connection/repl_set/repl_set.js @@ -0,0 +1,830 @@ +var ReadPreference = require('../read_preference').ReadPreference + , DbCommand = require('../../commands/db_command').DbCommand + , inherits = require('util').inherits + , format = require('util').format + , timers = require('timers') + , Server = require('../server').Server + , utils = require('../../utils') + , PingStrategy = require('./strategies/ping_strategy').PingStrategy + , StatisticsStrategy = require('./strategies/statistics_strategy').StatisticsStrategy + , Options = require('./options').Options + , ReplSetState = require('./repl_set_state').ReplSetState + , HighAvailabilityProcess = require('./ha').HighAvailabilityProcess + , Base = require('../base').Base; + +var STATE_STARTING_PHASE_1 = 0; +var STATE_PRIMARY = 1; +var STATE_SECONDARY = 2; +var STATE_RECOVERING = 3; +var STATE_FATAL_ERROR = 4; +var STATE_STARTING_PHASE_2 = 5; +var STATE_UNKNOWN = 6; +var STATE_ARBITER = 7; +var STATE_DOWN = 8; +var STATE_ROLLBACK = 9; + +// Set processor, setImmediate if 0.10 otherwise nextTick +var processor = require('../../utils').processor(); + +/** + * ReplSet constructor provides replicaset functionality + * + * Options + * - **ha** {Boolean, default:true}, turn on high availability. + * - **haInterval** {Number, default:2000}, time between each replicaset status check. + * - **reconnectWait** {Number, default:1000}, time to wait in miliseconds before attempting reconnect. + * - **retries** {Number, default:30}, number of times to attempt a replicaset reconnect. + * - **rs_name** {String}, the name of the replicaset to connect to. + * - **socketOptions** {Object, default:null}, an object containing socket options to use (noDelay:(boolean), keepAlive:(number), connectTimeoutMS:(number), socketTimeoutMS:(number)) + * - **strategy** {String, default:'ping'}, selection strategy for reads choose between (ping, statistical and none, default is ping) + * - **secondaryAcceptableLatencyMS** {Number, default:15}, sets the range of servers to pick when using NEAREST (lowest ping ms + the latency fence, ex: range of 1 to (1 + 15) ms) + * - **connectWithNoPrimary** {Boolean, default:false}, sets if the driver should connect even if no primary is available + * - **connectArbiter** {Boolean, default:false}, sets if the driver should connect to arbiters or not. + * - **logger** {Object, default:null}, an object representing a logger that you want to use, needs to support functions debug, log, error **({error:function(message, object) {}, log:function(message, object) {}, debug:function(message, object) {}})**. + * - **poolSize** {Number, default:5}, number of connections in the connection pool for each server instance, set to 5 as default for legacy reasons. + * - **ssl** {Boolean, default:false}, use ssl connection (needs to have a mongod server with ssl support) + * - **sslValidate** {Boolean, default:false}, validate mongod server certificate against ca (needs to have a mongod server with ssl support, 2.4 or higher) + * - **sslCA** {Array, default:null}, Array of valid certificates either as Buffers or Strings (needs to have a mongod server with ssl support, 2.4 or higher) + * - **sslCert** {Buffer/String, default:null}, String or buffer containing the certificate we wish to present (needs to have a mongod server with ssl support, 2.4 or higher) + * - **sslKey** {Buffer/String, default:null}, String or buffer containing the certificate private key we wish to present (needs to have a mongod server with ssl support, 2.4 or higher) + * - **sslPass** {Buffer/String, default:null}, String or buffer containing the certificate password (needs to have a mongod server with ssl support, 2.4 or higher) + * + * @class Represents a + Replicaset Configuration + * @param {Array} list of server objects participating in the replicaset. + * @param {Object} [options] additional options for the replicaset connection. + */ +var ReplSet = exports.ReplSet = function(servers, options) { + // Set up basic + if(!(this instanceof ReplSet)) + return new ReplSet(servers, options); + + // Set up event emitter + Base.call(this); + + // Ensure we have a list of servers + if(!Array.isArray(servers)) throw Error("The parameter must be an array of servers and contain at least one server"); + // Ensure no Mongos's + for(var i = 0; i < servers.length; i++) { + if(!(servers[i] instanceof Server)) throw new Error("list of servers must be of type Server"); + } + + // Save the options + this.options = new Options(options); + // Ensure basic validation of options + this.options.init(); + + // Server state + this._serverState = ReplSet.REPLSET_DISCONNECTED; + // Add high availability process + this._haProcess = new HighAvailabilityProcess(this, this.options); + + // Let's iterate over all the provided server objects and decorate them + this.servers = this.options.decorateAndClean(servers, this._callBackStore); + // Throw error if no seed servers + if(this.servers.length == 0) throw new Error("No valid seed servers in the array"); + + // Let's set up our strategy object for picking secondaries + if(this.options.strategy == 'ping') { + // Create a new instance + this.strategyInstance = new PingStrategy(this, this.options.secondaryAcceptableLatencyMS); + } else if(this.options.strategy == 'statistical') { + // Set strategy as statistical + this.strategyInstance = new StatisticsStrategy(this); + // Add enable query information + this.enableRecordQueryStats(true); + } + + this.emitOpen = this.options.emitOpen || true; + // Set up a clean state + this._state = new ReplSetState(this); + // Current round robin selected server + this._currentServerChoice = 0; + // Ensure up the server callbacks + for(var i = 0; i < this.servers.length; i++) { + this.servers[i]._callBackStore = this._callBackStore; + this.servers[i].name = format("%s:%s", this.servers[i].host, this.servers[i].port) + this.servers[i].replicasetInstance = this; + this.servers[i].options.auto_reconnect = false; + this.servers[i].poolSize = this.options.poolSize; + this.servers[i].inheritReplSetOptionsFrom(this); + } + + // Allow setting the socketTimeoutMS on all connections + // to work around issues such as secondaries blocking due to compaction + utils.setSocketTimeoutProperty(this, this.options.socketOptions); +} + +/** + * @ignore + */ +inherits(ReplSet, Base); + +// Replicaset states +ReplSet.REPLSET_CONNECTING = 'connecting'; +ReplSet.REPLSET_DISCONNECTED = 'disconnected'; +ReplSet.REPLSET_CONNECTED = 'connected'; +ReplSet.REPLSET_RECONNECTING = 'reconnecting'; +ReplSet.REPLSET_DESTROYED = 'destroyed'; +ReplSet.REPLSET_READ_ONLY = 'readonly'; + +ReplSet.prototype.isAutoReconnect = function() { + return true; +} + +ReplSet.prototype.canWrite = function() { + return this._state.master && this._state.master.isConnected(); +} + +ReplSet.prototype.canRead = function(read) { + if((read == ReadPreference.PRIMARY + || (typeof read == 'object' && read.mode == ReadPreference.PRIMARY) + || read == null || read == false) && (this._state.master == null || !this._state.master.isConnected())) return false; + return Object.keys(this._state.secondaries).length > 0; +} + +/** + * @ignore + */ +ReplSet.prototype.enableRecordQueryStats = function(enable) { + // Set the global enable record query stats + this.recordQueryStats = enable; + + // Enable all the servers + for(var i = 0; i < this.servers.length; i++) { + this.servers[i].enableRecordQueryStats(enable); + } +} + +/** + * @ignore + */ +ReplSet.prototype.setSocketOptions = function(options) { + var servers = this.allServerInstances(); + + if(typeof options.socketTimeoutMS == 'number') { + this.options.socketOptions.socketTimeoutMS = options.socketTimeoutMS; + } + + if(typeof options.connectTimeoutMS == 'number') + this.options.socketOptions.connectTimeoutMS = options.connectTimeoutMS; + + for(var i = 0; i < servers.length; i++) { + servers[i].setSocketOptions(options); + } +} + +/** + * @ignore + */ +ReplSet.prototype.setReadPreference = function(preference) { + this.options.readPreference = preference; +} + +ReplSet.prototype.connect = function(parent, options, callback) { + if(this._serverState != ReplSet.REPLSET_DISCONNECTED) + return callback(new Error("in process of connection")); + + // If no callback throw + if(!(typeof callback == 'function')) + throw new Error("cannot call ReplSet.prototype.connect with no callback function"); + + var self = this; + // Save db reference + this.options.db = parent; + // Set replicaset as connecting + this._serverState = ReplSet.REPLSET_CONNECTING + // Copy all the servers to our list of seeds + var candidateServers = this.servers.slice(0); + // Pop the first server + var server = candidateServers.pop(); + server.name = format("%s:%s", server.host, server.port); + // Set up the options + var opts = { + returnIsMasterResults: true, + eventReceiver: server + } + + // Register some event listeners + this.once("fullsetup", function(err, db, replset) { + // Set state to connected + self._serverState = ReplSet.REPLSET_CONNECTED; + // Stop any process running + if(self._haProcess) self._haProcess.stop(); + // Start the HA process + self._haProcess.start(); + + // Emit fullsetup + processor(function() { + if(self.emitOpen) + self._emitAcrossAllDbInstances(self, null, "open", null, null, null); + + self._emitAcrossAllDbInstances(self, null, "fullsetup", null, null, null); + }); + + // If we have a strategy defined start it + if(self.strategyInstance) { + self.strategyInstance.start(); + } + + // Finishing up the call + callback(err, db, replset); + }); + + // Errors + this.once("connectionError", function(err, result) { + callback(err, result); + }); + + // Attempt to connect to the server + server.connect(this.options.db, opts, _connectHandler(this, candidateServers, server)); +} + +ReplSet.prototype.close = function(callback) { + var self = this; + // Set as destroyed + this._serverState = ReplSet.REPLSET_DESTROYED; + // Stop the ha + this._haProcess.stop(); + + // If we have a strategy stop it + if(this.strategyInstance) { + this.strategyInstance.stop(); + } + + // Kill all servers available + for(var name in this._state.addresses) { + this._state.addresses[name].close(); + } + + // Clean out the state + this._state = new ReplSetState(this); + + // Emit close event + processor(function() { + self._emitAcrossAllDbInstances(self, null, "close", null, null, true) + }); + + // Flush out any remaining call handlers + self._flushAllCallHandlers(utils.toError("Connection Closed By Application")); + + // Callback + if(typeof callback == 'function') + return callback(null, null); +} + +/** + * Creates a new server for the `replset` based on `host`. + * + * @param {String} host - host:port pair (localhost:27017) + * @param {ReplSet} replset - the ReplSet instance + * @return {Server} + * @ignore + */ +var createServer = function(self, host, options) { + // copy existing socket options to new server + var socketOptions = {} + if(options.socketOptions) { + var keys = Object.keys(options.socketOptions); + for(var k = 0; k < keys.length; k++) { + socketOptions[keys[k]] = options.socketOptions[keys[k]]; + } + } + + var parts = host.split(/:/); + if(1 === parts.length) { + parts[1] = Connection.DEFAULT_PORT; + } + + socketOptions.host = parts[0]; + socketOptions.port = parseInt(parts[1], 10); + + var serverOptions = { + readPreference: options.readPreference, + socketOptions: socketOptions, + poolSize: options.poolSize, + logger: options.logger, + auto_reconnect: false, + ssl: options.ssl, + sslValidate: options.sslValidate, + sslCA: options.sslCA, + sslCert: options.sslCert, + sslKey: options.sslKey, + sslPass: options.sslPass + } + + var server = new Server(socketOptions.host, socketOptions.port, serverOptions); + // Set up shared state + server._callBackStore = self._callBackStore; + server.replicasetInstance = self; + server.enableRecordQueryStats(self.recordQueryStats); + // Set up event handlers + server.on("close", _handler("close", self, server)); + server.on("error", _handler("error", self, server)); + server.on("timeout", _handler("timeout", self, server)); + return server; +} + +var _handler = function(event, self, server) { + return function(err, doc) { + // The event happened to a primary + // Remove it from play + if(self._state.isPrimary(server)) { + // Emit that the primary left the replicaset + self.emit('left', 'primary', server); + // Get the current master + var current_master = self._state.master; + self._state.master = null; + self._serverState = ReplSet.REPLSET_READ_ONLY; + + if(current_master != null) { + // Unpack variables + var host = current_master.socketOptions.host; + var port = current_master.socketOptions.port; + + // Fire error on any unknown callbacks + self.__executeAllServerSpecificErrorCallbacks(host, port, err); + } + } else if(self._state.isSecondary(server)) { + // Emit that a secondary left the replicaset + self.emit('left', 'secondary', server); + // Delete from the list + delete self._state.secondaries[server.name]; + } + + // If there is no more connections left and the setting is not destroyed + // set to disconnected + if(Object.keys(self._state.addresses).length == 0 + && self._serverState != ReplSet.REPLSET_DESTROYED) { + self._serverState = ReplSet.REPLSET_DISCONNECTED; + + // Emit close across all the attached db instances + self._dbStore.emit("close", new Error("replicaset disconnected, no valid servers contactable over tcp"), null, true); + } + + // Unpack variables + var host = server.socketOptions.host; + var port = server.socketOptions.port; + + // Fire error on any unknown callbacks + self.__executeAllServerSpecificErrorCallbacks(host, port, err); + } +} + +var locateNewServers = function(self, state, candidateServers, ismaster) { + // Retrieve the host + var hosts = ismaster.hosts; + // In candidate servers + var inCandidateServers = function(name, candidateServers) { + for(var i = 0; i < candidateServers.length; i++) { + if(candidateServers[i].name == name) return true; + } + + return false; + } + + // New servers + var newServers = []; + if(Array.isArray(hosts)) { + // Let's go over all the hosts + for(var i = 0; i < hosts.length; i++) { + if(!state.contains(hosts[i]) + && !inCandidateServers(hosts[i], candidateServers)) { + newServers.push(createServer(self, hosts[i], self.options)); + } + } + } + + // Return list of possible new servers + return newServers; +} + +var _connectHandler = function(self, candidateServers, instanceServer) { + return function(err, doc) { + // If we have an error add to the list + if(err) { + self._state.errors[instanceServer.name] = instanceServer; + } else { + delete self._state.errors[instanceServer.name]; + } + + if(!err) { + var ismaster = doc.documents[0] + + // Error the server if + if(!ismaster.ismaster + && !ismaster.secondary) { + self._state.errors[instanceServer.name] = instanceServer; + } + } + + + // No error let's analyse the ismaster command + if(!err && self._state.errors[instanceServer.name] == null) { + var ismaster = doc.documents[0] + + // If no replicaset name exists set the current one + if(self.options.rs_name == null) { + self.options.rs_name = ismaster.setName; + } + + // If we have a member that is not part of the set let's finish up + if(typeof ismaster.setName == 'string' && ismaster.setName != self.options.rs_name) { + return self.emit("connectionError", new Error("Replicaset name " + ismaster.setName + " does not match specified name " + self.options.rs_name)); + } + + // Add the error handlers + instanceServer.on("close", _handler("close", self, instanceServer)); + instanceServer.on("error", _handler("error", self, instanceServer)); + instanceServer.on("timeout", _handler("timeout", self, instanceServer)); + + // Set any tags on the instance server + instanceServer.name = ismaster.me; + instanceServer.tags = ismaster.tags; + + // Add the server to the list + self._state.addServer(instanceServer, ismaster); + + // Check if we have more servers to add (only check when done with initial set) + if(candidateServers.length == 0) { + // Get additional new servers that are not currently in set + var new_servers = locateNewServers(self, self._state, candidateServers, ismaster); + + // Locate any new servers that have not errored out yet + for(var i = 0; i < new_servers.length; i++) { + if(self._state.errors[new_servers[i].name] == null) { + candidateServers.push(new_servers[i]) + } + } + } + } + + // If the candidate server list is empty and no valid servers + if(candidateServers.length == 0 && + !self._state.hasValidServers()) { + return self.emit("connectionError", new Error("No valid replicaset instance servers found")); + } else if(candidateServers.length == 0) { + if(!self.options.connectWithNoPrimary && (self._state.master == null || !self._state.master.isConnected())) { + return self.emit("connectionError", new Error("No primary found in set")); + } + return self.emit("fullsetup", null, self.options.db, self); + } + + // Let's connect the next server + var nextServer = candidateServers.pop(); + + // Set up the options + var opts = { + returnIsMasterResults: true, + eventReceiver: nextServer + } + + // Attempt to connect to the server + nextServer.connect(self.options.db, opts, _connectHandler(self, candidateServers, nextServer)); + } +} + +ReplSet.prototype.isDestroyed = function() { + return this._serverState == ReplSet.REPLSET_DESTROYED; +} + +ReplSet.prototype.isConnected = function(read) { + var isConnected = false; + + if(read == null || read == ReadPreference.PRIMARY || read == false) + isConnected = this._state.master != null && this._state.master.isConnected(); + + if((read == ReadPreference.PRIMARY_PREFERRED || read == ReadPreference.SECONDARY_PREFERRED || read == ReadPreference.NEAREST) + && ((this._state.master != null && this._state.master.isConnected()) + || (this._state && this._state.secondaries && Object.keys(this._state.secondaries).length > 0))) { + isConnected = true; + } else if(read == ReadPreference.SECONDARY) { + isConnected = this._state && this._state.secondaries && Object.keys(this._state.secondaries).length > 0; + } + + // No valid connection return false + return isConnected; +} + +ReplSet.prototype.isMongos = function() { + return false; +} + +ReplSet.prototype.checkoutWriter = function() { + if(this._state.master) return this._state.master.checkoutWriter(); + return new Error("no writer connection available"); +} + +ReplSet.prototype.processIsMaster = function(_server, _ismaster) { + // Server in recovery mode, remove it from available servers + if(!_ismaster.ismaster && !_ismaster.secondary) { + // Locate the actual server + var server = this._state.addresses[_server.name]; + // Close the server, simulating the closing of the connection + // to get right removal semantics + if(server) server.close(); + // Execute any callback errors + _handler(null, this, server)(new Error("server is in recovery mode")); + } +} + +ReplSet.prototype.allRawConnections = function() { + var connections = []; + + for(var name in this._state.addresses) { + connections = connections.concat(this._state.addresses[name].allRawConnections()); + } + + return connections; +} + +/** + * @ignore + */ +ReplSet.prototype.allServerInstances = function() { + var self = this; + // If no state yet return empty + if(!self._state) return []; + // Close all the servers (concatenate entire list of servers first for ease) + var allServers = self._state.master != null ? [self._state.master] : []; + + // Secondary keys + var keys = Object.keys(self._state.secondaries); + // Add all secondaries + for(var i = 0; i < keys.length; i++) { + allServers.push(self._state.secondaries[keys[i]]); + } + + // Return complete list of all servers + return allServers; +} + +/** + * @ignore + */ +ReplSet.prototype.checkoutReader = function(readPreference, tags) { + var connection = null; + + // If we have a read preference object unpack it + if(typeof readPreference == 'object' && readPreference['_type'] == 'ReadPreference') { + // Validate if the object is using a valid mode + if(!readPreference.isValid()) throw new Error("Illegal readPreference mode specified, " + JSON.stringify(readPreference.mode)); + // Set the tag + tags = readPreference.tags; + readPreference = readPreference.mode; + } else if(typeof readPreference == 'object' && readPreference['_type'] != 'ReadPreference') { + return new Error("read preferences must be either a string or an instance of ReadPreference"); + } + + // Set up our read Preference, allowing us to override the readPreference + var finalReadPreference = readPreference != null ? readPreference : this.options.readPreference; + + // Ensure we unpack a reference + if(finalReadPreference != null && typeof finalReadPreference == 'object' && finalReadPreference['_type'] == 'ReadPreference') { + // Validate if the object is using a valid mode + if(!finalReadPreference.isValid()) throw new Error("Illegal readPreference mode specified, " + JSON.stringify(finalReadPreference.mode)); + // Set the tag + tags = finalReadPreference.tags; + readPreference = finalReadPreference.mode; + } + + // Finalize the read preference setup + finalReadPreference = finalReadPreference == true ? ReadPreference.SECONDARY_PREFERRED : finalReadPreference; + finalReadPreference = finalReadPreference == null ? ReadPreference.PRIMARY : finalReadPreference; + + // If we are reading from a primary + if(finalReadPreference == 'primary') { + // If we provide a tags set send an error + if(typeof tags == 'object' && tags != null) { + return new Error("PRIMARY cannot be combined with tags"); + } + + // If we provide a tags set send an error + if(this._state.master == null) { + return new Error("No replica set primary available for query with ReadPreference PRIMARY"); + } + + // Checkout a writer + return this.checkoutWriter(); + } + + // If we have specified to read from a secondary server grab a random one and read + // from it, otherwise just pass the primary connection + if((this.options.readSecondary || finalReadPreference == ReadPreference.SECONDARY_PREFERRED || finalReadPreference == ReadPreference.SECONDARY) && Object.keys(this._state.secondaries).length > 0) { + // If we have tags, look for servers matching the specific tag + if(this.strategyInstance != null) { + // Only pick from secondaries + var _secondaries = []; + for(var key in this._state.secondaries) { + _secondaries.push(this._state.secondaries[key]); + } + + if(finalReadPreference == ReadPreference.SECONDARY) { + // Check out the nearest from only the secondaries + connection = this.strategyInstance.checkoutConnection(tags, _secondaries); + } else { + connection = this.strategyInstance.checkoutConnection(tags, _secondaries); + // No candidate servers that match the tags, error + if(connection == null || connection instanceof Error) { + // No secondary server avilable, attemp to checkout a primary server + connection = this.checkoutWriter(); + // If no connection return an error + if(connection == null || connection instanceof Error) { + return new Error("No replica set members available for query"); + } + } + } + } else if(tags != null && typeof tags == 'object') { + // Get connection + connection = _pickFromTags(this, tags);// = function(self, readPreference, tags) { + // No candidate servers that match the tags, error + if(connection == null) { + return new Error("No replica set members available for query"); + } + } else { + connection = _roundRobin(this, tags); + } + } else if(finalReadPreference == ReadPreference.PRIMARY_PREFERRED) { + // Check if there is a primary available and return that if possible + connection = this.checkoutWriter(); + // If no connection available checkout a secondary + if(connection == null || connection instanceof Error) { + // If we have tags, look for servers matching the specific tag + if(tags != null && typeof tags == 'object') { + // Get connection + connection = _pickFromTags(this, tags);// = function(self, readPreference, tags) { + // No candidate servers that match the tags, error + if(connection == null) { + return new Error("No replica set members available for query"); + } + } else { + connection = _roundRobin(this, tags); + } + } + } else if(finalReadPreference == ReadPreference.SECONDARY_PREFERRED) { + // If we have tags, look for servers matching the specific tag + if(this.strategyInstance != null) { + connection = this.strategyInstance.checkoutConnection(tags); + + // No candidate servers that match the tags, error + if(connection == null || connection instanceof Error) { + // No secondary server avilable, attemp to checkout a primary server + connection = this.checkoutWriter(); + // If no connection return an error + if(connection == null || connection instanceof Error) { + var preferenceName = finalReadPreference == ReadPreference.SECONDARY ? 'secondary' : finalReadPreference; + return new Error("No replica set member available for query with ReadPreference " + preferenceName + " and tags " + JSON.stringify(tags)); + } + } + } else if(tags != null && typeof tags == 'object') { + // Get connection + connection = _pickFromTags(this, tags);// = function(self, readPreference, tags) { + // No candidate servers that match the tags, error + if(connection == null) { + // No secondary server avilable, attemp to checkout a primary server + connection = this.checkoutWriter(); + // If no connection return an error + if(connection == null || connection instanceof Error) { + var preferenceName = finalReadPreference == ReadPreference.SECONDARY ? 'secondary' : finalReadPreference; + return new Error("No replica set member available for query with ReadPreference " + preferenceName + " and tags " + JSON.stringify(tags)); + } + } + } + } else if(finalReadPreference == ReadPreference.NEAREST && this.strategyInstance != null) { + connection = this.strategyInstance.checkoutConnection(tags); + } else if(finalReadPreference == ReadPreference.NEAREST && this.strategyInstance == null) { + return new Error("A strategy for calculating nearness must be enabled such as ping or statistical"); + } else if(finalReadPreference == ReadPreference.SECONDARY && Object.keys(this._state.secondaries).length == 0) { + if(tags != null && typeof tags == 'object') { + var preferenceName = finalReadPreference == ReadPreference.SECONDARY ? 'secondary' : finalReadPreference; + return new Error("No replica set member available for query with ReadPreference " + preferenceName + " and tags " + JSON.stringify(tags)); + } else { + return new Error("No replica set secondary available for query with ReadPreference SECONDARY"); + } + } else { + connection = this.checkoutWriter(); + } + + // Return the connection + return connection; +} + +/** + * @ignore + */ +var _pickFromTags = function(self, tags) { + // If we have an array or single tag selection + var tagObjects = Array.isArray(tags) ? tags : [tags]; + // Iterate over all tags until we find a candidate server + for(var _i = 0; _i < tagObjects.length; _i++) { + // Grab a tag object + var tagObject = tagObjects[_i]; + // Matching keys + var matchingKeys = Object.keys(tagObject); + // Match all the servers that match the provdided tags + var keys = Object.keys(self._state.secondaries); + var candidateServers = []; + + for(var i = 0; i < keys.length; i++) { + var server = self._state.secondaries[keys[i]]; + // If we have tags match + if(server.tags != null) { + var matching = true; + // Ensure we have all the values + for(var j = 0; j < matchingKeys.length; j++) { + if(server.tags[matchingKeys[j]] != tagObject[matchingKeys[j]]) { + matching = false; + break; + } + } + + // If we have a match add it to the list of matching servers + if(matching) { + candidateServers.push(server); + } + } + } + + // If we have a candidate server return + if(candidateServers.length > 0) { + if(self.strategyInstance) return self.strategyInstance.checkoutConnection(tags, candidateServers); + // Set instance to return + return candidateServers[Math.floor(Math.random() * candidateServers.length)].checkoutReader(); + } + } + + // No connection found + return null; +} + +/** + * Pick a secondary using round robin + * + * @ignore + */ +function _roundRobin (replset, tags) { + var keys = Object.keys(replset._state.secondaries); + // Update index + replset._currentServerChoice = replset._currentServerChoice + 1; + // Pick a server + var key = keys[replset._currentServerChoice % keys.length]; + + var conn = null != replset._state.secondaries[key] + ? replset._state.secondaries[key].checkoutReader() + : null; + + // If connection is null fallback to first available secondary + if(null == conn) { + conn = pickFirstConnectedSecondary(replset, tags); + } + + return conn; +} + +/** + * @ignore + */ +var pickFirstConnectedSecondary = function pickFirstConnectedSecondary(self, tags) { + var keys = Object.keys(self._state.secondaries); + var connection; + + // Find first available reader if any + for(var i = 0; i < keys.length; i++) { + connection = self._state.secondaries[keys[i]].checkoutReader(); + if(connection) return connection; + } + + // If we still have a null, read from primary if it's not secondary only + if(self._readPreference == ReadPreference.SECONDARY_PREFERRED) { + connection = self._state.master.checkoutReader(); + if(connection) return connection; + } + + var preferenceName = self._readPreference == ReadPreference.SECONDARY_PREFERRED + ? 'secondary' + : self._readPreference; + + return new Error("No replica set member available for query with ReadPreference " + + preferenceName + " and tags " + JSON.stringify(tags)); +} + +/** + * Get list of secondaries + * @ignore + */ +Object.defineProperty(ReplSet.prototype, "secondaries", {enumerable: true + , get: function() { + return utils.objectToArray(this._state.secondaries); + } +}); + +/** + * Get list of secondaries + * @ignore + */ +Object.defineProperty(ReplSet.prototype, "arbiters", {enumerable: true + , get: function() { + return utils.objectToArray(this._state.arbiters); + } +}); + diff --git a/node_modules/mongodb/lib/mongodb/connection/repl_set/repl_set_state.js b/node_modules/mongodb/lib/mongodb/connection/repl_set/repl_set_state.js new file mode 100644 index 0000000..1fbd9c0 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/connection/repl_set/repl_set_state.js @@ -0,0 +1,74 @@ +/** + * Interval state object constructor + * + * @ignore + */ +var ReplSetState = function ReplSetState (replset) { + this.errorMessages = []; + this.secondaries = {}; + this.addresses = {}; + this.arbiters = {}; + this.passives = {}; + this.members = []; + this.errors = {}; + this.setName = null; + this.master = null; + this.replset = replset; +} + +ReplSetState.prototype.hasValidServers = function() { + var validServers = []; + if(this.master && this.master.isConnected()) return true; + + if(this.secondaries) { + var keys = Object.keys(this.secondaries) + for(var i = 0; i < keys.length; i++) { + if(this.secondaries[keys[i]].isConnected()) + return true; + } + } + + return false; +} + +ReplSetState.prototype.getAllReadServers = function() { + var candidate_servers = []; + for(var name in this.addresses) { + candidate_servers.push(this.addresses[name]); + } + + // Return all possible read candidates + return candidate_servers; +} + +ReplSetState.prototype.addServer = function(server, master) { + server.name = master.me; + + if(master.ismaster) { + this.master = server; + this.addresses[server.name] = server; + this.replset.emit('joined', "primary", master, server); + } else if(master.secondary) { + this.secondaries[server.name] = server; + this.addresses[server.name] = server; + this.replset.emit('joined', "secondary", master, server); + } else if(master.arbiters) { + this.arbiters[server.name] = server; + this.addresses[server.name] = server; + this.replset.emit('joined', "arbiter", master, server); + } +} + +ReplSetState.prototype.contains = function(host) { + return this.addresses[host] != null; +} + +ReplSetState.prototype.isPrimary = function(server) { + return this.master && this.master.name == server.name; +} + +ReplSetState.prototype.isSecondary = function(server) { + return this.secondaries[server.name] != null; +} + +exports.ReplSetState = ReplSetState; diff --git a/node_modules/mongodb/lib/mongodb/connection/repl_set/strategies/ping_strategy.js b/node_modules/mongodb/lib/mongodb/connection/repl_set/strategies/ping_strategy.js new file mode 100644 index 0000000..7e2a6c9 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/connection/repl_set/strategies/ping_strategy.js @@ -0,0 +1,366 @@ +var Server = require("../../server").Server + , format = require('util').format; + +// The ping strategy uses pings each server and records the +// elapsed time for the server so it can pick a server based on lowest +// return time for the db command {ping:true} +var PingStrategy = exports.PingStrategy = function(replicaset, secondaryAcceptableLatencyMS) { + this.replicaset = replicaset; + this.secondaryAcceptableLatencyMS = secondaryAcceptableLatencyMS; + this.state = 'disconnected'; + // Interval of ping attempts + this.pingInterval = replicaset.options.socketOptions.pingInterval || 5000; + // Timeout for ping response, default - no timeout + this.pingTimeout = replicaset.options.socketOptions.pingTimeout || null; + // Class instance + this.Db = require("../../../db").Db; + // Active db connections + this.dbs = {}; + // Current server index + this.index = 0; + // Logger api + this.Logger = null; +} + +// Starts any needed code +PingStrategy.prototype.start = function(callback) { + // already running? + if ('connected' == this.state) return; + + this.state = 'connected'; + + // Start ping server + this._pingServer(callback); +} + +// Stops and kills any processes running +PingStrategy.prototype.stop = function(callback) { + // Stop the ping process + this.state = 'disconnected'; + + // Stop all the server instances + for(var key in this.dbs) { + this.dbs[key].close(); + } + + // optional callback + callback && callback(null, null); +} + +PingStrategy.prototype.checkoutConnection = function(tags, secondaryCandidates) { + // Servers are picked based on the lowest ping time and then servers that lower than that + secondaryAcceptableLatencyMS + // Create a list of candidat servers, containing the primary if available + var candidateServers = []; + var self = this; + + // If we have not provided a list of candidate servers use the default setup + if(!Array.isArray(secondaryCandidates)) { + candidateServers = this.replicaset._state.master != null ? [this.replicaset._state.master] : []; + // Add all the secondaries + var keys = Object.keys(this.replicaset._state.secondaries); + for(var i = 0; i < keys.length; i++) { + candidateServers.push(this.replicaset._state.secondaries[keys[i]]) + } + } else { + candidateServers = secondaryCandidates; + } + + // Final list of eligable server + var finalCandidates = []; + + // If we have tags filter by tags + if(tags != null && typeof tags == 'object') { + // If we have an array or single tag selection + var tagObjects = Array.isArray(tags) ? tags : [tags]; + // Iterate over all tags until we find a candidate server + for(var _i = 0; _i < tagObjects.length; _i++) { + // Grab a tag object + var tagObject = tagObjects[_i]; + // Matching keys + var matchingKeys = Object.keys(tagObject); + // Remove any that are not tagged correctly + for(var i = 0; i < candidateServers.length; i++) { + var server = candidateServers[i]; + // If we have tags match + if(server.tags != null) { + var matching = true; + + // Ensure we have all the values + for(var j = 0; j < matchingKeys.length; j++) { + if(server.tags[matchingKeys[j]] != tagObject[matchingKeys[j]]) { + matching = false; + break; + } + } + + // If we have a match add it to the list of matching servers + if(matching) { + finalCandidates.push(server); + } + } + } + } + } else { + // Final array candidates + var finalCandidates = candidateServers; + } + + // Filter out any non-connected servers + finalCandidates = finalCandidates.filter(function(s) { + return s.isConnected(); + }) + + // Sort by ping time + finalCandidates.sort(function(a, b) { + return a.runtimeStats['pingMs'] > b.runtimeStats['pingMs']; + }); + + if(0 === finalCandidates.length) + return new Error("No replica set members available for query"); + + // find lowest server with a ping time + var lowest = finalCandidates.filter(function (server) { + return undefined != server.runtimeStats.pingMs; + })[0]; + + if(!lowest) { + lowest = finalCandidates[0]; + } + + // convert to integer + var lowestPing = lowest.runtimeStats.pingMs | 0; + + // determine acceptable latency + var acceptable = lowestPing + this.secondaryAcceptableLatencyMS; + + // remove any server responding slower than acceptable + var len = finalCandidates.length; + while(len--) { + if(finalCandidates[len].runtimeStats['pingMs'] > acceptable) { + finalCandidates.splice(len, 1); + } + } + + if(self.logger && self.logger.debug) { + self.logger.debug("Ping strategy selection order for tags", tags); + finalCandidates.forEach(function(c) { + self.logger.debug(format("%s:%s = %s ms", c.host, c.port, c.runtimeStats['pingMs']), null); + }) + } + + // If no candidates available return an error + if(finalCandidates.length == 0) + return new Error("No replica set members available for query"); + + // Ensure no we don't overflow + this.index = this.index % finalCandidates.length + // Pick a random acceptable server + var connection = finalCandidates[this.index].checkoutReader(); + // Point to next candidate (round robin style) + this.index = this.index + 1; + + if(self.logger && self.logger.debug) { + if(connection) + self.logger.debug(format("picked server %s:%s", connection.socketOptions.host, connection.socketOptions.port)); + } + + return connection; +} + +PingStrategy.prototype._pingServer = function(callback) { + var self = this; + + // Ping server function + var pingFunction = function() { + // Our state changed to disconnected or destroyed return + if(self.state == 'disconnected' || self.state == 'destroyed') return; + // If the replicaset is destroyed return + if(self.replicaset.isDestroyed() || self.replicaset._serverState == 'disconnected') return + + // Create a list of all servers we can send the ismaster command to + var allServers = self.replicaset._state.master != null ? [self.replicaset._state.master] : []; + + // Secondary keys + var keys = Object.keys(self.replicaset._state.secondaries); + // Add all secondaries + for(var i = 0; i < keys.length; i++) { + allServers.push(self.replicaset._state.secondaries[keys[i]]); + } + + // Number of server entries + var numberOfEntries = allServers.length; + + // We got keys + for(var i = 0; i < allServers.length; i++) { + + // We got a server instance + var server = allServers[i]; + + // Create a new server object, avoid using internal connections as they might + // be in an illegal state + new function(serverInstance) { + var _db = self.dbs[serverInstance.host + ":" + serverInstance.port]; + // If we have a db + if(_db != null) { + // Startup time of the command + var startTime = Date.now(); + + // Execute ping command in own scope + var _ping = function(__db, __serverInstance) { + + // Server unavailable. Checks only if pingTimeout defined & greater than 0 + var _failTimer = self.pingTimeout ? setTimeout(function () { + if(null != __serverInstance.runtimeStats && __serverInstance.isConnected()) { + __serverInstance.close(); + } + }, self.pingTimeout) : null; + + // Execute ping on this connection + __db.executeDbCommand({ping:1}, {failFast:true}, function(err) { + + // Server available + clearTimeout(_failTimer); + + // Emit the ping + self.replicaset.emit("ping", err, serverInstance); + + if(err) { + delete self.dbs[__db.serverConfig.host + ":" + __db.serverConfig.port]; + __db.close(); + return done(); + } + + if(null != __serverInstance.runtimeStats && __serverInstance.isConnected()) { + __serverInstance.runtimeStats['pingMs'] = Date.now() - startTime; + } + + __db.executeDbCommand({ismaster:1}, {failFast:true}, function(err, result) { + // Emit the ping + self.replicaset.emit("ping_ismaster", err, result, serverInstance); + + if(err) { + delete self.dbs[__db.serverConfig.host + ":" + __db.serverConfig.port]; + __db.close(); + return done(); + } + + // Process the ismaster for the server + if(result && result.documents && self.replicaset.processIsMaster) { + self.replicaset.processIsMaster(__serverInstance, result.documents[0]); + } + + // Done with the pinging + done(); + }); + }); + }; + // Ping + _ping(_db, serverInstance); + } else { + var connectTimeoutMS = self.replicaset.options.socketOptions + ? self.replicaset.options.socketOptions.connectTimeoutMS : 0 + + // Create a new master connection + var _server = new Server(serverInstance.host, serverInstance.port, { + auto_reconnect: false, + returnIsMasterResults: true, + slaveOk: true, + poolSize: 1, + socketOptions: { connectTimeoutMS: connectTimeoutMS }, + ssl: self.replicaset.options.ssl, + sslValidate: self.replicaset.options.sslValidate, + sslCA: self.replicaset.options.sslCA, + sslCert: self.replicaset.options.sslCert, + sslKey: self.replicaset.options.sslKey, + sslPass: self.replicaset.options.sslPass + }); + + // Create Db instance + var _db = new self.Db('local', _server, { safe: true }); + _db.on("close", function() { + delete self.dbs[this.serverConfig.host + ":" + this.serverConfig.port]; + }) + + var _ping = function(__db, __serverInstance) { + if(self.state == 'disconnected') { + self.stop(); + return; + } + + __db.open(function(err, db) { + // Emit ping connect + self.replicaset.emit("ping_connect", err, __serverInstance); + + if(self.state == 'disconnected' && __db != null) { + return __db.close(); + } + + if(err) { + delete self.dbs[__db.serverConfig.host + ":" + __db.serverConfig.port]; + __db.close(); + return done(); + } + + // Save instance + self.dbs[__db.serverConfig.host + ":" + __db.serverConfig.port] = __db; + + // Startup time of the command + var startTime = Date.now(); + + // Execute ping on this connection + __db.executeDbCommand({ping:1}, {failFast:true}, function(err) { + self.replicaset.emit("ping", err, __serverInstance); + + if(err) { + delete self.dbs[__db.serverConfig.host + ":" + __db.serverConfig.port]; + __db.close(); + return done(); + } + + if(null != __serverInstance.runtimeStats && __serverInstance.isConnected()) { + __serverInstance.runtimeStats['pingMs'] = Date.now() - startTime; + } + + __db.executeDbCommand({ismaster:1}, {failFast:true}, function(err, result) { + self.replicaset.emit("ping_ismaster", err, result, __serverInstance); + + if(err) { + delete self.dbs[__db.serverConfig.host + ":" + __db.serverConfig.port]; + __db.close(); + return done(); + } + + // Process the ismaster for the server + if(result && result.documents && self.replicaset.processIsMaster) { + self.replicaset.processIsMaster(__serverInstance, result.documents[0]); + } + + // Done with the pinging + done(); + }); + }); + }); + }; + + // Ping the server + _ping(_db, serverInstance); + } + + function done() { + // Adjust the number of checks + numberOfEntries--; + + // If we are done with all results coming back trigger ping again + if(0 === numberOfEntries && 'connected' == self.state) { + setTimeout(pingFunction, self.pingInterval); + } + } + }(server); + } + } + + // Start pingFunction + pingFunction(); + + callback && callback(null); +} diff --git a/node_modules/mongodb/lib/mongodb/connection/repl_set/strategies/statistics_strategy.js b/node_modules/mongodb/lib/mongodb/connection/repl_set/strategies/statistics_strategy.js new file mode 100644 index 0000000..32d23c3 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/connection/repl_set/strategies/statistics_strategy.js @@ -0,0 +1,93 @@ +// The Statistics strategy uses the measure of each end-start time for each +// query executed against the db to calculate the mean, variance and standard deviation +// and pick the server which the lowest mean and deviation +var StatisticsStrategy = exports.StatisticsStrategy = function(replicaset) { + this.replicaset = replicaset; + // Logger api + this.Logger = null; +} + +// Starts any needed code +StatisticsStrategy.prototype.start = function(callback) { + callback && callback(null, null); +} + +StatisticsStrategy.prototype.stop = function(callback) { + callback && callback(null, null); +} + +StatisticsStrategy.prototype.checkoutConnection = function(tags, secondaryCandidates) { + // Servers are picked based on the lowest ping time and then servers that lower than that + secondaryAcceptableLatencyMS + // Create a list of candidat servers, containing the primary if available + var candidateServers = []; + + // If we have not provided a list of candidate servers use the default setup + if(!Array.isArray(secondaryCandidates)) { + candidateServers = this.replicaset._state.master != null ? [this.replicaset._state.master] : []; + // Add all the secondaries + var keys = Object.keys(this.replicaset._state.secondaries); + for(var i = 0; i < keys.length; i++) { + candidateServers.push(this.replicaset._state.secondaries[keys[i]]) + } + } else { + candidateServers = secondaryCandidates; + } + + // Final list of eligable server + var finalCandidates = []; + + // If we have tags filter by tags + if(tags != null && typeof tags == 'object') { + // If we have an array or single tag selection + var tagObjects = Array.isArray(tags) ? tags : [tags]; + // Iterate over all tags until we find a candidate server + for(var _i = 0; _i < tagObjects.length; _i++) { + // Grab a tag object + var tagObject = tagObjects[_i]; + // Matching keys + var matchingKeys = Object.keys(tagObject); + // Remove any that are not tagged correctly + for(var i = 0; i < candidateServers.length; i++) { + var server = candidateServers[i]; + // If we have tags match + if(server.tags != null) { + var matching = true; + + // Ensure we have all the values + for(var j = 0; j < matchingKeys.length; j++) { + if(server.tags[matchingKeys[j]] != tagObject[matchingKeys[j]]) { + matching = false; + break; + } + } + + // If we have a match add it to the list of matching servers + if(matching) { + finalCandidates.push(server); + } + } + } + } + } else { + // Final array candidates + var finalCandidates = candidateServers; + } + + finalCandidates.sort(function(a, b) { + return a.runtimeStats.queryStats.sScore > b.runtimeStats.queryStats.sScore; + }); + + // If no candidates available return an error + if(finalCandidates.length == 0) return new Error("No replica set members available for query"); + + var bestCandidates = [finalCandidates[0]]; + for (var i = 1; i < finalCandidates.length; ++i) { + if (finalCandidates[i].runtimeStats.queryStats.sScore > finalCandidates[i - 1].runtimeStats.queryStats.sScore) { + break; + } else { + bestCandidates.push(finalCandidates[i]); + } + } + + return bestCandidates[Math.floor(Math.random() * bestCandidates.length)].checkoutReader(); +} diff --git a/node_modules/mongodb/lib/mongodb/connection/server.js b/node_modules/mongodb/lib/mongodb/connection/server.js new file mode 100644 index 0000000..dfff183 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/connection/server.js @@ -0,0 +1,945 @@ +var Connection = require('./connection').Connection, + ReadPreference = require('./read_preference').ReadPreference, + DbCommand = require('../commands/db_command').DbCommand, + MongoReply = require('../responses/mongo_reply').MongoReply, + ConnectionPool = require('./connection_pool').ConnectionPool, + EventEmitter = require('events').EventEmitter, + ServerCapabilities = require('./server_capabilities').ServerCapabilities, + Base = require('./base').Base, + format = require('util').format, + utils = require('../utils'), + timers = require('timers'), + inherits = require('util').inherits; + +// Set processor, setImmediate if 0.10 otherwise nextTick +var processor = require('../utils').processor(); + +/** + * Class representing a single MongoDB Server connection + * + * Options + * - **ssl** {Boolean, default:false}, use ssl connection (needs to have a mongod server with ssl support) + * - **sslValidate** {Boolean, default:false}, validate mongod server certificate against ca (needs to have a mongod server with ssl support, 2.4 or higher) + * - **sslCA** {Array, default:null}, Array of valid certificates either as Buffers or Strings (needs to have a mongod server with ssl support, 2.4 or higher) + * - **sslCert** {Buffer/String, default:null}, String or buffer containing the certificate we wish to present (needs to have a mongod server with ssl support, 2.4 or higher) + * - **sslKey** {Buffer/String, default:null}, String or buffer containing the certificate private key we wish to present (needs to have a mongod server with ssl support, 2.4 or higher) + * - **sslPass** {Buffer/String, default:null}, String or buffer containing the certificate password (needs to have a mongod server with ssl support, 2.4 or higher) + * - **poolSize** {Number, default:5}, number of connections in the connection pool, set to 5 as default for legacy reasons. + * - **socketOptions** {Object, default:null}, an object containing socket options to use (noDelay:(boolean), keepAlive:(number), connectTimeoutMS:(number), socketTimeoutMS:(number)) + * - **logger** {Object, default:null}, an object representing a logger that you want to use, needs to support functions debug, log, error **({error:function(message, object) {}, log:function(message, object) {}, debug:function(message, object) {}})**. + * - **auto_reconnect** {Boolean, default:false}, reconnect on error. + * - **disableDriverBSONSizeCheck** {Boolean, default:false}, force the server to error if the BSON message is to big + * + * @class Represents a Server connection. + * @param {String} host the server host + * @param {Number} port the server port + * @param {Object} [options] optional options for insert command + */ +function Server(host, port, options) { + // Set up Server instance + if(!(this instanceof Server)) return new Server(host, port, options); + + // Set up event emitter + Base.call(this); + + // Ensure correct values + if(port != null && typeof port == 'object') { + options = port; + port = Connection.DEFAULT_PORT; + } + + var self = this; + this.host = host; + this.port = port; + this.options = options == null ? {} : options; + this.internalConnection; + this.internalMaster = false; + this.connected = false; + this.poolSize = this.options.poolSize == null ? 5 : this.options.poolSize; + this.disableDriverBSONSizeCheck = this.options.disableDriverBSONSizeCheck != null ? this.options.disableDriverBSONSizeCheck : false; + this._used = false; + this.replicasetInstance = null; + + // Emit open setup + this.emitOpen = this.options.emitOpen || true; + // Set ssl as connection method + this.ssl = this.options.ssl == null ? false : this.options.ssl; + // Set ssl validation + this.sslValidate = this.options.sslValidate == null ? false : this.options.sslValidate; + // Set the ssl certificate authority (array of Buffer/String keys) + this.sslCA = Array.isArray(this.options.sslCA) ? this.options.sslCA : null; + // Certificate to present to the server + this.sslCert = this.options.sslCert; + // Certificate private key if in separate file + this.sslKey = this.options.sslKey; + // Password to unlock private key + this.sslPass = this.options.sslPass; + // Server capabilities + this.serverCapabilities = null; + // Set server name + this.name = format("%s:%s", host, port); + + // Ensure we are not trying to validate with no list of certificates + if(this.sslValidate && (!Array.isArray(this.sslCA) || this.sslCA.length == 0)) { + throw new Error("The driver expects an Array of CA certificates in the sslCA parameter when enabling sslValidate"); + } + + // Contains the isMaster information returned from the server + this.isMasterDoc; + + // Set default connection pool options + this.socketOptions = this.options.socketOptions != null ? this.options.socketOptions : {}; + if(this.disableDriverBSONSizeCheck) this.socketOptions.disableDriverBSONSizeCheck = this.disableDriverBSONSizeCheck; + + // Set ssl up if it's defined + if(this.ssl) { + this.socketOptions.ssl = true; + // Set ssl validation + this.socketOptions.sslValidate = this.sslValidate == null ? false : this.sslValidate; + // Set the ssl certificate authority (array of Buffer/String keys) + this.socketOptions.sslCA = Array.isArray(this.sslCA) ? this.sslCA : null; + // Set certificate to present + this.socketOptions.sslCert = this.sslCert; + // Set certificate to present + this.socketOptions.sslKey = this.sslKey; + // Password to unlock private key + this.socketOptions.sslPass = this.sslPass; + } + + // Set up logger if any set + this.logger = this.options.logger != null + && (typeof this.options.logger.debug == 'function') + && (typeof this.options.logger.error == 'function') + && (typeof this.options.logger.log == 'function') + ? this.options.logger : {error:function(message, object) {}, log:function(message, object) {}, debug:function(message, object) {}}; + + // Just keeps list of events we allow + this.eventHandlers = {error:[], parseError:[], poolReady:[], message:[], close:[], timeout:[]}; + // Internal state of server connection + this._serverState = 'disconnected'; + // Contains state information about server connection + this._state = {'runtimeStats': {'queryStats':new RunningStats()}}; + // Do we record server stats or not + this.recordQueryStats = false; + + // Allow setting the socketTimeoutMS on all connections + // to work around issues such as secondaries blocking due to compaction + utils.setSocketTimeoutProperty(this, this.socketOptions); +}; + +/** + * @ignore + */ +inherits(Server, Base); + +// +// Deprecated, USE ReadPreferences class +// +Server.READ_PRIMARY = ReadPreference.PRIMARY; +Server.READ_SECONDARY = ReadPreference.SECONDARY_PREFERRED; +Server.READ_SECONDARY_ONLY = ReadPreference.SECONDARY; + +/** + * Always ourselves + * @ignore + */ +Server.prototype.setReadPreference = function(readPreference) { + this._readPreference = readPreference; +} + +/** + * @ignore + */ +Server.prototype.isMongos = function() { + return this.isMasterDoc != null && this.isMasterDoc['msg'] == "isdbgrid" ? true : false; +} + +/** + * @ignore + */ +Server.prototype._isUsed = function() { + return this._used; +} + +/** + * @ignore + */ +Server.prototype.close = function(callback) { + // Set server status as disconnected + this._serverState = 'destroyed'; + // Remove all local listeners + this.removeAllListeners(); + + if(this.connectionPool != null) { + // Remove all the listeners on the pool so it does not fire messages all over the place + this.connectionPool.removeAllEventListeners(); + // Close the connection if it's open + this.connectionPool.stop(true); + } + + // Emit close event + if(this.db && !this.isSetMember()) { + var self = this; + processor(function() { + self._emitAcrossAllDbInstances(self, null, "close", null, null, true) + }) + + // Flush out any remaining call handlers + self._flushAllCallHandlers(utils.toError("Connection Closed By Application")); + } + + // Peform callback if present + if(typeof callback === 'function') callback(null); +}; + +Server.prototype.isDestroyed = function() { + return this._serverState == 'destroyed'; +} + +/** + * @ignore + */ +Server.prototype.isConnected = function() { + return this.connectionPool != null && this.connectionPool.isConnected(); +} + +/** + * @ignore + */ +Server.prototype.canWrite = Server.prototype.isConnected; +Server.prototype.canRead = Server.prototype.isConnected; + +Server.prototype.isAutoReconnect = function() { + if(this.isSetMember()) return false; + return this.options.auto_reconnect != null ? this.options.auto_reconnect : true; +} + +/** + * @ignore + */ +Server.prototype.allServerInstances = function() { + return [this]; +} + +/** + * @ignore + */ +Server.prototype.isSetMember = function() { + return this.replicasetInstance != null || this.mongosInstance != null; +} + +/** + * @ignore + */ +Server.prototype.setSocketOptions = function(options) { + var connections = this.allRawConnections(); + for(var i = 0; i < connections.length; i++) { + connections[i].setSocketOptions(options); + } +} + +/** + * Assigns a replica set to this `server`. + * + * @param {ReplSet} replset + * @ignore + */ +Server.prototype.assignReplicaSet = function (replset) { + this.replicasetInstance = replset; + this.inheritReplSetOptionsFrom(replset); + this.enableRecordQueryStats(replset.recordQueryStats); +} + +/** + * Takes needed options from `replset` and overwrites + * our own options. + * + * @param {ReplSet} replset + * @ignore + */ +Server.prototype.inheritReplSetOptionsFrom = function (replset) { + this.socketOptions = {}; + this.socketOptions.connectTimeoutMS = replset.options.socketOptions.connectTimeoutMS || 30000; + + if(replset.options.ssl) { + // Set ssl on + this.socketOptions.ssl = true; + // Set ssl validation + this.socketOptions.sslValidate = replset.options.sslValidate == null ? false : replset.options.sslValidate; + // Set the ssl certificate authority (array of Buffer/String keys) + this.socketOptions.sslCA = Array.isArray(replset.options.sslCA) ? replset.options.sslCA : null; + // Set certificate to present + this.socketOptions.sslCert = replset.options.sslCert; + // Set certificate to present + this.socketOptions.sslKey = replset.options.sslKey; + // Password to unlock private key + this.socketOptions.sslPass = replset.options.sslPass; + } + + // If a socket option object exists clone it + if(utils.isObject(replset.options.socketOptions)) { + var keys = Object.keys(replset.options.socketOptions); + for(var i = 0; i < keys.length; i++) + this.socketOptions[keys[i]] = replset.options.socketOptions[keys[i]]; + } +} + +/** + * Opens this server connection. + * + * @ignore + */ +Server.prototype.connect = function(dbInstance, options, callback) { + if('function' === typeof options) callback = options, options = {}; + if(options == null) options = {}; + if(!('function' === typeof callback)) callback = null; + var self = this; + // Save the options + this.options = options; + + // Currently needed to work around problems with multiple connections in a pool with ssl + // TODO fix if possible + if(this.ssl == true) { + // Set up socket options for ssl + this.socketOptions.ssl = true; + // Set ssl validation + this.socketOptions.sslValidate = this.sslValidate == null ? false : this.sslValidate; + // Set the ssl certificate authority (array of Buffer/String keys) + this.socketOptions.sslCA = Array.isArray(this.sslCA) ? this.sslCA : null; + // Set certificate to present + this.socketOptions.sslCert = this.sslCert; + // Set certificate to present + this.socketOptions.sslKey = this.sslKey; + // Password to unlock private key + this.socketOptions.sslPass = this.sslPass; + } + + // Let's connect + var server = this; + // Let's us override the main receiver of events + var eventReceiver = options.eventReceiver != null ? options.eventReceiver : this; + // Save reference to dbInstance + this.db = dbInstance; // `db` property matches ReplSet and Mongos + this.dbInstances = [dbInstance]; + + // Force connection pool if there is one + if(server.connectionPool) server.connectionPool.stop(); + // Set server state to connecting + this._serverState = 'connecting'; + + if(server.connectionPool != null) { + // Remove all the listeners on the pool so it does not fire messages all over the place + this.connectionPool.removeAllEventListeners(); + // Close the connection if it's open + this.connectionPool.stop(true); + } + + this.connectionPool = new ConnectionPool(this.host, this.port, this.poolSize, dbInstance.bson, this.socketOptions); + var connectionPool = this.connectionPool; + // If ssl is not enabled don't wait between the pool connections + if(this.ssl == null || !this.ssl) connectionPool._timeToWait = null; + // Set logger on pool + connectionPool.logger = this.logger; + connectionPool.bson = dbInstance.bson; + + // Set basic parameters passed in + var returnIsMasterResults = options.returnIsMasterResults == null ? false : options.returnIsMasterResults; + + // Create a default connect handler, overriden when using replicasets + var connectCallback = function(_server) { + return function(err, reply) { + // ensure no callbacks get called twice + var internalCallback = callback; + callback = null; + + // Assign the server + _server = _server != null ? _server : server; + + // If something close down the connection and removed the callback before + // proxy killed connection etc, ignore the erorr as close event was isssued + if(err != null && internalCallback == null) return; + // Internal callback + if(err != null) return internalCallback(err, null, _server); + _server.master = reply.documents[0].ismaster == 1 ? true : false; + _server.connectionPool.setMaxBsonSize(reply.documents[0].maxBsonObjectSize); + _server.connectionPool.setMaxMessageSizeBytes(reply.documents[0].maxMessageSizeBytes); + _server.connectionPool.setMaxWriteBatchSize(reply.documents[0].maxWriteBatchSize); + // Set server state to connEcted + _server._serverState = 'connected'; + // Set server as connected + _server.connected = true; + // Save document returned so we can query it + _server.isMasterDoc = reply.documents[0]; + + if(self.emitOpen) { + _server._emitAcrossAllDbInstances(_server, eventReceiver, "open", null, returnIsMasterResults ? reply : null, null); + self.emitOpen = false; + } else { + _server._emitAcrossAllDbInstances(_server, eventReceiver, "reconnect", null, returnIsMasterResults ? reply : null, null); + } + + // Set server capabilities + server.serverCapabilities = new ServerCapabilities(_server.isMasterDoc); + + // If we have it set to returnIsMasterResults + if(returnIsMasterResults) { + internalCallback(null, reply, _server); + } else { + internalCallback(null, dbInstance, _server); + } + } + }; + + // Let's us override the main connect callback + var connectHandler = options.connectHandler == null ? connectCallback(server) : options.connectHandler; + + // Set up on connect method + connectionPool.on("poolReady", function() { + // Create db command and Add the callback to the list of callbacks by the request id (mapping outgoing messages to correct callbacks) + var db_command = DbCommand.NcreateIsMasterCommand(dbInstance, dbInstance.databaseName); + // Check out a reader from the pool + var connection = connectionPool.checkoutConnection(); + // Register handler for messages + server._registerHandler(db_command, false, connection, connectHandler); + // Write the command out + connection.write(db_command); + }) + + // Set up item connection + connectionPool.on("message", function(message) { + // Attempt to parse the message + try { + // Create a new mongo reply + var mongoReply = new MongoReply() + // Parse the header + mongoReply.parseHeader(message, connectionPool.bson) + + // If message size is not the same as the buffer size + // something went terribly wrong somewhere + if(mongoReply.messageLength != message.length) { + // Emit the error + if(eventReceiver.listeners("error") && eventReceiver.listeners("error").length > 0) eventReceiver.emit("error", new Error("bson length is different from message length"), server); + // Remove all listeners + server.removeAllListeners(); + } else { + var startDate = new Date().getTime(); + + // Callback instance + var callbackInfo = server._findHandler(mongoReply.responseTo.toString()); + // Abort if not a valid callbackInfo, don't try to call it + if(callbackInfo == null || callbackInfo.info == null) return; + + // The command executed another request, log the handler again under that request id + if(mongoReply.requestId > 0 && mongoReply.cursorId.toString() != "0" + && callbackInfo && callbackInfo.info && callbackInfo.info.exhaust) { + server._reRegisterHandler(mongoReply.requestId, callbackInfo); + } + + // Parse the body + mongoReply.parseBody(message, connectionPool.bson, callbackInfo.info.raw, function(err) { + if(err != null) { + // If pool connection is already closed + if(server._serverState === 'disconnected') return; + // Set server state to disconnected + server._serverState = 'disconnected'; + // Remove all listeners and close the connection pool + server.removeAllListeners(); + connectionPool.stop(true); + + // If we have a callback return the error + if(typeof callback === 'function') { + // ensure no callbacks get called twice + var internalCallback = callback; + callback = null; + // Perform callback + internalCallback(err, null, server); + } else if(server.isSetMember()) { + if(server.listeners("parseError") && server.listeners("parseError").length > 0) server.emit("parseError", utils.toError(err), server); + } else { + if(eventReceiver.listeners("parseError") && eventReceiver.listeners("parseError").length > 0) eventReceiver.emit("parseError", utils.toError(err), server); + } + + // If we are a single server connection fire errors correctly + if(!server.isSetMember()) { + // Fire all callback errors + server.__executeAllCallbacksWithError(err); + // Emit error + server._emitAcrossAllDbInstances(server, eventReceiver, "parseError", server, null, true); + } + // Short cut + return; + } + + // Let's record the stats info if it's enabled + if(server.recordQueryStats == true && server._state['runtimeStats'] != null + && server._state.runtimeStats['queryStats'] instanceof RunningStats) { + // Add data point to the running statistics object + server._state.runtimeStats.queryStats.push(new Date().getTime() - callbackInfo.info.start); + } + + // Dispatch the call + server._callHandler(mongoReply.responseTo, mongoReply, null); + + // If we have an error about the server not being master or primary + if((mongoReply.responseFlag & (1 << 1)) != 0 + && mongoReply.documents[0].code + && mongoReply.documents[0].code == 13436) { + server.close(); + } + }); + } + } catch (err) { + // Throw error in next tick + processor(function() { + throw err; + }) + } + }); + + // Handle timeout + connectionPool.on("timeout", function(err) { + // If pool connection is already closed + if(server._serverState === 'disconnected' + || server._serverState === 'destroyed') return; + // Set server state to disconnected + server._serverState = 'disconnected'; + // If we have a callback return the error + if(typeof callback === 'function') { + // ensure no callbacks get called twice + var internalCallback = callback; + callback = null; + // Perform callback + internalCallback(err, null, server); + } else if(server.isSetMember()) { + if(server.listeners("timeout") && server.listeners("timeout").length > 0) server.emit("timeout", err, server); + } else { + if(eventReceiver.listeners("timeout") && eventReceiver.listeners("timeout").length > 0) eventReceiver.emit("timeout", err, server); + } + + // If we are a single server connection fire errors correctly + if(!server.isSetMember()) { + // Fire all callback errors + server.__executeAllCallbacksWithError(err); + // Emit error + server._emitAcrossAllDbInstances(server, eventReceiver, "timeout", err, server, true); + } + + // If we have autoConnect enabled let's fire up an attempt to reconnect + if(server.isAutoReconnect() + && !server.isSetMember() + && (server._serverState != 'destroyed') + && !server._reconnectInProgreess) { + // Set the number of retries + server._reconnect_retries = server.db.numberOfRetries; + // Attempt reconnect + server._reconnectInProgreess = true; + setTimeout(__attemptReconnect(server), server.db.retryMiliSeconds); + } + }); + + // Handle errors + connectionPool.on("error", function(message, connection, error_options) { + // If pool connection is already closed + if(server._serverState === 'disconnected' + || server._serverState === 'destroyed') return; + + // Set server state to disconnected + server._serverState = 'disconnected'; + // Error message + var error_message = new Error(message && message.err ? message.err : message); + // Error message coming from ssl + if(error_options && error_options.ssl) error_message.ssl = true; + + // If we have a callback return the error + if(typeof callback === 'function') { + // ensure no callbacks get called twice + var internalCallback = callback; + callback = null; + // Perform callback + internalCallback(error_message, null, server); + } else if(server.isSetMember()) { + if(server.listeners("error") && server.listeners("error").length > 0) server.emit("error", error_message, server); + } else { + if(eventReceiver.listeners("error") && eventReceiver.listeners("error").length > 0) eventReceiver.emit("error", error_message, server); + } + + // If we are a single server connection fire errors correctly + if(!server.isSetMember()) { + // Fire all callback errors + server.__executeAllCallbacksWithError(error_message); + // Emit error + server._emitAcrossAllDbInstances(server, eventReceiver, "error", error_message, server, true); + } + + // If we have autoConnect enabled let's fire up an attempt to reconnect + if(server.isAutoReconnect() + && !server.isSetMember() + && (server._serverState != 'destroyed') + && !server._reconnectInProgreess) { + + // Set the number of retries + server._reconnect_retries = server.db.numberOfRetries; + // Attempt reconnect + server._reconnectInProgreess = true; + setTimeout(__attemptReconnect(server), server.db.retryMiliSeconds); + } + }); + + // Handle close events + connectionPool.on("close", function() { + // If pool connection is already closed + if(server._serverState === 'disconnected' + || server._serverState === 'destroyed') return; + // Set server state to disconnected + server._serverState = 'disconnected'; + // If we have a callback return the error + if(typeof callback == 'function') { + // ensure no callbacks get called twice + var internalCallback = callback; + callback = null; + // Perform callback + internalCallback(new Error("connection closed"), null, server); + } else if(server.isSetMember()) { + if(server.listeners("close") && server.listeners("close").length > 0) server.emit("close", new Error("connection closed"), server); + } else { + if(eventReceiver.listeners("close") && eventReceiver.listeners("close").length > 0) eventReceiver.emit("close", new Error("connection closed"), server); + } + + // If we are a single server connection fire errors correctly + if(!server.isSetMember()) { + // Fire all callback errors + server.__executeAllCallbacksWithError(new Error("connection closed")); + // Emit error + server._emitAcrossAllDbInstances(server, eventReceiver, "close", server, null, true); + } + + // If we have autoConnect enabled let's fire up an attempt to reconnect + if(server.isAutoReconnect() + && !server.isSetMember() + && (server._serverState != 'destroyed') + && !server._reconnectInProgreess) { + + // Set the number of retries + server._reconnect_retries = server.db.numberOfRetries; + // Attempt reconnect + server._reconnectInProgreess = true; + setTimeout(__attemptReconnect(server), server.db.retryMiliSeconds); + } + }); + + /** + * @ignore + */ + var __attemptReconnect = function(server) { + return function() { + // Attempt reconnect + server.connect(server.db, server.options, function(err, result) { + server._reconnect_retries = server._reconnect_retries - 1; + + if(err) { + // Retry + if(server._reconnect_retries == 0 || server._serverState == 'destroyed') { + server._serverState = 'connected'; + server._reconnectInProgreess = false + // Fire all callback errors + return server.__executeAllCallbacksWithError(new Error("failed to reconnect to server")); + } else { + return setTimeout(__attemptReconnect(server), server.db.retryMiliSeconds); + } + } else { + // Set as authenticating (isConnected will be false) + server._serverState = 'authenticating'; + // Apply any auths, we don't try to catch any errors here + // as there are nowhere to simply propagate them to + self._apply_auths(server.db, function(err, result) { + server._serverState = 'connected'; + server._reconnectInProgreess = false; + + // Execute any buffered reads and writes + server._commandsStore.execute_queries(); + server._commandsStore.execute_writes(); + // Emit reconnect event + server.emit('reconnect'); + }); + } + }); + } + } + + // If we have a parser error we are in an unknown state, close everything and emit + // error + connectionPool.on("parseError", function(err) { + // If pool connection is already closed + if(server._serverState === 'disconnected' + || server._serverState === 'destroyed') return; + // Set server state to disconnected + server._serverState = 'disconnected'; + // If we have a callback return the error + if(typeof callback === 'function') { + // ensure no callbacks get called twice + var internalCallback = callback; + callback = null; + // Perform callback + internalCallback(utils.toError(err), null, server); + } else if(server.isSetMember()) { + if(server.listeners("parseError") && server.listeners("parseError").length > 0) server.emit("parseError", utils.toError(err), server); + } else { + if(eventReceiver.listeners("parseError") && eventReceiver.listeners("parseError").length > 0) eventReceiver.emit("parseError", utils.toError(err), server); + } + + // If we are a single server connection fire errors correctly + if(!server.isSetMember()) { + // Fire all callback errors + server.__executeAllCallbacksWithError(utils.toError(err)); + // Emit error + server._emitAcrossAllDbInstances(server, eventReceiver, "parseError", server, null, true); + // Emit close event + if(eventReceiver.listeners("close") && eventReceiver.listeners("close").length > 0) eventReceiver.emit("close", new Error("connection closed"), server); } + }); + + // Boot up connection poole, pass in a locator of callbacks + connectionPool.start(); +} + +/** + * @ignore + */ +Server.prototype.allRawConnections = function() { + return this.connectionPool != null ? this.connectionPool.getAllConnections() : []; +} + +/** + * Check if a writer can be provided + * @ignore + */ +var canCheckoutWriter = function(self, read) { + // We cannot write to an arbiter or secondary server + if(self.isMasterDoc && self.isMasterDoc['arbiterOnly'] == true) { + return new Error("Cannot write to an arbiter"); + } if(self.isMasterDoc && self.isMasterDoc['secondary'] == true) { + return new Error("Cannot write to a secondary"); + } else if(read == true && self._readPreference == ReadPreference.SECONDARY && self.isMasterDoc && self.isMasterDoc['ismaster'] == true) { + return new Error("Cannot read from primary when secondary only specified"); + } else if(!self.isMasterDoc) { + return new Error("Cannot determine state of server"); + } + + // Return no error + return null; +} + +/** + * @ignore + */ +Server.prototype.checkoutWriter = function(read) { + if(this._serverState == 'disconnected' || this._serverState == 'destroyed') + return null; + if(read == true) return this.connectionPool.checkoutConnection(); + // Check if are allowed to do a checkout (if we try to use an arbiter f.ex) + var result = canCheckoutWriter(this, read); + // If the result is null check out a writer + if(result == null && this.connectionPool != null) { + var connection = this.connectionPool.checkoutConnection(); + // Add server capabilities to the connection + if(connection) + connection.serverCapabilities = this.serverCapabilities; + return connection; + } else if(result == null) { + return null; + } else { + return result; + } +} + +/** + * Check if a reader can be provided + * @ignore + */ +var canCheckoutReader = function(self) { + // We cannot write to an arbiter or secondary server + if(self.isMasterDoc && self.isMasterDoc['arbiterOnly'] == true && self.isSetMember()) { + return new Error("Cannot write to an arbiter"); + } else if(self._readPreference != null) { + // If the read preference is Primary and the instance is not a master return an error + if((self._readPreference == ReadPreference.PRIMARY) && self.isMasterDoc && self.isMasterDoc['ismaster'] != true) { + return new Error("Read preference is Server.PRIMARY and server is not master"); + } else if(self._readPreference == ReadPreference.SECONDARY && self.isMasterDoc && self.isMasterDoc['ismaster'] == true) { + return new Error("Cannot read from primary when secondary only specified"); + } + } else if(!self.isMasterDoc) { + return new Error("Cannot determine state of server"); + } + + // Return no error + return null; +} + +/** + * @ignore + */ +Server.prototype.checkoutReader = function(read) { + if(this._serverState == 'disconnected' || this._serverState == 'destroyed') + return null; + // Check if are allowed to do a checkout (if we try to use an arbiter f.ex) + var result = canCheckoutReader(this); + // If the result is null check out a writer + if(result == null && this.connectionPool != null) { + var connection = this.connectionPool.checkoutConnection(); + // Add server capabilities to the connection + if(connection) + connection.serverCapabilities = this.serverCapabilities; + return connection; + } else if(result == null) { + return null; + } else { + return result; + } +} + +/** + * @ignore + */ +Server.prototype.enableRecordQueryStats = function(enable) { + this.recordQueryStats = enable; +} + +/** + * Internal statistics object used for calculating average and standard devitation on + * running queries + * @ignore + */ +var RunningStats = function() { + var self = this; + this.m_n = 0; + this.m_oldM = 0.0; + this.m_oldS = 0.0; + this.m_newM = 0.0; + this.m_newS = 0.0; + + // Define getters + Object.defineProperty(this, "numDataValues", { enumerable: true + , get: function () { return this.m_n; } + }); + + Object.defineProperty(this, "mean", { enumerable: true + , get: function () { return (this.m_n > 0) ? this.m_newM : 0.0; } + }); + + Object.defineProperty(this, "variance", { enumerable: true + , get: function () { return ((this.m_n > 1) ? this.m_newS/(this.m_n - 1) : 0.0); } + }); + + Object.defineProperty(this, "standardDeviation", { enumerable: true + , get: function () { return Math.sqrt(this.variance); } + }); + + Object.defineProperty(this, "sScore", { enumerable: true + , get: function () { + var bottom = this.mean + this.standardDeviation; + if(bottom == 0) return 0; + return ((2 * this.mean * this.standardDeviation)/(bottom)); + } + }); +} + +/** + * @ignore + */ +RunningStats.prototype.push = function(x) { + // Update the number of samples + this.m_n = this.m_n + 1; + + // See Knuth TAOCP vol 2, 3rd edition, page 232 + if(this.m_n == 1) { + this.m_oldM = this.m_newM = x; + this.m_oldS = 0.0; + } else { + this.m_newM = this.m_oldM + (x - this.m_oldM) / this.m_n; + this.m_newS = this.m_oldS + (x - this.m_oldM) * (x - this.m_newM); + // set up for next iteration + this.m_oldM = this.m_newM; + this.m_oldS = this.m_newS; + } +} + +/** + * @ignore + */ +Object.defineProperty(Server.prototype, "autoReconnect", { enumerable: true + , get: function () { + return this.options['auto_reconnect'] == null ? false : this.options['auto_reconnect']; + } +}); + +/** + * @ignore + */ +Object.defineProperty(Server.prototype, "connection", { enumerable: true + , get: function () { + return this.internalConnection; + } + , set: function(connection) { + this.internalConnection = connection; + } +}); + +/** + * @ignore + */ +Object.defineProperty(Server.prototype, "master", { enumerable: true + , get: function () { + return this.internalMaster; + } + , set: function(value) { + this.internalMaster = value; + } +}); + +/** + * @ignore + */ +Object.defineProperty(Server.prototype, "primary", { enumerable: true + , get: function () { + return this; + } +}); + +/** + * Getter for query Stats + * @ignore + */ +Object.defineProperty(Server.prototype, "queryStats", { enumerable: true + , get: function () { + return this._state.runtimeStats.queryStats; + } +}); + +/** + * @ignore + */ +Object.defineProperty(Server.prototype, "runtimeStats", { enumerable: true + , get: function () { + return this._state.runtimeStats; + } +}); + +/** + * Get Read Preference method + * @ignore + */ +Object.defineProperty(Server.prototype, "readPreference", { enumerable: true + , get: function () { + if(this._readPreference == null && this.readSecondary) { + return Server.READ_SECONDARY; + } else if(this._readPreference == null && !this.readSecondary) { + return Server.READ_PRIMARY; + } else { + return this._readPreference; + } + } +}); + +/** + * @ignore + */ +exports.Server = Server; diff --git a/node_modules/mongodb/lib/mongodb/connection/server_capabilities.js b/node_modules/mongodb/lib/mongodb/connection/server_capabilities.js new file mode 100644 index 0000000..68d42ea --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/connection/server_capabilities.js @@ -0,0 +1,48 @@ +var ServerCapabilities = function(isMasterResult) { + // Capabilities + var aggregationCursor = false; + var writeCommands = false; + var textSearch = false; + var authCommands = false; + var maxNumberOfDocsInBatch = isMasterResult.maxWriteBatchSize || 1000; + + if(isMasterResult.minWireVersion >= 0) { + textSearch = true; + } + + if(isMasterResult.maxWireVersion >= 1) { + aggregationCursor = true; + authCommands = true; + } + + if(isMasterResult.maxWireVersion >= 2) { + writeCommands = true; + } + + // If no min or max wire version set to 0 + if(isMasterResult.minWireVersion == null) { + isMasterResult.minWireVersion = 0; + } + + if(isMasterResult.maxWireVersion == null) { + isMasterResult.maxWireVersion = 0; + } + + // Map up read only parameters + setup_get_property(this, "hasAggregationCursor", aggregationCursor); + setup_get_property(this, "hasWriteCommands", writeCommands); + setup_get_property(this, "hasTextSearch", textSearch); + setup_get_property(this, "hasAuthCommands", authCommands); + setup_get_property(this, "minWireVersion", isMasterResult.minWireVersion); + setup_get_property(this, "maxWireVersion", isMasterResult.maxWireVersion); + setup_get_property(this, "maxNumberOfDocsInBatch", maxNumberOfDocsInBatch); +} + +var setup_get_property = function(object, name, value) { + Object.defineProperty(object, name, { + enumerable: true + , get: function () { return value; } + }); +} + +exports.ServerCapabilities = ServerCapabilities; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/connection/url_parser.js b/node_modules/mongodb/lib/mongodb/connection/url_parser.js new file mode 100644 index 0000000..4db9579 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/connection/url_parser.js @@ -0,0 +1,265 @@ +var fs = require('fs'), + ReadPreference = require('./read_preference').ReadPreference; + +exports.parse = function(url, options) { + // Ensure we have a default options object if none set + options = options || {}; + // Variables + var connection_part = ''; + var auth_part = ''; + var query_string_part = ''; + var dbName = 'admin'; + + // Must start with mongodb + if(url.indexOf("mongodb://") != 0) + throw Error("URL must be in the format mongodb://user:pass@host:port/dbname"); + // If we have a ? mark cut the query elements off + if(url.indexOf("?") != -1) { + query_string_part = url.substr(url.indexOf("?") + 1); + connection_part = url.substring("mongodb://".length, url.indexOf("?")) + } else { + connection_part = url.substring("mongodb://".length); + } + + // Check if we have auth params + if(connection_part.indexOf("@") != -1) { + auth_part = connection_part.split("@")[0]; + connection_part = connection_part.split("@")[1]; + } + + // Check if the connection string has a db + if(connection_part.indexOf(".sock") != -1) { + if(connection_part.indexOf(".sock/") != -1) { + dbName = connection_part.split(".sock/")[1]; + connection_part = connection_part.split("/", connection_part.indexOf(".sock") + ".sock".length); + } + } else if(connection_part.indexOf("/") != -1) { + dbName = connection_part.split("/")[1]; + connection_part = connection_part.split("/")[0]; + } + + // Result object + var object = {}; + + // Pick apart the authentication part of the string + var authPart = auth_part || ''; + var auth = authPart.split(':', 2); + if(options['uri_decode_auth']){ + auth[0] = decodeURIComponent(auth[0]); + if(auth[1]){ + auth[1] = decodeURIComponent(auth[1]); + } + } + + // Add auth to final object if we have 2 elements + if(auth.length == 2) object.auth = {user: auth[0], password: auth[1]}; + + // Variables used for temporary storage + var hostPart; + var urlOptions; + var servers; + var serverOptions = {socketOptions: {}}; + var dbOptions = {read_preference_tags: []}; + var replSetServersOptions = {socketOptions: {}}; + // Add server options to final object + object.server_options = serverOptions; + object.db_options = dbOptions; + object.rs_options = replSetServersOptions; + object.mongos_options = {}; + + // Let's check if we are using a domain socket + if(url.match(/\.sock/)) { + // Split out the socket part + var domainSocket = url.substring( + url.indexOf("mongodb://") + "mongodb://".length + , url.lastIndexOf(".sock") + ".sock".length); + // Clean out any auth stuff if any + if(domainSocket.indexOf("@") != -1) domainSocket = domainSocket.split("@")[1]; + servers = [{domain_socket: domainSocket}]; + } else { + // Split up the db + hostPart = connection_part; + // Parse all server results + servers = hostPart.split(',').map(function(h) { + var _host, _port, ipv6match; + //check if it matches [IPv6]:port, where the port number is optional + if ((ipv6match = /\[([^\]]+)\](?:\:(.+))?/.exec(h))) { + _host = ipv6match[1]; + _port = parseInt(ipv6match[2], 10) || 27017; + } else { + //otherwise assume it's IPv4, or plain hostname + var hostPort = h.split(':', 2); + _host = hostPort[0] || 'localhost'; + _port = hostPort[1] != null ? parseInt(hostPort[1], 10) : 27017; + // Check for localhost?safe=true style case + if(_host.indexOf("?") != -1) _host = _host.split(/\?/)[0]; + } + // Return the mapped object + return {host: _host, port: _port}; + }); + } + + // Get the db name + object.dbName = dbName || 'admin'; + // Split up all the options + urlOptions = (query_string_part || '').split(/[&;]/); + // Ugh, we have to figure out which options go to which constructor manually. + urlOptions.forEach(function(opt) { + if(!opt) return; + var splitOpt = opt.split('='), name = splitOpt[0], value = splitOpt[1]; + // Options implementations + switch(name) { + case 'slaveOk': + case 'slave_ok': + serverOptions.slave_ok = (value == 'true'); + dbOptions.slaveOk = (value == 'true'); + break; + case 'maxPoolSize': + case 'poolSize': + serverOptions.poolSize = parseInt(value, 10); + replSetServersOptions.poolSize = parseInt(value, 10); + break; + case 'autoReconnect': + case 'auto_reconnect': + serverOptions.auto_reconnect = (value == 'true'); + break; + case 'minPoolSize': + throw new Error("minPoolSize not supported"); + case 'maxIdleTimeMS': + throw new Error("maxIdleTimeMS not supported"); + case 'waitQueueMultiple': + throw new Error("waitQueueMultiple not supported"); + case 'waitQueueTimeoutMS': + throw new Error("waitQueueTimeoutMS not supported"); + case 'uuidRepresentation': + throw new Error("uuidRepresentation not supported"); + case 'ssl': + if(value == 'prefer') { + serverOptions.ssl = value; + replSetServersOptions.ssl = value; + break; + } + serverOptions.ssl = (value == 'true'); + replSetServersOptions.ssl = (value == 'true'); + break; + case 'replicaSet': + case 'rs_name': + replSetServersOptions.rs_name = value; + break; + case 'reconnectWait': + replSetServersOptions.reconnectWait = parseInt(value, 10); + break; + case 'retries': + replSetServersOptions.retries = parseInt(value, 10); + break; + case 'readSecondary': + case 'read_secondary': + replSetServersOptions.read_secondary = (value == 'true'); + break; + case 'fsync': + dbOptions.fsync = (value == 'true'); + break; + case 'journal': + dbOptions.journal = (value == 'true'); + break; + case 'safe': + dbOptions.safe = (value == 'true'); + break; + case 'nativeParser': + case 'native_parser': + dbOptions.native_parser = (value == 'true'); + break; + case 'connectTimeoutMS': + serverOptions.socketOptions.connectTimeoutMS = parseInt(value, 10); + replSetServersOptions.socketOptions.connectTimeoutMS = parseInt(value, 10); + break; + case 'socketTimeoutMS': + serverOptions.socketOptions.socketTimeoutMS = parseInt(value, 10); + replSetServersOptions.socketOptions.socketTimeoutMS = parseInt(value, 10); + break; + case 'w': + dbOptions.w = parseInt(value, 10); + if(isNaN(dbOptions.w)) dbOptions.w = value; + break; + case 'authSource': + dbOptions.authSource = value; + break; + case 'gssapiServiceName': + dbOptions.gssapiServiceName = value; + break; + case 'authMechanism': + if(value == 'GSSAPI') { + // If no password provided decode only the principal + if(object.auth == null) { + var urlDecodeAuthPart = decodeURIComponent(authPart); + if(urlDecodeAuthPart.indexOf("@") == -1) throw new Error("GSSAPI requires a provided principal"); + object.auth = {user: urlDecodeAuthPart, password: null}; + } else { + object.auth.user = decodeURIComponent(object.auth.user); + } + } else if(value == 'MONGODB-X509') { + object.auth = {user: decodeURIComponent(authPart)}; + } + + // Only support GSSAPI or MONGODB-CR for now + if(value != 'GSSAPI' + && value != 'MONGODB-X509' + && value != 'SCRAM-SHA-1' + && value != 'MONGODB-CR' + && value != 'PLAIN') + throw new Error("only GSSAPI, PLAIN, MONGODB-X509, SCRAM-SHA-1 or MONGODB-CR is supported by authMechanism"); + + // Authentication mechanism + dbOptions.authMechanism = value; + break; + case 'wtimeoutMS': + dbOptions.wtimeout = parseInt(value, 10); + break; + case 'readPreference': + if(!ReadPreference.isValid(value)) throw new Error("readPreference must be either primary/primaryPreferred/secondary/secondaryPreferred/nearest"); + dbOptions.read_preference = value; + break; + case 'readPreferenceTags': + // Decode the value + value = decodeURIComponent(value); + // Contains the tag object + var tagObject = {}; + if(value == null || value == '') { + dbOptions.read_preference_tags.push(tagObject); + break; + } + + // Split up the tags + var tags = value.split(/\,/); + for(var i = 0; i < tags.length; i++) { + var parts = tags[i].trim().split(/\:/); + tagObject[parts[0]] = parts[1]; + } + + // Set the preferences tags + dbOptions.read_preference_tags.push(tagObject); + break; + default: + break; + } + }); + + // No tags: should be null (not []) + if(dbOptions.read_preference_tags.length === 0) { + dbOptions.read_preference_tags = null; + } + + // Validate if there are an invalid write concern combinations + if((dbOptions.w == -1 || dbOptions.w == 0) && ( + dbOptions.journal == true + || dbOptions.fsync == true + || dbOptions.safe == true)) throw new Error("w set to -1 or 0 cannot be combined with safe/w/journal/fsync") + + // If no read preference set it to primary + if(!dbOptions.read_preference) dbOptions.read_preference = 'primary'; + + // Add servers to result + object.servers = servers; + // Returned parsed object + return object; +} diff --git a/node_modules/mongodb/lib/mongodb/cursor.js b/node_modules/mongodb/lib/mongodb/cursor.js new file mode 100644 index 0000000..050cc9c --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/cursor.js @@ -0,0 +1,1038 @@ +var QueryCommand = require('./commands/query_command').QueryCommand, + GetMoreCommand = require('./commands/get_more_command').GetMoreCommand, + KillCursorCommand = require('./commands/kill_cursor_command').KillCursorCommand, + Long = require('bson').Long, + ReadPreference = require('./connection/read_preference').ReadPreference, + CursorStream = require('./cursorstream'), + timers = require('timers'), + utils = require('./utils'); + +// Set processor, setImmediate if 0.10 otherwise nextTick +var processor = require('./utils').processor(); + +/** + * Constructor for a cursor object that handles all the operations on query result + * using find. This cursor object is unidirectional and cannot traverse backwards. Clients should not be creating a cursor directly, + * but use find to acquire a cursor. (INTERNAL TYPE) + * + * Options + * - **skip** {Number} skip number of documents to skip. + * - **limit** {Number}, limit the number of results to return. -1 has a special meaning and is used by Db.eval. A value of 1 will also be treated as if it were -1. + * - **sort** {Array | Object}, set to sort the documents coming back from the query. Array of indexes, [['a', 1]] etc. + * - **hint** {Object}, hint force the query to use a specific index. + * - **explain** {Boolean}, explain return the explaination of the query. + * - **snapshot** {Boolean}, snapshot Snapshot mode assures no duplicates are returned. + * - **timeout** {Boolean}, timeout allow the query to timeout. + * - **tailable** {Boolean}, tailable allow the cursor to be tailable. + * - **awaitdata** {Boolean}, awaitdata allow the cursor to wait for data, only applicable for tailable cursor. + * - **oplogReplay** {Boolean}, sets an internal flag, only applicable for tailable cursor. + * - **batchSize** {Number}, batchSize the number of the subset of results to request the database to return for every request. This should initially be greater than 1 otherwise the database will automatically close the cursor. The batch size can be set to 1 with cursorInstance.batchSize after performing the initial query to the database. + * - **raw** {Boolean}, raw return all query documents as raw buffers (default false). + * - **read** {Boolean}, read specify override of read from source (primary/secondary). + * - **returnKey** {Boolean}, returnKey only return the index key. + * - **maxScan** {Number}, maxScan limit the number of items to scan. + * - **min** {Number}, min set index bounds. + * - **max** {Number}, max set index bounds. + * - **maxTimeMS** {Number}, number of miliseconds to wait before aborting the query. + * - **showDiskLoc** {Boolean}, showDiskLoc show disk location of results. + * - **comment** {String}, comment you can put a $comment field on a query to make looking in the profiler logs simpler. + * - **numberOfRetries** {Number}, numberOfRetries if using awaidata specifies the number of times to retry on timeout. + * - **dbName** {String}, dbName override the default dbName. + * - **tailableRetryInterval** {Number}, tailableRetryInterval specify the miliseconds between getMores on tailable cursor. + * - **exhaust** {Boolean}, exhaust have the server send all the documents at once as getMore packets. + * - **partial** {Boolean}, partial have the sharded system return a partial result from mongos. + * + * @class Represents a Cursor. + * @param {Db} db the database object to work with. + * @param {Collection} collection the collection to query. + * @param {Object} selector the query selector. + * @param {Object} fields an object containing what fields to include or exclude from objects returned. + * @param {Object} [options] additional options for the collection. +*/ +function Cursor(db, collection, selector, fields, options) { + this.db = db; + this.collection = collection; + this.selector = selector; + this.fields = fields; + options = !options ? {} : options; + + this.skipValue = options.skip == null ? 0 : options.skip; + this.limitValue = options.limit == null ? 0 : options.limit; + this.sortValue = options.sort; + this.hint = options.hint; + this.explainValue = options.explain; + this.snapshot = options.snapshot; + this.timeout = options.timeout == null ? true : options.timeout; + this.tailable = options.tailable; + this.awaitdata = options.awaitdata; + this.oplogReplay = options.oplogReplay; + this.numberOfRetries = options.numberOfRetries == null ? 5 : options.numberOfRetries; + this.currentNumberOfRetries = this.numberOfRetries; + this.batchSizeValue = options.batchSize == null ? 0 : options.batchSize; + this.raw = options.raw == null ? false : options.raw; + this.readPreference = options.readPreference == null ? ReadPreference.PRIMARY : options.readPreference; + this.returnKey = options.returnKey; + this.maxScan = options.maxScan; + this.min = options.min; + this.max = options.max; + this.showDiskLoc = options.showDiskLoc; + this.comment = options.comment; + this.tailableRetryInterval = options.tailableRetryInterval || 100; + this.exhaust = options.exhaust || false; + this.partial = options.partial || false; + this.slaveOk = options.slaveOk || false; + this.maxTimeMSValue = options.maxTimeMS; + this.connection = options.connection; + + this.totalNumberOfRecords = 0; + this.items = []; + this.cursorId = Long.fromInt(0); + + // This name + this.dbName = options.dbName; + + // State variables for the cursor + this.state = Cursor.INIT; + // Keep track of the current query run + this.queryRun = false; + this.getMoreTimer = false; + + // If we are using a specific db execute against it + if(this.dbName != null) { + this.collectionName = this.dbName + "." + this.collection.collectionName; + } else { + this.collectionName = (this.db.databaseName ? this.db.databaseName + "." : '') + this.collection.collectionName; + } +} + +/** + * Clones a given cursor but uses new options + * @param {Cursor} cursor the cursor to clone. + * @return {Object} [options] additional options for the collection when cloning. + */ +Cursor.cloneWithOptions = function(cursor, options) { + return new Cursor(cursor.db, cursor.collection, cursor.selector, cursor.fields, options); +} + +/** + * Resets this cursor to its initial state. All settings like the query string, + * tailable, batchSizeValue, skipValue and limits are preserved. + * + * @return {Cursor} returns itself with rewind applied. + * @api public + */ +Cursor.prototype.rewind = function() { + var self = this; + + if (self.state != Cursor.INIT) { + if (self.state != Cursor.CLOSED) { + self.close(function() {}); + } + + self.numberOfReturned = 0; + self.totalNumberOfRecords = 0; + self.items = []; + self.cursorId = Long.fromInt(0); + self.state = Cursor.INIT; + self.queryRun = false; + } + + return self; +} + + +/** + * Returns an array of documents. The caller is responsible for making sure that there + * is enough memory to store the results. Note that the array only contain partial + * results when this cursor had been previouly accessed. In that case, + * cursor.rewind() can be used to reset the cursor. + * + * @param {Function} callback This will be called after executing this method successfully. The first parameter will contain the Error object if an error occured, or null otherwise. The second parameter will contain an array of BSON deserialized objects as a result of the query. + * @return {null} + * @api public + */ +Cursor.prototype.toArray = function(callback) { + var self = this; + + if(!callback) { + throw new Error('callback is mandatory'); + } + + if(this.tailable) { + callback(new Error("Tailable cursor cannot be converted to array"), null); + } else if(this.state != Cursor.CLOSED) { + // return toArrayExhaust(self, callback); + // If we are using exhaust we can't use the quick fire method + if(self.exhaust) return toArrayExhaust(self, callback); + // Quick fire using trampoline to avoid nextTick + self.nextObject({noReturn: true}, function(err, result) { + if(err) return callback(utils.toError(err), null); + if(self.cursorId.toString() == "0") { + self.state = Cursor.CLOSED; + return callback(null, self.items); + } + + // Let's issue getMores until we have no more records waiting + getAllByGetMore(self, function(err, done) { + self.state = Cursor.CLOSED; + if(err) return callback(utils.toError(err), null); + // Let's release the internal list + var items = self.items; + self.items = null; + // Return all the items + callback(null, items); + }); + }) + + } else { + callback(new Error("Cursor is closed"), null); + } +} + +var toArrayExhaust = function(self, callback) { + var items = []; + + self.each(function(err, item) { + if(err != null) { + return callback(utils.toError(err), null); + } + + if(item != null && Array.isArray(items)) { + items.push(item); + } else { + var resultItems = items; + items = null; + self.items = []; + callback(null, resultItems); + } + }); +} + +var getAllByGetMore = function(self, callback) { + getMore(self, {noReturn: true}, function(err, result) { + if(err) return callback(utils.toError(err)); + if(result == null) return callback(null, null); + if(self.cursorId.toString() == "0") return callback(null, null); + getAllByGetMore(self, callback); + }) +}; + +/** + * Iterates over all the documents for this cursor. As with **{cursor.toArray}**, + * not all of the elements will be iterated if this cursor had been previouly accessed. + * In that case, **{cursor.rewind}** can be used to reset the cursor. However, unlike + * **{cursor.toArray}**, the cursor will only hold a maximum of batch size elements + * at any given time if batch size is specified. Otherwise, the caller is responsible + * for making sure that the entire result can fit the memory. + * + * @param {Function} callback this will be called for while iterating every document of the query result. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the document. + * @return {null} + * @api public + */ +Cursor.prototype.each = function(callback) { + var self = this; + var fn; + + if (!callback) { + throw new Error('callback is mandatory'); + } + + if(this.state != Cursor.CLOSED) { + // If we are using exhaust we can't use the quick fire method + if(self.exhaust) return eachExhaust(self, callback); + // Quick fire using trampoline to avoid nextTick + if(this.items.length > 0) { + // Trampoline all the entries + while(fn = loop(self, callback)) fn(self, callback); + // Call each again + self.each(callback); + } else { + self.nextObject(function(err, item) { + + if(err) { + self.state = Cursor.CLOSED; + return callback(utils.toError(err), item); + } + + if(item == null) return callback(null, null); + callback(null, item); + self.each(callback); + }) + } + } else { + callback(new Error("Cursor is closed"), null); + } +}; + +// Special for exhaust command as we don't initiate the actual result sets +// the server just sends them as they arrive meaning we need to get the IO event +// loop happen so we can receive more data from the socket or we return to early +// after the first fetch and loose all the incoming getMore's automatically issued +// from the server. +var eachExhaust = function(self, callback) { + //FIX: stack overflow (on deep callback) (cred: https://github.com/limp/node-mongodb-native/commit/27da7e4b2af02035847f262b29837a94bbbf6ce2) + processor(function(){ + // Fetch the next object until there is no more objects + self.nextObject(function(err, item) { + if(err != null) return callback(err, null); + if(item != null) { + callback(null, item); + eachExhaust(self, callback); + } else { + // Close the cursor if done + self.state = Cursor.CLOSED; + callback(err, null); + } + }); + }); +} + +// Trampoline emptying the number of retrieved items +// without incurring a nextTick operation +var loop = function(self, callback) { + // No more items we are done + if(self.items.length == 0) return; + // Get the next document + var doc = self.items.shift(); + // Callback + callback(null, doc); + // Loop + return loop; +} + +/** + * Determines how many result the query for this cursor will return + * + * @param {Boolean} applySkipLimit if set to true will apply the skip and limits set on the cursor. Defaults to false. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the number of results or null if an error occured. + * @return {null} + * @api public + */ +Cursor.prototype.count = function(applySkipLimit, callback) { + if(typeof applySkipLimit == 'function') { + callback = applySkipLimit; + applySkipLimit = false; + } + + var options = {}; + if(applySkipLimit) { + if(typeof this.skipValue == 'number') options.skip = this.skipValue; + if(typeof this.limitValue == 'number') options.limit = this.limitValue; + } + + // If maxTimeMS set + if(typeof this.maxTimeMSValue == 'number') options.maxTimeMS = this.maxTimeMSValue; + // Do we have a hint add it to the options + if(this.hint) options.hint = this.hint; + + // Call count command + this.collection.count(this.selector, options, callback); +}; + +/** + * Sets the sort parameter of this cursor to the given value. + * + * This method has the following method signatures: + * (keyOrList, callback) + * (keyOrList, direction, callback) + * + * @param {String|Array|Object} keyOrList This can be a string or an array. If passed as a string, the string will be the field to sort. If passed an array, each element will represent a field to be sorted and should be an array that contains the format [string, direction]. + * @param {String|Number} direction this determines how the results are sorted. "asc", "ascending" or 1 for asceding order while "desc", "desceding or -1 for descending order. Note that the strings are case insensitive. + * @param {Function} callback this will be called after executing this method. The first parameter will contain an error object when the cursor is already closed while the second parameter will contain a reference to this object upon successful execution. + * @return {Cursor} an instance of this object. + * @api public + */ +Cursor.prototype.sort = function(keyOrList, direction, callback) { + callback = callback || function(){}; + if(typeof direction === "function") { callback = direction; direction = null; } + + if(this.tailable) { + callback(new Error("Tailable cursor doesn't support sorting"), null); + } else if(this.queryRun == true || this.state == Cursor.CLOSED) { + callback(new Error("Cursor is closed"), null); + } else { + var order = keyOrList; + + if(direction != null) { + order = [[keyOrList, direction]]; + } + + this.sortValue = order; + callback(null, this); + } + return this; +}; + +/** + * Sets the limit parameter of this cursor to the given value. + * + * @param {Number} limit the new limit. + * @param {Function} [callback] this optional callback will be called after executing this method. The first parameter will contain an error object when the limit given is not a valid number or when the cursor is already closed while the second parameter will contain a reference to this object upon successful execution. + * @return {Cursor} an instance of this object. + * @api public + */ +Cursor.prototype.limit = function(limit, callback) { + if(this.tailable) { + if(callback) { + callback(new Error("Tailable cursor doesn't support limit"), null); + } else { + throw new Error("Tailable cursor doesn't support limit"); + } + } else if(this.queryRun == true || this.state == Cursor.CLOSED) { + if(callback) { + callback(new Error("Cursor is closed"), null); + } else { + throw new Error("Cursor is closed"); + } + } else { + if(limit != null && limit.constructor != Number) { + if(callback) { + callback(new Error("limit requires an integer"), null); + } else { + throw new Error("limit requires an integer"); + } + } else { + this.limitValue = limit; + if(callback) return callback(null, this); + } + } + + return this; +}; + +/** + * Specifies a time limit for a query operation. After the specified + * time is exceeded, the operation will be aborted and an error will be + * returned to the client. If maxTimeMS is null, no limit is applied. + * + * @param {Number} maxTimeMS the maxTimeMS for the query. + * @param {Function} [callback] this optional callback will be called after executing this method. The first parameter will contain an error object when the limit given is not a valid number or when the cursor is already closed while the second parameter will contain a reference to this object upon successful execution. + * @return {Cursor} an instance of this object. + * @api public + */ +Cursor.prototype.maxTimeMS = function(maxTimeMS, callback) { + if(typeof maxTimeMS != 'number') { + throw new Error("maxTimeMS must be a number"); + } + + // Save the maxTimeMS option + this.maxTimeMSValue = maxTimeMS; + // Return the cursor for chaining + return this; +}; + +/** + * Sets the read preference for the cursor + * + * @param {String} the read preference for the cursor, one of Server.READ_PRIMARY, Server.READ_SECONDARY, Server.READ_SECONDARY_ONLY + * @param {Function} [callback] this optional callback will be called after executing this method. The first parameter will contain an error object when the read preference given is not a valid number or when the cursor is already closed while the second parameter will contain a reference to this object upon successful execution. + * @return {Cursor} an instance of this object. + * @api public + */ +Cursor.prototype.setReadPreference = function(readPreference, tags, callback) { + if(typeof tags == 'function') callback = tags; + + var _mode = readPreference != null && typeof readPreference == 'object' ? readPreference.mode : readPreference; + + if(this.queryRun == true || this.state == Cursor.CLOSED) { + if(callback == null) throw new Error("Cannot change read preference on executed query or closed cursor"); + callback(new Error("Cannot change read preference on executed query or closed cursor")); + } else if(_mode != null && _mode != 'primary' + && _mode != 'secondaryOnly' && _mode != 'secondary' + && _mode != 'nearest' && _mode != 'primaryPreferred' && _mode != 'secondaryPreferred') { + if(callback == null) throw new Error("only readPreference of primary, secondary, secondaryPreferred, primaryPreferred or nearest supported"); + callback(new Error("only readPreference of primary, secondary, secondaryPreferred, primaryPreferred or nearest supported")); + } else { + this.readPreference = readPreference; + if(callback != null) callback(null, this); + } + + return this; +} + +/** + * Sets the skip parameter of this cursor to the given value. + * + * @param {Number} skip the new skip value. + * @param {Function} [callback] this optional callback will be called after executing this method. The first parameter will contain an error object when the skip value given is not a valid number or when the cursor is already closed while the second parameter will contain a reference to this object upon successful execution. + * @return {Cursor} an instance of this object. + * @api public + */ +Cursor.prototype.skip = function(skip, callback) { + callback = callback || function(){}; + + if(this.tailable) { + callback(new Error("Tailable cursor doesn't support skip"), null); + } else if(this.queryRun == true || this.state == Cursor.CLOSED) { + callback(new Error("Cursor is closed"), null); + } else { + if(skip != null && skip.constructor != Number) { + callback(new Error("skip requires an integer"), null); + } else { + this.skipValue = skip; + callback(null, this); + } + } + + return this; +}; + +/** + * Sets the batch size parameter of this cursor to the given value. + * + * @param {Number} batchSize the new batch size. + * @param {Function} [callback] this optional callback will be called after executing this method. The first parameter will contain an error object when the batchSize given is not a valid number or when the cursor is already closed while the second parameter will contain a reference to this object upon successful execution. + * @return {Cursor} an instance of this object. + * @api public + */ +Cursor.prototype.batchSize = function(batchSize, callback) { + if(this.state == Cursor.CLOSED) { + if(callback != null) { + return callback(new Error("Cursor is closed"), null); + } else { + throw new Error("Cursor is closed"); + } + } else if(batchSize != null && batchSize.constructor != Number) { + if(callback != null) { + return callback(new Error("batchSize requires an integer"), null); + } else { + throw new Error("batchSize requires an integer"); + } + } else { + this.batchSizeValue = batchSize; + if(callback != null) return callback(null, this); + } + + return this; +}; + +/** + * The limit used for the getMore command + * + * @return {Number} The number of records to request per batch. + * @ignore + * @api private + */ +var limitRequest = function(self) { + var requestedLimit = self.limitValue; + var absLimitValue = Math.abs(self.limitValue); + var absBatchValue = Math.abs(self.batchSizeValue); + + if(absLimitValue > 0) { + if (absBatchValue > 0) { + requestedLimit = Math.min(absLimitValue, absBatchValue); + } + } else { + requestedLimit = self.batchSizeValue; + } + + return requestedLimit; +}; + + +/** + * Generates a QueryCommand object using the parameters of this cursor. + * + * @return {QueryCommand} The command object + * @ignore + * @api private + */ +var generateQueryCommand = function(self) { + // Unpack the options + var queryOptions = QueryCommand.OPTS_NONE; + if(!self.timeout) { + queryOptions |= QueryCommand.OPTS_NO_CURSOR_TIMEOUT; + } + + if(self.tailable) { + queryOptions |= QueryCommand.OPTS_TAILABLE_CURSOR; + self.skipValue = self.limitValue = 0; + + // if awaitdata is set + if(self.awaitdata) { + queryOptions |= QueryCommand.OPTS_AWAIT_DATA; + } + + // This sets an internal undocumented flag. Clients should not depend on its + // behavior! + if(self.oplogReplay) { + queryOptions |= QueryCommand.OPTS_OPLOG_REPLAY; + } + } + + if(self.exhaust) { + queryOptions |= QueryCommand.OPTS_EXHAUST; + } + + // Unpack the read preference to set slave ok correctly + var readPreference = self.readPreference instanceof ReadPreference ? self.readPreference.mode : self.readPreference; + + // if(self.read == 'secondary') + if(readPreference == ReadPreference.PRIMARY_PREFERRED + || readPreference == ReadPreference.SECONDARY + || readPreference == ReadPreference.SECONDARY_PREFERRED + || readPreference == ReadPreference.NEAREST) { + queryOptions |= QueryCommand.OPTS_SLAVE; + } + + // Override slaveOk from the user + if(self.slaveOk) { + queryOptions |= QueryCommand.OPTS_SLAVE; + } + + if(self.partial) { + queryOptions |= QueryCommand.OPTS_PARTIAL; + } + + // limitValue of -1 is a special case used by Db#eval + var numberToReturn = self.limitValue == -1 ? -1 : limitRequest(self); + + // Check if we need a special selector + if(self.sortValue != null || self.explainValue != null || self.hint != null || self.snapshot != null + || self.returnKey != null || self.maxScan != null || self.min != null || self.max != null + || self.showDiskLoc != null || self.comment != null || typeof self.maxTimeMSValue == 'number') { + + // order by + var orderBy = utils.formattedOrderClause(self.sortValue); + + // Build special selector + var specialSelector = {'$query':self.selector}; + if(orderBy) specialSelector['orderby'] = orderBy; + if(self.hint != null && self.hint.constructor == Object) specialSelector['$hint'] = self.hint; + if(self.snapshot != null) specialSelector['$snapshot'] = self.snapshot; + if(self.returnKey != null) specialSelector['$returnKey'] = self.returnKey; + if(self.maxScan != null) specialSelector['$maxScan'] = self.maxScan; + if(self.min != null) specialSelector['$min'] = self.min; + if(self.max != null) specialSelector['$max'] = self.max; + if(self.showDiskLoc != null) specialSelector['$showDiskLoc'] = self.showDiskLoc; + if(self.comment != null) specialSelector['$comment'] = self.comment; + + // If we are querying the $cmd collection we need to add maxTimeMS as a field + // otherwise for a normal query it's a "special selector" $maxTimeMS + if(typeof self.maxTimeMSValue == 'number' + && self.collectionName.indexOf('.$cmd') != -1) { + specialSelector['maxTimeMS'] = self.maxTimeMSValue; + } else if(typeof self.maxTimeMSValue == 'number' + && self.collectionName.indexOf('.$cmd') == -1) { + specialSelector['$maxTimeMS'] = self.maxTimeMSValue; + } + + // If we have explain set only return a single document with automatic cursor close + if(self.explainValue) { + numberToReturn = (-1)*Math.abs(numberToReturn); + specialSelector['$explain'] = true; + } + + // Return the query + return new QueryCommand(self.db, self.collectionName, queryOptions, self.skipValue, numberToReturn, specialSelector, self.fields); + } else { + return new QueryCommand(self.db, self.collectionName, queryOptions, self.skipValue, numberToReturn, self.selector, self.fields); + } +}; + +/** + * @return {Object} Returns an object containing the sort value of this cursor with + * the proper formatting that can be used internally in this cursor. + * @ignore + * @api private + */ +Cursor.prototype.formattedOrderClause = function() { + return utils.formattedOrderClause(this.sortValue); +}; + +/** + * Converts the value of the sort direction into its equivalent numerical value. + * + * @param sortDirection {String|number} Range of acceptable values: + * 'ascending', 'descending', 'asc', 'desc', 1, -1 + * + * @return {number} The equivalent numerical value + * @throws Error if the given sortDirection is invalid + * @ignore + * @api private + */ +Cursor.prototype.formatSortValue = function(sortDirection) { + return utils.formatSortValue(sortDirection); +}; + +/** + * Gets the next document from the cursor. + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain an error object on error while the second parameter will contain a document from the returned result or null if there are no more results. + * @api public + */ +Cursor.prototype.nextObject = function(options, callback) { + var self = this; + + if(typeof options == 'function') { + callback = options; + options = {}; + } + + if(self.state == Cursor.INIT) { + var cmd; + try { + cmd = generateQueryCommand(self); + } catch (err) { + return callback(err, null); + } + + // No need to check the keys + var queryOptions = {exhaust: self.exhaust + , raw:self.raw + , readPreference:self.readPreference + , connection:self.connection + , checkKeys: false}; + + // Execute command + var commandHandler = function(err, result) { + // If on reconnect, the command got given a different connection, switch + // the whole cursor to it. + self.connection = queryOptions.connection; + self.state = Cursor.OPEN; // Adjust the state of the cursor + if(err != null && result == null) return callback(utils.toError(err), null); + + if(err == null && (result == null || result.documents == null || !Array.isArray(result.documents))) { + return self.close(function() {callback(new Error("command failed to return results"), null);}); + } + + if(err == null && result && result.documents[0] && result.documents[0]['$err']) { + return self.close(function() {callback(utils.toError(result.documents[0]['$err']), null);}); + } + + if(err == null && result && result.documents[0] && result.documents[0]['errmsg']) { + return self.close(function() {callback(utils.toError(result.documents[0]), null);}); + } + + self.queryRun = true; + self.cursorId = result.cursorId; + self.totalNumberOfRecords = result.numberReturned; + + // Add the new documents to the list of items, using forloop to avoid + // new array allocations and copying + for(var i = 0; i < result.documents.length; i++) { + self.items.push(result.documents[i]); + } + + // If we have noReturn set just return (not modifying the internal item list) + // used for toArray + if(options.noReturn) { + return callback(null, true); + } + + // Ignore callbacks until the cursor is dead for exhausted + if(self.exhaust && result.cursorId.toString() == "0") { + self.nextObject(callback); + } else if(self.exhaust == false || self.exhaust == null) { + self.nextObject(callback); + } + }; + + // If we have no connection set on this cursor check one out + if(self.connection == null) { + try { + self.connection = self.db.serverConfig.checkoutReader(this.readPreference); + + // Check if we have an error from the checkout Reader function + if(self.connection instanceof Error) { + return callback(utils.toError(self.connection), null); + } + + // Add to the query options + queryOptions.connection = self.connection; + } catch(err) { + return callback(utils.toError(err), null); + } + } + + // Execute the command + self.db._executeQueryCommand(cmd, queryOptions, commandHandler); + // Set the command handler to null + commandHandler = null; + } else if(self.items.length) { + callback(null, self.items.shift()); + } else if(self.cursorId.greaterThan(Long.fromInt(0))) { + getMore(self, callback); + } else { + // Force cursor to stay open + return self.close(function() {callback(null, null);}); + } +} + +/** + * Gets more results from the database if any. + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain an error object on error while the second parameter will contain a document from the returned result or null if there are no more results. + * @ignore + * @api private + */ +var getMore = function(self, options, callback) { + var limit = 0; + + if(typeof options == 'function') { + callback = options; + options = {}; + } + + if(self.state == Cursor.GET_MORE) return callback(null, null); + + // Set get more in progress + self.state = Cursor.GET_MORE; + + // Set options + if (!self.tailable && self.limitValue > 0) { + limit = self.limitValue - self.totalNumberOfRecords; + if (limit < 1) { + self.close(function() {callback(null, null);}); + return; + } + } + + try { + var getMoreCommand = new GetMoreCommand( + self.db + , self.collectionName + , limitRequest(self) + , self.cursorId + ); + + // Set up options + var command_options = { + readPreference: self.readPreference + , raw: self.raw + , connection:self.connection + }; + + // Execute the command + self.db._executeQueryCommand(getMoreCommand, command_options, function(err, result) { + var cbValue; + + // Get more done + self.state = Cursor.OPEN; + + if(err != null) { + self.state = Cursor.CLOSED; + return callback(utils.toError(err), null); + } + + // Ensure we get a valid result + if(!result || !result.documents) { + self.state = Cursor.CLOSED; + return callback(utils.toError("command failed to return results"), null) + } + + // If we have a timed out query + if((result.responseFlag & (1 << 0)) != 0) { + self.state = Cursor.CLOSED; + return callback(utils.toError("cursor killed or timed out"), null); + } + + // If the QueryFailure flag is set + if((result.responseFlag & (1 << 1)) != 0) { + self.state = Cursor.CLOSED; + return callback(utils.toError("QueryFailure flag set on getmore command"), null); + } + + try { + var isDead = 1 === result.responseFlag && result.cursorId.isZero(); + + self.cursorId = result.cursorId; + self.totalNumberOfRecords += result.numberReturned; + + // Determine if there's more documents to fetch + if(result.numberReturned > 0) { + if (self.limitValue > 0) { + var excessResult = self.totalNumberOfRecords - self.limitValue; + + if (excessResult > 0) { + result.documents.splice(-1 * excessResult, excessResult); + } + } + + // Reset the tries for awaitdata if we are using it + self.currentNumberOfRetries = self.numberOfRetries; + // Get the documents + for(var i = 0; i < result.documents.length; i++) { + self.items.push(result.documents[i]); + } + + // Don's shift a document out as we need it for toArray + if(options.noReturn) { + cbValue = true; + } else { + cbValue = self.items.shift(); + } + } else if(self.tailable && !isDead && self.awaitdata) { + // Excute the tailable cursor once more, will timeout after ~4 sec if awaitdata used + self.currentNumberOfRetries = self.currentNumberOfRetries - 1; + if(self.currentNumberOfRetries == 0) { + self.close(function() { + callback(new Error("tailable cursor timed out"), null); + }); + } else { + getMore(self, callback); + } + } else if(self.tailable && !isDead) { + self.getMoreTimer = setTimeout(function() { getMore(self, callback); }, self.tailableRetryInterval); + } else { + self.close(function() {callback(null, null); }); + } + + result = null; + } catch(err) { + callback(utils.toError(err), null); + } + if (cbValue != null) callback(null, cbValue); + }); + + getMoreCommand = null; + } catch(err) { + // Get more done + self.state = Cursor.OPEN; + + var handleClose = function() { + callback(utils.toError(err), null); + }; + + self.close(handleClose); + handleClose = null; + } +} + +/** + * Gets a detailed information about how the query is performed on this cursor and how + * long it took the database to process it. + * + * @param {Function} callback this will be called after executing this method. The first parameter will always be null while the second parameter will be an object containing the details. + * @api public + */ +Cursor.prototype.explain = function(callback) { + var limit = (-1)*Math.abs(this.limitValue); + + // Create a new cursor and fetch the plan + var cursor = new Cursor(this.db, this.collection, this.selector, this.fields, { + skip: this.skipValue + , limit:limit + , sort: this.sortValue + , hint: this.hint + , explain: true + , snapshot: this.snapshot + , timeout: this.timeout + , tailable: this.tailable + , batchSize: this.batchSizeValue + , slaveOk: this.slaveOk + , raw: this.raw + , readPreference: this.readPreference + , returnKey: this.returnKey + , maxScan: this.maxScan + , min: this.min + , max: this.max + , showDiskLoc: this.showDiskLoc + , comment: this.comment + , awaitdata: this.awaitdata + , oplogReplay: this.oplogReplay + , numberOfRetries: this.numberOfRetries + , dbName: this.dbName + }); + + // Fetch the explaination document + cursor.nextObject(function(err, item) { + if(err != null) return callback(utils.toError(err), null); + // close the cursor + cursor.close(function(err, result) { + if(err != null) return callback(utils.toError(err), null); + callback(null, item); + }); + }); +}; + +/** + * Returns a Node Transform Stream interface for this cursor. + * + * Options + * - **transform** {Function} function of type function(object) { return transformed }, allows for transformation of data before emitting. + * + * @return {CursorStream} returns a stream object. + * @api public + */ +Cursor.prototype.stream = function stream(options) { + return new CursorStream(this, options); +} + +/** + * Close the cursor. + * + * @param {Function} callback this will be called after executing this method. The first parameter will always contain null while the second parameter will contain a reference to this cursor. + * @return {null} + * @api public + */ +Cursor.prototype.close = function(callback) { + var self = this + this.getMoreTimer && clearTimeout(this.getMoreTimer); + // Close the cursor if not needed + if(this.cursorId instanceof Long && this.cursorId.greaterThan(Long.fromInt(0))) { + try { + var command = new KillCursorCommand(this.db, [this.cursorId]); + // Added an empty callback to ensure we don't throw any null exceptions + this.db._executeQueryCommand(command, {readPreference:self.readPreference, raw:self.raw, connection:self.connection}); + } catch(err) {} + } + + // Null out the connection + self.connection = null; + // Reset cursor id + this.cursorId = Long.fromInt(0); + // Set to closed status + this.state = Cursor.CLOSED; + + if(callback) { + callback(null, self); + self.items = []; + } + + return this; +}; + +/** + * Check if the cursor is closed or open. + * + * @return {Boolean} returns the state of the cursor. + * @api public + */ +Cursor.prototype.isClosed = function() { + return this.state == Cursor.CLOSED ? true : false; +}; + +/** + * Init state + * + * @classconstant INIT + **/ +Cursor.INIT = 0; + +/** + * Cursor open + * + * @classconstant OPEN + **/ +Cursor.OPEN = 1; + +/** + * Cursor closed + * + * @classconstant CLOSED + **/ +Cursor.CLOSED = 2; + +/** + * Cursor performing a get more + * + * @classconstant OPEN + **/ +Cursor.GET_MORE = 3; + +/** + * @ignore + * @api private + */ +exports.Cursor = Cursor; diff --git a/node_modules/mongodb/lib/mongodb/cursorstream.js b/node_modules/mongodb/lib/mongodb/cursorstream.js new file mode 100644 index 0000000..4370f45 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/cursorstream.js @@ -0,0 +1,167 @@ +var timers = require('timers'); + +// Set processor, setImmediate if 0.10 otherwise nextTick +var processor = require('./utils').processor(); + +/** + * Module dependecies. + */ +var Stream = require('stream').Stream; + +/** + * CursorStream + * + * Returns a stream interface for the **cursor**. + * + * Options + * - **transform** {Function} function of type function(object) { return transformed }, allows for transformation of data before emitting. + * + * Events + * - **data** {function(item) {}} the data event triggers when a document is ready. + * - **error** {function(err) {}} the error event triggers if an error happens. + * - **close** {function() {}} the end event triggers when there is no more documents available. + * + * @class Represents a CursorStream. + * @param {Cursor} cursor a cursor object that the stream wraps. + * @return {Stream} + */ +function CursorStream(cursor, options) { + if(!(this instanceof CursorStream)) return new CursorStream(cursor); + options = options ? options : {}; + + Stream.call(this); + + this.readable = true; + this.paused = false; + this._cursor = cursor; + this._destroyed = null; + this.options = options; + + // give time to hook up events + var self = this; + process.nextTick(function() { + self._init(); + }); +} + +/** + * Inherit from Stream + * @ignore + * @api private + */ +CursorStream.prototype.__proto__ = Stream.prototype; + +/** + * Flag stating whether or not this stream is readable. + */ +CursorStream.prototype.readable; + +/** + * Flag stating whether or not this stream is paused. + */ +CursorStream.prototype.paused; + +/** + * Initialize the cursor. + * @ignore + * @api private + */ +CursorStream.prototype._init = function () { + if (this._destroyed) return; + this._next(); +} + +/** + * Pull the next document from the cursor. + * @ignore + * @api private + */ +CursorStream.prototype._next = function () { + if(this.paused || this._destroyed) return; + + var self = this; + // Get the next object + processor(function() { + if(self.paused || self._destroyed) return; + + self._cursor.nextObject(function (err, doc) { + self._onNextObject(err, doc); + }); + }); +} + +/** + * Handle each document as its returned from the cursor. + * @ignore + * @api private + */ +CursorStream.prototype._onNextObject = function (err, doc) { + if(err) { + this.destroy(err); + return this.emit('end'); + } + + // when doc is null we hit the end of the cursor + if(!doc && (this._cursor.state == 1 || this._cursor.state == 2)) { + this.emit('end') + return this.destroy(); + } else if(doc) { + var data = typeof this.options.transform == 'function' ? this.options.transform(doc) : doc; + this.emit('data', data); + this._next(); + } +} + +/** + * Pauses the stream. + * + * @api public + */ +CursorStream.prototype.pause = function () { + this.paused = true; +} + +/** + * Resumes the stream. + * + * @api public + */ +CursorStream.prototype.resume = function () { + var self = this; + + // Don't do anything if we are not paused + if(!this.paused) return; + if(!this._cursor.state == 3) return; + + process.nextTick(function() { + self.paused = false; + // Only trigger more fetching if the cursor is open + self._next(); + }) +} + +/** + * Destroys the stream, closing the underlying + * cursor. No more events will be emitted. + * + * @api public + */ +CursorStream.prototype.destroy = function (err) { + if (this._destroyed) return; + this._destroyed = true; + this.readable = false; + + this._cursor.close(); + + if(err && this.listeners('error').length > 0) { + return this.emit('error', err); + } + + this.emit('close'); +} + +// TODO - maybe implement the raw option to pass binary? +//CursorStream.prototype.setEncoding = function () { +//} + +module.exports = exports = CursorStream; diff --git a/node_modules/mongodb/lib/mongodb/db.js b/node_modules/mongodb/lib/mongodb/db.js new file mode 100644 index 0000000..3715486 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/db.js @@ -0,0 +1,2179 @@ +/** + * Module dependencies. + * @ignore + */ +var QueryCommand = require('./commands/query_command').QueryCommand + , DbCommand = require('./commands/db_command').DbCommand + , MongoReply = require('./responses/mongo_reply').MongoReply + , Admin = require('./admin').Admin + , Collection = require('./collection').Collection + , Server = require('./connection/server').Server + , ReplSet = require('./connection/repl_set/repl_set').ReplSet + , ReadPreference = require('./connection/read_preference').ReadPreference + , Mongos = require('./connection/mongos').Mongos + , Cursor = require('./cursor').Cursor + , EventEmitter = require('events').EventEmitter + , InsertCommand = require('./commands/insert_command').InsertCommand + , f = require('util').format + , inherits = require('util').inherits + , crypto = require('crypto') + , timers = require('timers') + , utils = require('./utils') + + // Authentication methods + , mongodb_cr_authenticate = require('./auth/mongodb_cr.js').authenticate + , mongodb_gssapi_authenticate = require('./auth/mongodb_gssapi.js').authenticate + , mongodb_sspi_authenticate = require('./auth/mongodb_sspi.js').authenticate + , mongodb_plain_authenticate = require('./auth/mongodb_plain.js').authenticate + , mongodb_x509_authenticate = require('./auth/mongodb_x509.js').authenticate + , mongodb_scram_authenticate = require('./auth/mongodb_scram.js').authenticate; + +var hasKerberos = false; +// Check if we have a the kerberos library +try { + require('kerberos'); + hasKerberos = true; +} catch(err) {} + +// Set processor, setImmediate if 0.10 otherwise nextTick +var processor = require('./utils').processor(); + +/** + * Create a new Db instance. + * + * Options + * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowledgement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal + * - **j**, (Boolean, default:false) write waits for journal sync before returning + * - **readPreference** {String}, the preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). + * - **native_parser** {Boolean, default:false}, use c++ bson parser. + * - **forceServerObjectId** {Boolean, default:false}, force server to create _id fields instead of client. + * - **pkFactory** {Object}, object overriding the basic ObjectID primary key generation. + * - **serializeFunctions** {Boolean, default:false}, serialize functions. + * - **raw** {Boolean, default:false}, perform operations using raw bson buffers. + * - **recordQueryStats** {Boolean, default:false}, record query statistics during execution. + * - **retryMiliSeconds** {Number, default:5000}, number of milliseconds between retries. + * - **numberOfRetries** {Number, default:5}, number of retries off connection. + * - **logger** {Object, default:null}, an object representing a logger that you want to use, needs to support functions debug, log, error **({error:function(message, object) {}, log:function(message, object) {}, debug:function(message, object) {}})**. + * - **slaveOk** {Number, default:null}, force setting of SlaveOk flag on queries (only use when explicitly connecting to a secondary server). + * - **promoteLongs** {Boolean, default:true}, when deserializing a Long will fit it into a Number if it's smaller than 53 bits + * - **bufferMaxEntries** {Number, default: -1}, sets a cap on how many operations the driver will buffer up before giving up on getting a working connection, default is -1 which is unlimited + * + * @class Represents a Db + * @param {String} databaseName name of the database. + * @param {Object} serverConfig server config object. + * @param {Object} [options] additional options for the collection. + */ +function Db(databaseName, serverConfig, options) { + if(!(this instanceof Db)) return new Db(databaseName, serverConfig, options); + EventEmitter.call(this); + var self = this; + this.databaseName = databaseName; + this.serverConfig = serverConfig; + this.options = options == null ? {} : options; + // State to check against if the user force closed db + this._applicationClosed = false; + // Fetch the override flag if any + var overrideUsedFlag = this.options['override_used_flag'] == null ? false : this.options['override_used_flag']; + + // Verify that nobody is using this config + if(!overrideUsedFlag && this.serverConfig != null && typeof this.serverConfig == 'object' && this.serverConfig._isUsed && this.serverConfig._isUsed()) { + throw new Error('A Server or ReplSet instance cannot be shared across multiple Db instances'); + } else if(!overrideUsedFlag && typeof this.serverConfig == 'object'){ + // Set being used + this.serverConfig._used = true; + } + + // Allow slaveOk override + this.slaveOk = this.options['slave_ok'] == null ? false : this.options['slave_ok']; + this.slaveOk = this.options['slaveOk'] == null ? this.slaveOk : this.options['slaveOk']; + + // Number of operations to buffer before failure + this.bufferMaxEntries = typeof this.options['bufferMaxEntries'] == 'number' ? this.options['bufferMaxEntries'] : -1; + + // Ensure we have a valid db name + validateDatabaseName(databaseName); + + // Contains all the connections for the db + try { + this.native_parser = this.options.native_parser; + // The bson lib + var bsonLib = this.bsonLib = this.options.native_parser ? require('bson').BSONNative : require('bson').BSONPure; + bsonLib = require('bson').BSONPure; + // Fetch the serializer object + var BSON = bsonLib.BSON; + + // Create a new instance + this.bson = new BSON([bsonLib.Long, bsonLib.ObjectID, bsonLib.Binary, bsonLib.Code, bsonLib.DBRef, bsonLib.Symbol, bsonLib.Double, bsonLib.Timestamp, bsonLib.MaxKey, bsonLib.MinKey]); + this.bson.promoteLongs = this.options.promoteLongs == null ? true : this.options.promoteLongs; + + // Backward compatibility to access types + this.bson_deserializer = bsonLib; + this.bson_serializer = bsonLib; + + // Add any overrides to the serializer and deserializer + this.bson_deserializer.promoteLongs = this.options.promoteLongs == null ? true : this.options.promoteLongs; + } catch (err) { + // If we tried to instantiate the native driver + var msg = 'Native bson parser not compiled, please compile ' + + 'or avoid using native_parser=true'; + throw Error(msg); + } + + // Internal state of the server + this._state = 'disconnected'; + + this.pkFactory = this.options.pkFactory == null ? bsonLib.ObjectID : this.options.pkFactory; + this.forceServerObjectId = this.options.forceServerObjectId != null ? this.options.forceServerObjectId : false; + + // Added safe + this.safe = this.options.safe == null ? false : this.options.safe; + + // If we have not specified a "safe mode" we just print a warning to the console + if(this.options.safe == null + && this.options.w == null + && this.options.j == null + && this.options.journal == null + && this.options.fsync == null) { + console.log("========================================================================================"); + console.log("= Please ensure that you set the default write concern for the database by setting ="); + console.log("= one of the options ="); + console.log("= ="); + console.log("= w: (value of > -1 or the string 'majority'), where < 1 means ="); + console.log("= no write acknowledgement ="); + console.log("= journal: true/false, wait for flush to journal before acknowledgement ="); + console.log("= fsync: true/false, wait for flush to file system before acknowledgement ="); + console.log("= ="); + console.log("= For backward compatibility safe is still supported and ="); + console.log("= allows values of [true | false | {j:true} | {w:n, wtimeout:n} | {fsync:true}] ="); + console.log("= the default value is false which means the driver receives does not ="); + console.log("= return the information of the success/error of the insert/update/remove ="); + console.log("= ="); + console.log("= ex: new Db(new Server('localhost', 27017), {safe:false}) ="); + console.log("= ="); + console.log("= http://www.mongodb.org/display/DOCS/getLastError+Command ="); + console.log("= ="); + console.log("= The default of no acknowledgement will change in the very near future ="); + console.log("= ="); + console.log("= This message will disappear when the default safe is set on the driver Db ="); + console.log("========================================================================================"); + } + + // Internal states variables + this.notReplied ={}; + this.isInitializing = true; + this.openCalled = false; + + // Command queue, keeps a list of incoming commands that need to be executed once the connection is up + this.commands = []; + + // Set up logger + this.logger = this.options.logger != null + && (typeof this.options.logger.debug == 'function') + && (typeof this.options.logger.error == 'function') + && (typeof this.options.logger.log == 'function') + ? this.options.logger : {error:function(message, object) {}, log:function(message, object) {}, debug:function(message, object) {}}; + + // Associate the logger with the server config + this.serverConfig.logger = this.logger; + if(this.serverConfig.strategyInstance) this.serverConfig.strategyInstance.logger = this.logger; + this.tag = new Date().getTime(); + // Just keeps list of events we allow + this.eventHandlers = {error:[], parseError:[], poolReady:[], message:[], close:[]}; + + // Controls serialization options + this.serializeFunctions = this.options.serializeFunctions != null ? this.options.serializeFunctions : false; + + // Raw mode + this.raw = this.options.raw != null ? this.options.raw : false; + + // Record query stats + this.recordQueryStats = this.options.recordQueryStats != null ? this.options.recordQueryStats : false; + + // If we have server stats let's make sure the driver objects have it enabled + if(this.recordQueryStats == true) { + this.serverConfig.enableRecordQueryStats(true); + } + + // Retry information + this.retryMiliSeconds = this.options.retryMiliSeconds != null ? this.options.retryMiliSeconds : 1000; + this.numberOfRetries = this.options.numberOfRetries != null ? this.options.numberOfRetries : 60; + + // Set default read preference if any + this.readPreference = this.options.readPreference; + + // Set slaveOk if we have specified a secondary or secondary preferred readPreference + if(this.readPreference == ReadPreference.SECONDARY || + this.readPreference == ReadPreference.SECONDARY_PREFERRED) { + this.slaveOk = true; + } + + // Set read preference on serverConfig if none is set + // but the db one was + if(this.serverConfig.options.readPreference != null) { + this.serverConfig.setReadPreference(this.serverConfig.options.readPreference); + } else if(this.readPreference != null) { + this.serverConfig.setReadPreference(this.readPreference); + } + + // Ensure we keep a reference to this db + this.serverConfig._dbStore.add(this); +}; + +/** + * @ignore + */ +function validateDatabaseName(databaseName) { + if(typeof databaseName !== 'string') throw new Error("database name must be a string"); + if(databaseName.length === 0) throw new Error("database name cannot be the empty string"); + if(databaseName == '$external') return; + + var invalidChars = [" ", ".", "$", "/", "\\"]; + for(var i = 0; i < invalidChars.length; i++) { + if(databaseName.indexOf(invalidChars[i]) != -1) throw new Error("database names cannot contain the character '" + invalidChars[i] + "'"); + } +} + +/** + * @ignore + */ +inherits(Db, EventEmitter); + +/** + * Initialize the database connection. + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the index information or null if an error occurred. + * @return {null} + * @api public + */ +Db.prototype.open = function(callback) { + var self = this; + + // Check that the user has not called this twice + if(this.openCalled) { + // Close db + this.close(); + // Throw error + throw new Error("db object already connecting, open cannot be called multiple times"); + } + + // If we have a specified read preference + if(this.readPreference != null) this.serverConfig.setReadPreference(this.readPreference); + + // Set that db has been opened + this.openCalled = true; + + // Set the status of the server + self._state = 'connecting'; + + // Set up connections + if(self.serverConfig instanceof Server || self.serverConfig instanceof ReplSet || self.serverConfig instanceof Mongos) { + // Ensure we have the original options passed in for the server config + var connect_options = {}; + for(var name in self.serverConfig.options) { + connect_options[name] = self.serverConfig.options[name] + } + connect_options.firstCall = true; + + // Attempt to connect + self.serverConfig.connect(self, connect_options, function(err, result) { + if(err != null) { + // Close db to reset connection + return self.close(function () { + // Return error from connection + return callback(err, null); + }); + } + // Set the status of the server + self._state = 'connected'; + // If we have queued up commands execute a command to trigger replays + if(self.commands.length > 0) _execute_queued_command(self); + // Callback + process.nextTick(function() { + try { + callback(null, self); + } catch(err) { + self.close(); + throw err; + } + }); + }); + } else { + try { + callback(Error("Server parameter must be of type Server, ReplSet or Mongos"), null); + } catch(err) { + self.close(); + throw err; + } + } +}; + +/** + * Create a new Db instance sharing the current socket connections. + * + * @param {String} dbName the name of the database we want to use. + * @return {Db} a db instance using the new database. + * @api public + */ +Db.prototype.db = function(dbName) { + // Copy the options and add out internal override of the not shared flag + var options = {}; + for(var key in this.options) { + options[key] = this.options[key]; + } + + // Add override flag + options['override_used_flag'] = true; + // Check if the db already exists and reuse if it's the case + var db = this.serverConfig._dbStore.fetch(dbName); + + // Create a new instance + if(!db) { + db = new Db(dbName, this.serverConfig, options); + } + + // Return the db object + return db; +}; + +/** + * Close the current db connection, including all the child db instances. Emits close event and calls optional callback. + * + * @param {Boolean} [forceClose] connection can never be reused. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results or null if an error occurred. + * @return {null} + * @api public + */ +Db.prototype.close = function(forceClose, callback) { + var self = this; + // Ensure we force close all connections + this._applicationClosed = false; + + if(typeof forceClose == 'function') { + callback = forceClose; + } else if(typeof forceClose == 'boolean') { + this._applicationClosed = forceClose; + } + + this.serverConfig.close(function(err, result) { + // You can reuse the db as everything is shut down + self.openCalled = false; + // If we have a callback call it + if(callback) callback(err, result); + }); +}; + +/** + * Access the Admin database + * + * @param {Function} [callback] returns the results. + * @return {Admin} the admin db object. + * @api public + */ +Db.prototype.admin = function(callback) { + if(callback == null) return new Admin(this); + callback(null, new Admin(this)); +}; + +/** + * Get the list of all collection names for the specified db + * + * Options + * - **namesOnly** {String, default:false}, Return only the full collection namespace. + * - **filter** {String|Object, default:null}, Filter collections by this filter (string or object) + * + * @param {String} [collectionName] the collection name we wish to filter by. + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the collection names or null if an error occurred. + * @return {null} + * @api public + */ +Db.prototype.listCollections = function(name, options, callback) { + var args = Array.prototype.slice.call(arguments, 0); + callback = args.pop(); + name = args.length ? args.shift() : null; + options = args.length ? args.shift() || {} : {}; + var self = this; + + // Only passed in options + if(name != null && typeof name == 'object') options = name, name = null; + // Do we have a filter + var filter = options.filter || {}; + + // Fallback to pre 2.8 list collections + var fallbackListCollections = function() { + // Ensure we have a filter + filter = filter || {}; + // Set the name variable for the filter + if(typeof name == 'string') filter.name = f("%s.%s", self.databaseName, name); + // Get the system namespace collection as a cursor + var cursor = self.collection(DbCommand.SYSTEM_NAMESPACE_COLLECTION).find(filter); + // Get all documents + cursor.toArray(function(err, documents) { + if(err != null) return callback(err, null); + + // Filter out all the non valid names + var filtered_documents = documents.filter(function(document) { + if(document.name.indexOf('$') != -1) return false; + return true; + }); + + // If we are returning only the names + if(options.namesOnly) { + filtered_documents = filtered_documents.map(function(document) { return document.name }); + } + + // Return filtered items + callback(null, filtered_documents); + }); + } + + // Set up the listCollectionsCommand + var listCollectionsCommand = {listCollections:1}; + // Add the optional filter if available + if(filter) listCollectionsCommand.filter = filter; + // Set the name variable for the filter + if(typeof name == 'string') filter.name = name; + + // Attempt to execute the collection list + self.command(listCollectionsCommand, function(err, result) { + if(err) return fallbackListCollections(); + // List of result documents that have been filtered + var filtered_documents = result.collections.filter(function(document) { + if(name && document.name != name) return false; + if(document.name.indexOf('$') != -1) return false; + return true; + }); + + // If we are returning only the names + if(options.namesOnly) { + filtered_documents = filtered_documents.map(function(document) { return document.name }); + } + + // Return filtered items + callback(null, filtered_documents); + }); +}; + +/** + * Get the list of all collection names for the specified db + * + * Options + * - **namesOnly** {String, default:false}, Return only the full collection namespace. + * + * @param {String} [collectionName] the collection name we wish to filter by. + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the collection names or null if an error occurred. + * @return {null} + * @api public + */ +Db.prototype.collectionNames = function(collectionName, options, callback) { + var args = Array.prototype.slice.call(arguments, 0); + this.listCollections.apply(this, args); +}; + +/** + * Fetch a specific collection (containing the actual collection information). If the application does not use strict mode you can + * can use it without a callback in the following way. var collection = db.collection('mycollection'); + * + * Options +* - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowledgement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal + * - **j**, (Boolean, default:false) write waits for journal sync before returning + * - **serializeFunctions** {Boolean, default:false}, serialize functions on the document. + * - **raw** {Boolean, default:false}, perform all operations using raw bson objects. + * - **pkFactory** {Object}, object overriding the basic ObjectID primary key generation. + * - **readPreference** {String}, the preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). + * - **strict**, (Boolean, default:false) returns an error if the collection does not exist + * + * @param {String} collectionName the collection name we wish to access. + * @param {Object} [options] returns option results. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the collection or null if an error occurred. + * @return {null} + * @api public + */ +Db.prototype.collection = function(collectionName, options, callback) { + if(typeof options == 'function') callback = options, options = {}; + options = options || {}; + var self = this; + + if(options == null || !options.strict) { + try { + var collection = new Collection(self, collectionName, self.pkFactory, options); + if(callback) callback(null, collection); + return collection; + } catch(err) { + if(callback) return callback(err); + throw err; + } + } + + // Strict mode + if(typeof callback != 'function') { + throw utils.toError(f("A callback is required in strict mode. While getting collection %s.", collectionName)); + } + + self.listCollections(collectionName, function(err, collections) { + if(err != null) return callback(err, null); + if(collections.length == 0) return callback(utils.toError(f("Collection %s does not exist. Currently in strict mode.", collectionName)), null); + + try { + return callback(null, new Collection(self, collectionName, self.pkFactory, options)); + } catch(err) { + return callback(err, null); + } + }); +}; + +/** + * Fetch all collections for the current db. + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the collections or null if an error occurred. + * @return {null} + * @api public + */ +Db.prototype.collections = function(callback) { + var self = this; + // Let's get the collection names + self.collectionNames(function(err, documents) { + if(err != null) return callback(err, null); + var collections = []; + documents.forEach(function(document) { + collections.push(new Collection(self, document.name.replace(self.databaseName + ".", ''), self.pkFactory)); + }); + // Return the collection objects + callback(null, collections); + }); +}; + +/** + * Evaluate javascript on the server + * + * Options + * - **nolock** {Boolean, default:false}, Tell MongoDB not to block on the evaulation of the javascript. + * + * @param {Code} code javascript to execute on server. + * @param {Object|Array} [parameters] the parameters for the call. + * @param {Object} [options] the options + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from eval or null if an error occurred. + * @return {null} + * @api public + */ +Db.prototype.eval = function(code, parameters, options, callback) { + // Unpack calls + var args = Array.prototype.slice.call(arguments, 1); + callback = args.pop(); + parameters = args.length ? args.shift() : parameters; + options = args.length ? args.shift() || {} : {}; + + var finalCode = code; + var finalParameters = []; + // If not a code object translate to one + if(!(finalCode instanceof this.bsonLib.Code)) { + finalCode = new this.bsonLib.Code(finalCode); + } + + // Ensure the parameters are correct + if(parameters != null && parameters.constructor != Array && typeof parameters !== 'function') { + finalParameters = [parameters]; + } else if(parameters != null && parameters.constructor == Array && typeof parameters !== 'function') { + finalParameters = parameters; + } + + // Create execution selector + var cmd = {'$eval':finalCode, 'args':finalParameters}; + // Check if the nolock parameter is passed in + if(options['nolock']) { + cmd['nolock'] = options['nolock']; + } + + // Set primary read preference + options.readPreference = ReadPreference.PRIMARY; + + // Execute the command + this.command(cmd, options, function(err, result) { + if(err) return callback(err, null); + if(result && result.ok == 1) return callback(null, result.retval); + if(result) return callback(new Error("eval failed: " + result.errmsg), null); + callback(err, result); + }); +}; + +/** + * Dereference a dbref, against a db + * + * @param {DBRef} dbRef db reference object we wish to resolve. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from dereference or null if an error occurred. + * @return {null} + * @api public + */ +Db.prototype.dereference = function(dbRef, callback) { + var db = this; + // If we have a db reference then let's get the db first + if(dbRef.db != null) db = this.db(dbRef.db); + // Fetch the collection and find the reference + var collection = db.collection(dbRef.namespace); + collection.findOne({'_id':dbRef.oid}, function(err, result) { + callback(err, result); + }); +} + +/** + * Logout user from server, fire off on all connections and remove all auth info + * + * Options + * - **authMechanism** {String, default:MONGODB-CR}, The authentication mechanism to use, GSSAPI or MONGODB-CR + * - **authdb** {String}, The Db to authenticate against instead of this + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from logout or null if an error occurred. + * @param {Object} [options] the options + * @return {null} + * @api public + */ +Db.prototype.logout = function(options, callback) { + var self = this; + // Unpack calls + var args = Array.prototype.slice.call(arguments, 0); + callback = args.pop(); + options = args.length ? args.shift() || {} : {}; + + // We have passed in an auth db + var runDb = options.authdb ? this.db(options.authdb) : this; + + // Number of connections we need to logout from + var numberOfConnections = this.serverConfig.allRawConnections().length; + // logout command + var cmd = {'logout':1}; + // Add onAll to login to ensure all connection are logged out + options.onAll = true; + + // Execute the command + runDb.command(cmd, options, function(err, result) { + // Count down + numberOfConnections = numberOfConnections - 1; + // Work around the case where the number of connections are 0 + if(numberOfConnections == 0 && typeof callback == 'function') { + var internalCallback = callback; + callback = null; + + // Remove the db from auths + self.serverConfig.auth.remove(self.databaseName); + // Callback with result + internalCallback(null, result.ok == 1 ? true : false); + } + }); +} + +/** + * Authenticate a user against the server. + * authMechanism + * Options + * - **authMechanism** {String, default:MONGODB-CR}, The authentication mechanism to use, GSSAPI or MONGODB-CR + * - **authdb** {String}, The Db to authenticate against instead of this + * + * @param {String} username username. + * @param {String} password password. + * @param {Object} [options] the options + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from authentication or null if an error occurred. + * @return {null} + * @api public + */ +Db.prototype.authenticate = function(username, password, options, callback) { + var self = this; + + if(typeof options == 'function') { + callback = options; + options = {}; + } + + // Set default mechanism + if(!options.authMechanism) { + options.authMechanism = 'DEFAULT'; + } else if(options.authMechanism != 'GSSAPI' + && options.authMechanism != 'MONGODB-CR' + && options.authMechanism != 'MONGODB-X509' + && options.authMechanism != 'SCRAM-SHA-1' + && options.authMechanism != 'PLAIN') { + return callback(new Error("only GSSAPI, PLAIN, MONGODB-X509, SCRAM-SHA-1 or MONGODB-CR is supported by authMechanism")); + } + + // the default db to authenticate against is 'this' + // if authententicate is called from a retry context, it may be another one, like admin + var authdb = options.authdb ? options.authdb : self.databaseName; + authdb = options.authSource ? options.authSource : authdb; + + // Callback + var _callback = function(err, result) { + if(self.listeners("authenticated").length > 0) { + self.emit("authenticated", err, result); + } + + // Return to caller + callback(err, result); + } + + // If classic auth delegate to auth command + if(options.authMechanism == 'MONGODB-CR') { + mongodb_cr_authenticate(self, username, password, authdb, options, _callback); + } else if(options.authMechanism == 'PLAIN') { + mongodb_plain_authenticate(self, username, password, options, _callback); + } else if(options.authMechanism == 'MONGODB-X509') { + mongodb_x509_authenticate(self, username, password, options, _callback); + } else if(options.authMechanism == 'SCRAM-SHA-1') { + mongodb_scram_authenticate(self, username, password, authdb, options, _callback); + } else if(options.authMechanism == 'DEFAULT') { + // Get a server + var servers = this.serverConfig.allServerInstances(); + // if the max wire protocol version >= 3 do scram otherwise mongodb_cr + if(servers.length > 0 && servers[0].isMasterDoc && servers[0].isMasterDoc.maxWireVersion >= 3) { + mongodb_scram_authenticate(self, username, password, authdb, options, _callback); + } else { + mongodb_cr_authenticate(self, username, password, authdb, options, _callback); + } + } else if(options.authMechanism == 'GSSAPI') { + // + // Kerberos library is not installed, throw and error + if(hasKerberos == false) { + console.log("========================================================================================"); + console.log("= Please make sure that you install the Kerberos library to use GSSAPI ="); + console.log("= ="); + console.log("= npm install -g kerberos ="); + console.log("= ="); + console.log("= The Kerberos package is not installed by default for simplicities sake ="); + console.log("= and needs to be global install ="); + console.log("========================================================================================"); + throw new Error("Kerberos library not installed"); + } + + if(process.platform == 'win32') { + mongodb_sspi_authenticate(self, username, password, authdb, options, _callback); + } else { + // We have the kerberos library, execute auth process + mongodb_gssapi_authenticate(self, username, password, authdb, options, _callback); + } + } +}; + +/** + * Add a user to the database. + * + * Options + * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowledgement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal + * - **j**, (Boolean, default:false) write waits for journal sync before returning + * - **customData**, (Object, default:{}) custom data associated with the user (only Mongodb 2.6 or higher) + * - **roles**, (Array, default:[]) roles associated with the created user (only Mongodb 2.6 or higher) + * + * @param {String} username username. + * @param {String} password password. + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from addUser or null if an error occurred. + * @return {null} + * @api public + */ +Db.prototype.addUser = function(username, password, options, callback) { + // Checkout a write connection to get the server capabilities + var connection = this.serverConfig.checkoutWriter(); + if(connection != null + && connection.serverCapabilities != null + && connection.serverCapabilities.hasAuthCommands) { + return _executeAuthCreateUserCommand(this, username, password, options, callback); + } + + // Unpack the parameters + var self = this; + var args = Array.prototype.slice.call(arguments, 2); + callback = args.pop(); + options = args.length ? args.shift() || {} : {}; + + // Get the error options + var errorOptions = _getWriteConcern(this, options); + errorOptions.w = errorOptions.w == null ? 1 : errorOptions.w; + // Use node md5 generator + var md5 = crypto.createHash('md5'); + // Generate keys used for authentication + md5.update(username + ":mongo:" + password); + var userPassword = md5.digest('hex'); + // Fetch a user collection + var collection = this.collection(DbCommand.SYSTEM_USER_COLLECTION); + // Check if we are inserting the first user + collection.count({}, function(err, count) { + // We got an error (f.ex not authorized) + if(err != null) return callback(err, null); + // Check if the user exists and update i + collection.find({user: username}, {dbName: options['dbName']}).toArray(function(err, documents) { + // We got an error (f.ex not authorized) + if(err != null) return callback(err, null); + // Add command keys + var commandOptions = errorOptions; + commandOptions.dbName = options['dbName']; + commandOptions.upsert = true; + + // We have a user, let's update the password or upsert if not + collection.update({user: username},{$set: {user: username, pwd: userPassword}}, commandOptions, function(err, results, full) { + if(count == 0 && err) { + callback(null, [{user:username, pwd:userPassword}]); + } else if(err) { + callback(err, null) + } else { + callback(null, [{user:username, pwd:userPassword}]); + } + }); + }); + }); +}; + +/** + * @ignore + */ +var _executeAuthCreateUserCommand = function(self, username, password, options, callback) { + // Special case where there is no password ($external users) + if(typeof username == 'string' + && password != null && typeof password == 'object') { + callback = options; + options = password; + password = null; + } + + // Unpack all options + if(typeof options == 'function') { + callback = options; + options = {}; + } + + // Error out if we digestPassword set + if(options.digestPassword != null) { + throw utils.toError("The digestPassword option is not supported via add_user. Please use db.command('createUser', ...) instead for this option."); + } + + // Get additional values + var customData = options.customData != null ? options.customData : {}; + var roles = Array.isArray(options.roles) ? options.roles : []; + var maxTimeMS = typeof options.maxTimeMS == 'number' ? options.maxTimeMS : null; + + // If not roles defined print deprecated message + if(roles.length == 0) { + console.log("Creating a user without roles is deprecated in MongoDB >= 2.6"); + } + + // Get the error options + var writeConcern = _getWriteConcern(self, options); + var commandOptions = {writeCommand:true}; + if(options['dbName']) commandOptions.dbName = options['dbName']; + + // Add maxTimeMS to options if set + if(maxTimeMS != null) commandOptions.maxTimeMS = maxTimeMS; + + // Check the db name and add roles if needed + if((self.databaseName.toLowerCase() == 'admin' || options.dbName == 'admin') && !Array.isArray(options.roles)) { + roles = ['root'] + } else if(!Array.isArray(options.roles)) { + roles = ['dbOwner'] + } + + // Build the command to execute + var command = { + createUser: username + , customData: customData + , roles: roles + , digestPassword:false + , writeConcern: writeConcern + } + + // Use node md5 generator + var md5 = crypto.createHash('md5'); + // Generate keys used for authentication + md5.update(username + ":mongo:" + password); + var userPassword = md5.digest('hex'); + + // No password + if(typeof password == 'string') { + command.pwd = userPassword; + } + + // Execute the command + self.command(command, commandOptions, function(err, result) { + if(err) return callback(err, null); + callback(!result.ok ? utils.toError("Failed to add user " + username) : null + , result.ok ? [{user: username, pwd: ''}] : null); + }) +} + +/** + * Remove a user from a database + * + * Options + * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowledgement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal + * - **j**, (Boolean, default:false) write waits for journal sync before returning + * + * @param {String} username username. + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from removeUser or null if an error occurred. + * @return {null} + * @api public + */ +Db.prototype.removeUser = function(username, options, callback) { + // Checkout a write connection to get the server capabilities + var connection = this.serverConfig.checkoutWriter(); + if(connection != null && connection.serverCapabilities != null && connection.serverCapabilities.hasAuthCommands) { + return _executeAuthRemoveUserCommand(this, username, options, callback); + } + + // Unpack the parameters + var self = this; + var args = Array.prototype.slice.call(arguments, 1); + callback = args.pop(); + options = args.length ? args.shift() || {} : {}; + + // Figure out the safe mode settings + var safe = self.safe != null && self.safe == false ? {w: 1} : self.safe; + // Override with options passed in if applicable + safe = options != null && options['safe'] != null ? options['safe'] : safe; + // Ensure it's at least set to safe + safe = safe == null ? {w: 1} : safe; + + // Fetch a user collection + var collection = this.collection(DbCommand.SYSTEM_USER_COLLECTION); + collection.findOne({user: username}, {dbName: options['dbName']}, function(err, user) { + if(user != null) { + // Add command keys + var commandOptions = safe; + commandOptions.dbName = options['dbName']; + + collection.remove({user: username}, commandOptions, function(err, result) { + callback(err, true); + }); + } else { + callback(err, false); + } + }); +}; + +var _executeAuthRemoveUserCommand = function(self, username, options, callback) { + // Unpack all options + if(typeof options == 'function') { + callback = options; + options = {}; + } + + // Get the error options + var writeConcern = _getWriteConcern(self, options); + var commandOptions = {writeCommand:true}; + if(options['dbName']) commandOptions.dbName = options['dbName']; + + // Get additional values + var maxTimeMS = typeof options.maxTimeMS == 'number' ? options.maxTimeMS : null; + + // Add maxTimeMS to options if set + if(maxTimeMS != null) commandOptions.maxTimeMS = maxTimeMS; + + // Build the command to execute + var command = { + dropUser: username + , writeConcern: writeConcern + } + + // Execute the command + self.command(command, commandOptions, function(err, result) { + if(err) return callback(err, null); + callback(null, result.ok ? true : false); + }) +} + +/** + * Creates a collection on a server pre-allocating space, need to create f.ex capped collections. + * + * Options +* - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowledgement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal + * - **j**, (Boolean, default:false) write waits for journal sync before returning + * - **serializeFunctions** {Boolean, default:false}, serialize functions on the document. + * - **raw** {Boolean, default:false}, perform all operations using raw bson objects. + * - **pkFactory** {Object}, object overriding the basic ObjectID primary key generation. + * - **capped** {Boolean, default:false}, create a capped collection. + * - **size** {Number}, the size of the capped collection in bytes. + * - **max** {Number}, the maximum number of documents in the capped collection. + * - **autoIndexId** {Boolean, default:true}, create an index on the _id field of the document, True by default on MongoDB 2.2 or higher off for version < 2.2. + * - **readPreference** {String}, the preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). + * - **strict**, (Boolean, default:false) throws an error if collection already exists + * + * @param {String} collectionName the collection name we wish to access. + * @param {Object} [options] returns option results. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from createCollection or null if an error occurred. + * @return {null} + * @api public + */ +Db.prototype.createCollection = function(collectionName, options, callback) { + var self = this; + if(typeof options == 'function') { + callback = options; + options = {}; + } + + // Figure out the safe mode settings + var safe = self.safe != null && self.safe == false ? {w: 1} : self.safe; + // Override with options passed in if applicable + safe = options != null && options['safe'] != null ? options['safe'] : safe; + // Ensure it's at least set to safe + safe = safe == null ? {w: 1} : safe; + // Check if we have the name + this.listCollections(collectionName, function(err, collections) { + if(err != null) return callback(err, null); + if(collections.length > 0 && options.strict) { + return callback(utils.toError(f("Collection %s already exists. Currently in strict mode.", collectionName)), null); + } else if (collections.length > 0) { + try { return callback(null, new Collection(self, collectionName, self.pkFactory, options)); } + catch(err) { return callback(err); } + } + + // logout command + var cmd = {'create':collectionName}; + + for(var name in options) { + if(options[name] != null && typeof options[name] != 'function') cmd[name] = options[name]; + } + + // Execute the command + self.command(cmd, options, function(err, result) { + if(err && err.code && err.code != 48 && options && options.strict) return callback(err, null); + try { + callback(null, new Collection(self, collectionName, self.pkFactory, options)); + } catch(err) { + callback(utils.toError(err), null); + } + }); + }); +}; + +var _getReadConcern = function(self, options) { + if(options.readPreference) return options.readPreference; + if(self.readPreference) return self.readPreference; + return 'primary'; +} + +/** + * Execute a command hash against MongoDB. This lets you acess any commands not available through the api on the server. + * + * Options + * - **readPreference** {String}, the preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). + * - **maxTimeMS** {Number}, number of milliseconds to wait before aborting the query. + * - **ignoreCommandFilter** {Boolean}, overrides the default redirection of certain commands to primary. + * - **writeCommand** {Boolean, default: false}, signals this is a write command and to ignore read preferences + * - **checkKeys** {Boolean, default: false}, overrides the default not to check the key names for the command + * + * @param {Object} selector the command hash to send to the server, ex: {ping:1}. + * @param {Object} [options] additional options for the command. + * @param {Function} callback this will be called after executing this method. The command always return the whole result of the command as the second parameter. + * @return {null} + * @api public + */ +Db.prototype.command = function(selector, options, callback) { + if(typeof options == 'function') { + callback = options; + options = {}; + } + + // Make a shallow copy so no modifications happen on the original + options = utils.shallowObjectCopy(options); + + // Ignore command preference (I know what I'm doing) + var ignoreCommandFilter = options.ignoreCommandFilter ? options.ignoreCommandFilter : false; + + // Get read preference if we set one + var readPreference = _getReadConcern(this, options); + + // Ensure only commands who support read Prefrences are exeuted otherwise override and use Primary + if(readPreference != false && ignoreCommandFilter == false) { + if(selector['group'] || selector['aggregate'] || selector['collStats'] || selector['dbStats'] + || selector['count'] || selector['distinct'] || selector['geoNear'] || selector['geoSearch'] + || selector['geoWalk'] || selector['text'] || selector['cursorInfo'] + || selector['parallelCollectionScan'] + || (selector['mapreduce'] && (selector.out == 'inline' || selector.out.inline))) { + // Set the read preference + options.readPreference = readPreference; + } else { + options.readPreference = ReadPreference.PRIMARY; + } + } else if(readPreference != false) { + options.readPreference = readPreference; + } + + // Add the maxTimeMS option to the command if specified + if(typeof options.maxTimeMS == 'number') { + selector.maxTimeMS = options.maxTimeMS + } + + // Command options + var command_options = {}; + + // Do we have an override for checkKeys + if(typeof options['checkKeys'] == 'boolean') command_options['checkKeys'] = options['checkKeys']; + command_options['checkKeys'] = typeof options['checkKeys'] == 'boolean' ? options['checkKeys'] : false; + if(typeof options['serializeFunctions'] == 'boolean') command_options['serializeFunctions'] = options['serializeFunctions']; + if(options['dbName']) command_options['dbName'] = options['dbName']; + + // If we have a write command, remove readPreference as an option + if((options.writeCommand + || selector['findAndModify'] + || selector['insert'] || selector['update'] || selector['delete'] + || selector['createUser'] || selector['updateUser'] || selector['removeUser']) + && options.readPreference) { + delete options['readPreference']; + } + + // Add a write concern if we have passed in any + if(options.w || options.wtimeout || options.j || options.fsync || options.safe) { + selector.writeConcern = {}; + if(options.safe) selector.writeConcern.w = 1; + if(options.w) selector.writeConcern.w = options.w; + if(options.wtimeout) selector.writeConcern.wtimeout = options.wtimeout; + if(options.j) selector.writeConcern.j = options.j; + if(options.fsync) selector.writeConcern.fsync = options.fsync; + } + + // If we have an actual writeConcern object override + if(options.writeConcern) { + selector.writeConcern = writeConcern; + } + + // Check if we need to set slaveOk + if(command_options.readPreference != 'primary') + command_options.slaveOk = true; + + // Execution db + var execDb = typeof options.auth == 'string' ? this.db(options.auth) : this; + execDb = typeof options.authdb == 'string' ? this.db(options.authdb) : execDb; + + // Execute a query command + this._executeQueryCommand(DbCommand.createDbSlaveOkCommand(execDb, selector, command_options), options, function(err, results, connection) { + if(options.returnConnection) { + if(err) return callback(err, null, connection); + if(results == null || results.documents == null) return callback(new Error("command failed to return result")); + if(results.documents[0].errmsg) + return callback(utils.toError(results.documents[0]), null, connection); + callback(null, results.documents[0], connection); + } else { + if(err) return callback(err, null); + if(results == null || results.documents == null) return callback(new Error("command failed to return result")); + if(results.documents[0].errmsg) + return callback(utils.toError(results.documents[0]), null); + callback(null, results.documents[0]); + } + }); +}; + +/** + * Drop a collection from the database, removing it permanently. New accesses will create a new collection. + * + * @param {String} collectionName the name of the collection we wish to drop. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from dropCollection or null if an error occurred. + * @return {null} + * @api public + */ +Db.prototype.dropCollection = function(collectionName, callback) { + var self = this; + callback || (callback = function(){}); + + // Command to execute + var cmd = {'drop':collectionName} + + // Execute the command + this.command(cmd, {}, function(err, result) { + if(err) return callback(err, null); + if(result.ok) return callback(null, true); + callback(null, false); + }); +}; + +/** + * Rename a collection. + * + * Options + * - **dropTarget** {Boolean, default:false}, drop the target name collection if it previously exists. + * + * @param {String} fromCollection the name of the current collection we wish to rename. + * @param {String} toCollection the new name of the collection. + * @param {Object} [options] returns option results. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from renameCollection or null if an error occurred. + * @return {null} + * @api public + */ +Db.prototype.renameCollection = function(fromCollection, toCollection, options, callback) { + var self = this; + + if(typeof options == 'function') { + callback = options; + options = {} + } + + // Add return new collection + options.new_collection = true; + + // Execute using the collection method + this.collection(fromCollection).rename(toCollection, options, callback); +}; + +/** + * Runs a command on the database. + * @ignore + * @api private + */ +Db.prototype.executeDbCommand = function(command_hash, options, callback) { + if(callback == null) { callback = options; options = {}; } + this._executeQueryCommand(DbCommand.createDbSlaveOkCommand(this, command_hash, options), options, function(err, result) { + if(callback) callback(err, result); + }); +}; + +/** + * Runs a command on the database as admin. + * @ignore + * @api private + */ +Db.prototype.executeDbAdminCommand = function(command_hash, options, callback) { + if(typeof options == 'function') { + callback = options; + options = {} + } + + if(options.readPreference) { + options.readPreference = options.readPreference; + } + + this._executeQueryCommand(DbCommand.createAdminDbCommand(this, command_hash), options, function(err, result) { + if(callback) callback(err, result); + }); +}; + +/** + * Creates an index on the collection. + * + * Options +* - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowledgement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal + * - **j**, (Boolean, default:false) write waits for journal sync before returning + * - **unique** {Boolean, default:false}, creates an unique index. + * - **sparse** {Boolean, default:false}, creates a sparse index. + * - **background** {Boolean, default:false}, creates the index in the background, yielding whenever possible. + * - **min** {Number}, for geospatial indexes set the lower bound for the co-ordinates. + * - **max** {Number}, for geospatial indexes set the high bound for the co-ordinates. + * - **v** {Number}, specify the format version of the indexes. + * - **expireAfterSeconds** {Number}, allows you to expire data on indexes applied to a data (MongoDB 2.2 or higher) + * - **name** {String}, override the autogenerated index name (useful if the resulting name is larger than 128 bytes) + * + * @param {String} collectionName name of the collection to create the index on. + * @param {Object} fieldOrSpec fieldOrSpec that defines the index. + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from createIndex or null if an error occurred. + * @return {null} + * @api public + */ +Db.prototype.createIndex = function(collectionName, fieldOrSpec, options, callback) { + var self = this; + var args = Array.prototype.slice.call(arguments, 2); + callback = args.pop(); + options = args.length ? args.shift() || {} : {}; + options = typeof callback === 'function' ? options : callback; + options = options == null ? {} : options; + + // Get the error options + var writeConcern = _getWriteConcern(self, options); + // Ensure we have a callback + if(_hasWriteConcern(writeConcern) && typeof callback != 'function') { + throw new Error("Cannot use a writeConcern without a provided callback"); + } + + // Attempt to run using createIndexes command + createIndexUsingCreateIndexes(self, collectionName, fieldOrSpec, options, function(err, result) { + if(err == null) { + return callback(err, result); + } + + // Create command + var command = createCreateIndexCommand(self, collectionName, fieldOrSpec, options); + // Default command options + var commandOptions = {}; + + // If we have error conditions set handle them + if(_hasWriteConcern(writeConcern) && typeof callback == 'function') { + // Set safe option + commandOptions['safe'] = writeConcern; + // If we have an error option + if(typeof writeConcern == 'object') { + var keys = Object.keys(writeConcern); + for(var i = 0; i < keys.length; i++) { + commandOptions[keys[i]] = writeConcern[keys[i]]; + } + } + + // Execute insert command + self._executeInsertCommand(command, commandOptions, function(err, result) { + if(err != null) return callback(err, null); + if(result == null || result.documents == null) return callback(new Error("command failed to return result")); + + result = result && result.documents; + if (result[0].err) { + callback(utils.toError(result[0])); + } else { + callback(null, command.documents[0].name); + } + }); + } else { + // Execute insert command + var result = self._executeInsertCommand(command, commandOptions, function() {}); + // If no callback just return + if(!callback) return; + // If error return error + if(result instanceof Error) { + return callback(result); + } + // Otherwise just return + return callback(null, null); + } + }); +}; + +var createCreateIndexCommand = function(db, collectionName, fieldOrSpec, options) { + var indexParameters = utils.parseIndexOptions(fieldOrSpec); + var fieldHash = indexParameters.fieldHash; + var keys = indexParameters.keys; + + // Generate the index name + var indexName = typeof options.name == 'string' + ? options.name + : indexParameters.name; + + var selector = { + 'ns': db.databaseName + "." + collectionName, + 'key': fieldHash, + 'name': indexName + } + + // Ensure we have a correct finalUnique + var finalUnique = options == null || 'object' === typeof options + ? false + : options; + + // Set up options + options = options == null || typeof options == 'boolean' + ? {} + : options; + + // Add all the options + var keysToOmit = Object.keys(selector); + for(var optionName in options) { + if(keysToOmit.indexOf(optionName) == -1) { + selector[optionName] = options[optionName]; + } + } + + if(selector['unique'] == null) + selector['unique'] = finalUnique; + + var name = db.databaseName + "." + DbCommand.SYSTEM_INDEX_COLLECTION; + var cmd = new InsertCommand(db, name, false); + return cmd.add(selector); +} + +var createIndexUsingCreateIndexes = function(self, collectionName, fieldOrSpec, options, callback) { + // Build the index + var indexParameters = utils.parseIndexOptions(fieldOrSpec); + // Generate the index name + var indexName = typeof options.name == 'string' + ? options.name + : indexParameters.name; + + // Set up the index + var indexes = [{ + name: indexName + , key: indexParameters.fieldHash + }]; + + // merge all the options + var keysToOmit = Object.keys(indexes[0]); + for(var optionName in options) { + if(keysToOmit.indexOf(optionName) == -1) { + indexes[0][optionName] = options[optionName]; + } + } + + // Create command + var command = {createIndexes: collectionName, indexes: indexes}; + // Build the command + self.command(command, options, function(err, result) { + if(err) return callback(err, null); + if(result.ok == 0) { + return callback(utils.toError(result), null); + } + + // Return the indexName for backward compatibility + callback(null, indexName); + }); +} + +/** + * Ensures that an index exists, if it does not it creates it + * + * Options + * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowledgement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal + * - **j**, (Boolean, default:false) write waits for journal sync before returning + * - **unique** {Boolean, default:false}, creates an unique index. + * - **sparse** {Boolean, default:false}, creates a sparse index. + * - **background** {Boolean, default:false}, creates the index in the background, yielding whenever possible. + * - **min** {Number}, for geospatial indexes set the lower bound for the co-ordinates. + * - **max** {Number}, for geospatial indexes set the high bound for the co-ordinates. + * - **v** {Number}, specify the format version of the indexes. + * - **expireAfterSeconds** {Number}, allows you to expire data on indexes applied to a data (MongoDB 2.2 or higher) + * - **name** {String}, override the autogenerated index name (useful if the resulting name is larger than 128 bytes) + * + * @param {String} collectionName name of the collection to create the index on. + * @param {Object} fieldOrSpec fieldOrSpec that defines the index. + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from ensureIndex or null if an error occurred. + * @return {null} + * @api public + */ +Db.prototype.ensureIndex = function(collectionName, fieldOrSpec, options, callback) { + var self = this; + + if(typeof callback === 'undefined' && typeof options === 'function') { + callback = options; + options = {}; + } + + // Ensure non empty options + options = options || {}; + + // Get the error options + var writeConcern = _getWriteConcern(this, options); + // Make sure we don't try to do a write concern without a callback + if(_hasWriteConcern(writeConcern) && callback == null) + throw new Error("Cannot use a writeConcern without a provided callback"); + + // Create command + var command = createCreateIndexCommand(this, collectionName, fieldOrSpec, options); + var index_name = command.documents[0].name; + + // Check if the index allready exists + this.indexInformation(collectionName, writeConcern, function(err, indexInformation) { + if(err != null) return callback(err, null); + // If the index does not exist, create it + if(!indexInformation[index_name]) { + self.createIndex(collectionName, fieldOrSpec, options, callback); + } else { + if(typeof callback === 'function') return callback(null, index_name); + } + }); +}; + +/** + * Returns the information available on allocated cursors. + * + * Options + * - **readPreference** {String}, the preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). + * + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from cursorInfo or null if an error occurred. + * @return {null} + * @api public + */ +Db.prototype.cursorInfo = function(options, callback) { + var args = Array.prototype.slice.call(arguments, 0); + callback = args.pop(); + options = args.length ? args.shift() || {} : {}; + + // cursorInfo command + var cmd = {'cursorInfo':1}; + + // Execute the command + this.command(cmd, options, function(err, result) { + if(err) return callback(err, null); + callback(null, result); + }); +}; + +/** + * Drop an index on a collection. + * + * @param {String} collectionName the name of the collection where the command will drop an index. + * @param {String} indexName name of the index to drop. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from dropIndex or null if an error occurred. + * @return {null} + * @api public + */ +Db.prototype.dropIndex = function(collectionName, indexName, options, callback) { + var args = Array.prototype.slice.call(arguments, 2); + callback = args.pop(); + options = args.length ? args.shift() || {} : {}; + + // Delete index command + var cmd = {'deleteIndexes':collectionName, 'index':indexName}; + + // Execute command + this.command(cmd, options, function(err, result) { + if(callback == null) return; + if(err) return callback(err, null); + callback(null, result); + }); +}; + +/** + * Reindex all indexes on the collection + * Warning: reIndex is a blocking operation (indexes are rebuilt in the foreground) and will be slow for large collections. + * + * @param {String} collectionName the name of the collection. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from reIndex or null if an error occurred. + * @api public +**/ +Db.prototype.reIndex = function(collectionName, options, callback) { + if(typeof options == 'function') { + callback = options; + options = {}; + } + + // Reindex + var cmd = {'reIndex':collectionName}; + + // Execute the command + this.command(cmd, options, function(err, result) { + if(callback == null) return; + if(err) return callback(err, null); + callback(null, result.ok ? true : false); + }); +}; + +/** + * Retrieves this collections index info. + * + * Options + * - **full** {Boolean, default:false}, returns the full raw index information. + * - **readPreference** {String}, the preferred read preference ((Server.PRIMARY, Server.PRIMARY_PREFERRED, Server.SECONDARY, Server.SECONDARY_PREFERRED, Server.NEAREST). + * + * @param {String} collectionName the name of the collection. + * @param {Object} [options] additional options during update. + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from indexInformation or null if an error occurred. + * @return {null} + * @api public + */ +Db.prototype.indexInformation = function(name, options, callback) { + if(typeof callback === 'undefined') { + if(typeof options === 'undefined') { + callback = name; + name = null; + } else { + callback = options; + } + options = {}; + } + + // Throw is no name provided + if(name == null) throw new Error("A collection name must be provided as first argument"); + + // If we specified full information + var full = options['full'] == null ? false : options['full']; + var self = this; + + // Process all the results from the index command and collection + var processResults = function(indexes) { + // Contains all the information + var info = {}; + // Process all the indexes + for(var i = 0; i < indexes.length; i++) { + var index = indexes[i]; + // Let's unpack the object + info[index.name] = []; + for(var name in index.key) { + info[index.name].push([name, index.key[name]]); + } + } + + return info; + } + + // Fallback to pre 2.8 getting the index information + var fallbackListIndexes = function() { + // Build selector for the indexes + var selector = name != null ? {ns: (self.databaseName + "." + name)} : {}; + + // Get read preference if we set one + var readPreference = ReadPreference.PRIMARY; + + // Iterate through all the fields of the index + var collection = self.collection(DbCommand.SYSTEM_INDEX_COLLECTION); + // Perform the find for the collection + collection.find(selector).setReadPreference(readPreference).toArray(function(err, indexes) { + if(err != null) return callback(err, null); + // if full defined just return all the indexes directly + if(full) return callback(null, indexes); + // Return all the indexes + callback(null, processResults(indexes)); + }); + } + + // Attempt to execute the listIndexes command + self.command({listIndexes: name}, function(err, result) { + if(err) return fallbackListIndexes(); + // if full defined just return all the indexes directly + if(full) return callback(null, result.indexes); + // Return all the indexes + callback(null, processResults(result.indexes)); + }); +}; + +/** + * Drop a database. + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from dropDatabase or null if an error occurred. + * @return {null} + * @api public + */ +Db.prototype.dropDatabase = function(options, callback) { + if(typeof options == 'function') { + callback = options; + options = {}; + } + + // Reindex + var cmd = {'dropDatabase':1}; + + // Execute the command + this.command(cmd, options, function(err, result) { + if(callback == null) return; + if(err) return callback(err, null); + callback(null, result.ok ? true : false); + }); +} + +/** + * Get all the db statistics. + * + * Options + * - **scale** {Number}, divide the returned sizes by scale value. + * - **readPreference** {String}, the preferred read preference ((Server.PRIMARY, Server.PRIMARY_PREFERRED, Server.SECONDARY, Server.SECONDARY_PREFERRED, Server.NEAREST). + * + * @param {Objects} [options] options for the stats command + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from stats or null if an error occurred. + * @return {null} + * @api public + */ +Db.prototype.stats = function stats(options, callback) { + var args = Array.prototype.slice.call(arguments, 0); + callback = args.pop(); + // Fetch all commands + options = args.length ? args.shift() || {} : {}; + + // Build command object + var commandObject = { + dbStats:true + }; + + // Check if we have the scale value + if(options['scale'] != null) commandObject['scale'] = options['scale']; + + // Execute the command + this.command(commandObject, options, callback); +} + +/** + * @ignore + */ +var bindToCurrentDomain = function(callback) { + var domain = process.domain; + if(domain == null || callback == null) { + return callback; + } else { + return domain.bind(callback); + } +} + +/** + * @ignore + */ +var __executeQueryCommand = function(self, db_command, options, callback) { + // Options unpacking + var readPreference = options.readPreference != null ? options.readPreference : 'primary'; + var onAll = options['onAll'] != null ? options['onAll'] : false; + var specifiedConnection = options['connection'] != null ? options['connection'] : null; + var raw = typeof options.raw == 'boolean' ? options.raw : false; + + // Correct readPreference preference to default primary if set to false, null or primary + if(!(typeof readPreference == 'object') && readPreference._type == 'ReadPreference') { + readPreference = (readPreference == null || readPreference == 'primary' || readPreference == false) ? ReadPreference.PRIMARY : readPreference; + if(!ReadPreference.isValid(readPreference)) return callback(new Error("Illegal readPreference mode specified, " + JSON.stringify(readPreference))); + } else if(typeof readPreference == 'object' && readPreference._type == 'ReadPreference') { + if(!readPreference.isValid()) return callback(new Error("Illegal readPreference mode specified, " + JSON.stringify(readPreference))); + } + + // If we have a read preference set and we are a mongos pass the read preference on to the mongos instance, + if(self.serverConfig.isMongos() && readPreference != null && readPreference != 'primary') { + db_command.setMongosReadPreference(readPreference); + } + + // If we got a callback object + if(typeof callback === 'function' && !onAll) { + callback = bindToCurrentDomain(callback); + // Override connection if we passed in a specific connection + var connection = specifiedConnection != null ? specifiedConnection : null; + + if(connection instanceof Error) return callback(connection, null); + + // Fetch either a reader or writer dependent on the specified readPreference option if no connection + // was passed in + if(connection == null) { + connection = self.serverConfig.checkoutReader(readPreference); + } + + if(connection == null) { + return callback(new Error("no open connections")); + } else if(connection instanceof Error || connection['message'] != null) { + return callback(connection); + } + + // Exhaust Option + var exhaust = options.exhaust || false; + + // Register the handler in the data structure + self.serverConfig._registerHandler(db_command, raw, connection, exhaust, callback); + + // Write the message out and handle any errors if there are any + connection.write(db_command, function(err) { + if(err != null) { + // Call the handler with an error + if(Array.isArray(db_command)) + self.serverConfig._callHandler(db_command[0].getRequestId(), null, err); + else + self.serverConfig._callHandler(db_command.getRequestId(), null, err); + } + }); + } else if(typeof callback === 'function' && onAll) { + callback = bindToCurrentDomain(callback); + var connections = self.serverConfig.allRawConnections(); + var numberOfEntries = connections.length; + // Go through all the connections + for(var i = 0; i < connections.length; i++) { + // Fetch a connection + var connection = connections[i]; + + // Ensure we have a valid connection + if(connection == null) { + return callback(new Error("no open connections")); + } else if(connection instanceof Error) { + return callback(connection); + } + + // Register the handler in the data structure + self.serverConfig._registerHandler(db_command, raw, connection, callback); + + // Write the message out + connection.write(db_command, function(err) { + // Adjust the number of entries we need to process + numberOfEntries = numberOfEntries - 1; + // Remove listener + if(err != null) { + // Clean up listener and return error + self.serverConfig._removeHandler(db_command.getRequestId()); + } + + // No more entries to process callback with the error + if(numberOfEntries <= 0) { + callback(err); + } + }); + + // Update the db_command request id + db_command.updateRequestId(); + } + } else { + // Fetch either a reader or writer dependent on the specified read option + var connection = self.serverConfig.checkoutReader(readPreference); + // Override connection if needed + connection = specifiedConnection != null ? specifiedConnection : connection; + // Ensure we have a valid connection + if(connection == null || connection instanceof Error || connection['message'] != null) return null; + // Write the message out + connection.write(db_command, function(err) { + if(err != null) { + // Emit the error + self.emit("error", err); + } + }); + } +}; + +/** + * Execute db query command (not safe) + * @ignore + * @api private + */ +Db.prototype._executeQueryCommand = function(db_command, options, callback) { + var self = this; + + // Unpack the parameters + if(typeof options === 'function') { + callback = options; + options = {}; + } + callback = bindToCurrentDomain(callback); + + // fast fail option used for HA, no retry + var failFast = options['failFast'] != null + ? options['failFast'] + : false; + + // Check if the user force closed the command + if(this._applicationClosed) { + var err = new Error("db closed by application"); + if('function' == typeof callback) { + return callback(err, null); + } else { + throw err; + } + } + + if(this.serverConfig.isDestroyed()) + return callback(new Error("Connection was destroyed by application")); + + // Specific connection + var connection = options.connection; + // Check if the connection is actually live + if(connection + && (!connection.isConnected || !connection.isConnected())) connection = null; + + // Get the configuration + var config = this.serverConfig; + var readPreference = options.readPreference; + // Allow for the usage of the readPreference model + if(readPreference == null) { + readPreference = options.readPreference; + } + + if(!connection && !config.canRead(readPreference) && !config.canWrite() && config.isAutoReconnect()) { + + if(readPreference == ReadPreference.PRIMARY + || readPreference == ReadPreference.PRIMARY_PREFERRED + || (readPreference != null && typeof readPreference == 'object' && readPreference.mode) + || readPreference == null) { + + // Save the command + self.serverConfig._commandsStore.read_from_writer( + { type: 'query' + , db_command: db_command + , options: options + , callback: callback + , db: self + , executeQueryCommand: __executeQueryCommand + , executeInsertCommand: __executeInsertCommand + } + ); + } else { + self.serverConfig._commandsStore.read( + { type: 'query' + , db_command: db_command + , options: options + , callback: callback + , db: self + , executeQueryCommand: __executeQueryCommand + , executeInsertCommand: __executeInsertCommand + } + ); + } + + // If we have blown through the number of items let's + if(!self.serverConfig._commandsStore.validateBufferLimit(self.bufferMaxEntries)) { + self.close(); + } + } else if(!connection && !config.canRead(readPreference) && !config.canWrite() && !config.isAutoReconnect()) { + return callback(new Error("no open connections"), null); + } else { + if(typeof callback == 'function') { + __executeQueryCommand(self, db_command, options, function (err, result, conn) { + callback(err, result, conn); + }); + } else { + __executeQueryCommand(self, db_command, options); + } + } +}; + +/** + * @ignore + */ +var __executeInsertCommand = function(self, db_command, options, callback) { + // Always checkout a writer for this kind of operations + var connection = self.serverConfig.checkoutWriter(); + // Get safe mode + var safe = options['safe'] != null ? options['safe'] : false; + var specifiedConnection = options['connection'] != null ? options['connection'] : null; + // Override connection if needed + connection = specifiedConnection != null ? specifiedConnection : connection; + + // Validate if we can use this server 2.6 wire protocol + if(connection && !connection.isCompatible()) { + return callback(utils.toError("driver is incompatible with this server version"), null); + } + + // Ensure we have a valid connection + if(typeof callback === 'function') { + callback = bindToCurrentDomain(callback); + // Ensure we have a valid connection + if(connection == null) { + return callback(new Error("no open connections")); + } else if(connection instanceof Error) { + return callback(connection); + } + + var errorOptions = _getWriteConcern(self, options); + if(errorOptions.w > 0 || errorOptions.w == 'majority' || errorOptions.j || errorOptions.journal || errorOptions.fsync) { + // db command is now an array of commands (original command + lastError) + db_command = [db_command, DbCommand.createGetLastErrorCommand(errorOptions, self)]; + // Register the handler in the data structure + self.serverConfig._registerHandler(db_command[1], false, connection, callback); + } + } + + // If we have no callback and there is no connection + if(connection == null) return null; + if(connection instanceof Error && typeof callback == 'function') return callback(connection, null); + if(connection instanceof Error) return null; + if(connection == null && typeof callback == 'function') return callback(new Error("no primary server found"), null); + + // Write the message out + connection.write(db_command, function(err) { + // Return the callback if it's not a safe operation and the callback is defined + if(typeof callback === 'function' && (safe == null || safe == false)) { + // Perform the callback + callback(err, null); + } else if(typeof callback === 'function') { + // Call the handler with an error + self.serverConfig._callHandler(db_command[1].getRequestId(), null, err); + } else if(typeof callback == 'function' && safe && safe.w == -1) { + // Call the handler with no error + self.serverConfig._callHandler(db_command[1].getRequestId(), null, null); + } else if(!safe || safe.w == -1) { + self.emit("error", err); + } + }); +}; + +/** + * Execute an insert Command + * @ignore + * @api private + */ +Db.prototype._executeInsertCommand = function(db_command, options, callback) { + var self = this; + + // Unpack the parameters + if(callback == null && typeof options === 'function') { + callback = options; + options = {}; + } + callback = bindToCurrentDomain(callback); + // Ensure options are not null + options = options == null ? {} : options; + + // Check if the user force closed the command + if(this._applicationClosed) { + if(typeof callback == 'function') { + return callback(new Error("db closed by application"), null); + } else { + throw new Error("db closed by application"); + } + } + + if(this.serverConfig.isDestroyed()) return callback(new Error("Connection was destroyed by application")); + + // Specific connection + var connection = options.connection; + // Check if the connection is actually live + if(connection + && (!connection.isConnected || !connection.isConnected())) connection = null; + + // Get config + var config = self.serverConfig; + // Check if we are connected + if(!connection && !config.canWrite() && config.isAutoReconnect()) { + self.serverConfig._commandsStore.write( + { type:'insert' + , 'db_command':db_command + , 'options':options + , 'callback':callback + , db: self + , executeQueryCommand: __executeQueryCommand + , executeInsertCommand: __executeInsertCommand + } + ); + + // If we have blown through the number of items let's + if(!self.serverConfig._commandsStore.validateBufferLimit(self.bufferMaxEntries)) { + self.close(); + } + } else if(!connection && !config.canWrite() && !config.isAutoReconnect()) { + return callback(new Error("no open connections"), null); + } else { + __executeInsertCommand(self, db_command, options, callback); + } +}; + +/** + * Update command is the same + * @ignore + * @api private + */ +Db.prototype._executeUpdateCommand = Db.prototype._executeInsertCommand; +/** + * Remove command is the same + * @ignore + * @api private + */ +Db.prototype._executeRemoveCommand = Db.prototype._executeInsertCommand; + +/** + * Wrap a Mongo error document into an Error instance. + * Deprecated. Use utils.toError instead. + * + * @ignore + * @api private + * @deprecated + */ +Db.prototype.wrap = utils.toError; + +/** + * Default URL + * + * @classconstant DEFAULT_URL + **/ +Db.DEFAULT_URL = 'mongodb://localhost:27017/default'; + +/** + * Connect to MongoDB using a url as documented at + * + * docs.mongodb.org/manual/reference/connection-string/ + * + * Options + * - **uri_decode_auth** {Boolean, default:false} uri decode the user name and password for authentication + * - **db** {Object, default: null} a hash off options to set on the db object, see **Db constructor** + * - **server** {Object, default: null} a hash off options to set on the server objects, see **Server** constructor** + * - **replSet** {Object, default: null} a hash off options to set on the replSet object, see **ReplSet** constructor** + * - **mongos** {Object, default: null} a hash off options to set on the mongos object, see **Mongos** constructor** + * + * @param {String} url connection url for MongoDB. + * @param {Object} [options] optional options for insert command + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the db instance or null if an error occurred. + * @return {null} + * @api public + */ +Db.connect = function(url, options, callback) { + // Ensure correct mapping of the callback + if(typeof options == 'function') { + callback = options; + options = {}; + } + + // Ensure same behavior as previous version w:0 + if(url.indexOf("safe") == -1 + && url.indexOf("w") == -1 + && url.indexOf("journal") == -1 && url.indexOf("j") == -1 + && url.indexOf("fsync") == -1) options.w = 1; + + // Avoid circular require problem + var MongoClient = require('./mongo_client.js').MongoClient; + // Attempt to connect + MongoClient.connect.call(MongoClient, url, options, callback); +}; + +/** + * State of the db connection + * @ignore + */ +Object.defineProperty(Db.prototype, "state", { enumerable: true + , get: function () { + return this.serverConfig._serverState; + } +}); + +/** + * @ignore + */ +var _hasWriteConcern = function(errorOptions) { + return errorOptions == true + || errorOptions.w > 0 + || errorOptions.w == 'majority' + || errorOptions.j == true + || errorOptions.journal == true + || errorOptions.fsync == true +}; + +/** + * @ignore + */ +var _setWriteConcernHash = function(options) { + var finalOptions = {}; + if(options.w != null) finalOptions.w = options.w; + if(options.journal == true) finalOptions.j = options.journal; + if(options.j == true) finalOptions.j = options.j; + if(options.fsync == true) finalOptions.fsync = options.fsync; + if(options.wtimeout != null) finalOptions.wtimeout = options.wtimeout; + return finalOptions; +}; + +/** + * @ignore + */ +var _getWriteConcern = function(self, options) { + // Final options + var finalOptions = {w:1}; + // Local options verification + if(options.w != null || typeof options.j == 'boolean' || typeof options.journal == 'boolean' || typeof options.fsync == 'boolean') { + finalOptions = _setWriteConcernHash(options); + } else if(options.safe != null && typeof options.safe == 'object') { + finalOptions = _setWriteConcernHash(options.safe); + } else if(typeof options.safe == "boolean") { + finalOptions = {w: (options.safe ? 1 : 0)}; + } else if(self.options.w != null || typeof self.options.j == 'boolean' || typeof self.options.journal == 'boolean' || typeof self.options.fsync == 'boolean') { + finalOptions = _setWriteConcernHash(self.options); + } else if(self.safe.w != null || typeof self.safe.j == 'boolean' || typeof self.safe.journal == 'boolean' || typeof self.safe.fsync == 'boolean') { + finalOptions = _setWriteConcernHash(self.safe); + } else if(typeof self.safe == "boolean") { + finalOptions = {w: (self.safe ? 1 : 0)}; + } + + // Ensure we don't have an invalid combination of write concerns + if(finalOptions.w < 1 + && (finalOptions.journal == true || finalOptions.j == true || finalOptions.fsync == true)) throw new Error("No acknowledgement using w < 1 cannot be combined with journal:true or fsync:true"); + + // Return the options + return finalOptions; +} + +/** + * Legacy support + * + * @ignore + * @api private + */ +exports.connect = Db.connect; +exports.Db = Db; + +/** + * Remove all listeners to the db instance. + * @ignore + * @api private + */ +Db.prototype.removeAllEventListeners = function() { + this.removeAllListeners("close"); + this.removeAllListeners("error"); + this.removeAllListeners("timeout"); + this.removeAllListeners("parseError"); + this.removeAllListeners("poolReady"); + this.removeAllListeners("message"); +}; diff --git a/node_modules/mongodb/lib/mongodb/gridfs/chunk.js b/node_modules/mongodb/lib/mongodb/gridfs/chunk.js new file mode 100644 index 0000000..8cddafe --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/gridfs/chunk.js @@ -0,0 +1,232 @@ +var Binary = require('bson').Binary, + ObjectID = require('bson').ObjectID; + +/** + * Class for representing a single chunk in GridFS. + * + * @class + * + * @param file {GridStore} The {@link GridStore} object holding this chunk. + * @param mongoObject {object} The mongo object representation of this chunk. + * + * @throws Error when the type of data field for {@link mongoObject} is not + * supported. Currently supported types for data field are instances of + * {@link String}, {@link Array}, {@link Binary} and {@link Binary} + * from the bson module + * + * @see Chunk#buildMongoObject + */ +var Chunk = exports.Chunk = function(file, mongoObject, writeConcern) { + if(!(this instanceof Chunk)) return new Chunk(file, mongoObject); + + this.file = file; + var self = this; + var mongoObjectFinal = mongoObject == null ? {} : mongoObject; + this.writeConcern = writeConcern || {w:1}; + this.objectId = mongoObjectFinal._id == null ? new ObjectID() : mongoObjectFinal._id; + this.chunkNumber = mongoObjectFinal.n == null ? 0 : mongoObjectFinal.n; + this.data = new Binary(); + + if(mongoObjectFinal.data == null) { + } else if(typeof mongoObjectFinal.data == "string") { + var buffer = new Buffer(mongoObjectFinal.data.length); + buffer.write(mongoObjectFinal.data, 'binary', 0); + this.data = new Binary(buffer); + } else if(Array.isArray(mongoObjectFinal.data)) { + var buffer = new Buffer(mongoObjectFinal.data.length); + buffer.write(mongoObjectFinal.data.join(''), 'binary', 0); + this.data = new Binary(buffer); + } else if(mongoObjectFinal.data instanceof Binary || mongoObjectFinal.data._bsontype === 'Binary' || Object.prototype.toString.call(mongoObjectFinal.data) == "[object Binary]") { + this.data = mongoObjectFinal.data; + } else if(Buffer.isBuffer(mongoObjectFinal.data)) { + } else { + throw Error("Illegal chunk format"); + } + + // Update position + this.internalPosition = 0; +}; + +/** + * Writes a data to this object and advance the read/write head. + * + * @param data {string} the data to write + * @param callback {function(*, GridStore)} This will be called after executing + * this method. The first parameter will contain null and the second one + * will contain a reference to this object. + */ +Chunk.prototype.write = function(data, callback) { + this.data.write(data, this.internalPosition); + this.internalPosition = this.data.length(); + if(callback != null) return callback(null, this); + return this; +}; + +/** + * Reads data and advances the read/write head. + * + * @param length {number} The length of data to read. + * + * @return {string} The data read if the given length will not exceed the end of + * the chunk. Returns an empty String otherwise. + */ +Chunk.prototype.read = function(length) { + // Default to full read if no index defined + length = length == null || length == 0 ? this.length() : length; + + if(this.length() - this.internalPosition + 1 >= length) { + var data = this.data.read(this.internalPosition, length); + this.internalPosition = this.internalPosition + length; + return data; + } else { + return ''; + } +}; + +Chunk.prototype.readSlice = function(length) { + if ((this.length() - this.internalPosition) >= length) { + var data = null; + if (this.data.buffer != null) { //Pure BSON + data = this.data.buffer.slice(this.internalPosition, this.internalPosition + length); + } else { //Native BSON + data = new Buffer(length); + length = this.data.readInto(data, this.internalPosition); + } + this.internalPosition = this.internalPosition + length; + return data; + } else { + return null; + } +}; + +/** + * Checks if the read/write head is at the end. + * + * @return {boolean} Whether the read/write head has reached the end of this + * chunk. + */ +Chunk.prototype.eof = function() { + return this.internalPosition == this.length() ? true : false; +}; + +/** + * Reads one character from the data of this chunk and advances the read/write + * head. + * + * @return {string} a single character data read if the the read/write head is + * not at the end of the chunk. Returns an empty String otherwise. + */ +Chunk.prototype.getc = function() { + return this.read(1); +}; + +/** + * Clears the contents of the data in this chunk and resets the read/write head + * to the initial position. + */ +Chunk.prototype.rewind = function() { + this.internalPosition = 0; + this.data = new Binary(); +}; + +/** + * Saves this chunk to the database. Also overwrites existing entries having the + * same id as this chunk. + * + * @param callback {function(*, GridStore)} This will be called after executing + * this method. The first parameter will contain null and the second one + * will contain a reference to this object. + */ +Chunk.prototype.save = function(options, callback) { + var self = this; + if(typeof options == 'function') { + callback = options; + options = {}; + } + + self.file.chunkCollection(function(err, collection) { + if(err) return callback(err); + + // Merge the options + var writeOptions = {}; + for(var name in options) writeOptions[name] = options[name]; + for(var name in self.writeConcern) writeOptions[name] = self.writeConcern[name]; + + // collection.remove({'_id':self.objectId}, self.writeConcern, function(err, result) { + collection.remove({'_id':self.objectId}, writeOptions, function(err, result) { + if(err) return callback(err); + + if(self.data.length() > 0) { + self.buildMongoObject(function(mongoObject) { + var options = {forceServerObjectId:true}; + for(var name in self.writeConcern) { + options[name] = self.writeConcern[name]; + } + + collection.insert(mongoObject, writeOptions, function(err, collection) { + callback(err, self); + }); + }); + } else { + callback(null, self); + } + }); + }); +}; + +/** + * Creates a mongoDB object representation of this chunk. + * + * @param callback {function(Object)} This will be called after executing this + * method. The object will be passed to the first parameter and will have + * the structure: + * + *

+ *        {
+ *          '_id' : , // {number} id for this chunk
+ *          'files_id' : , // {number} foreign key to the file collection
+ *          'n' : , // {number} chunk number
+ *          'data' : , // {bson#Binary} the chunk data itself
+ *        }
+ *        
+ * + * @see MongoDB GridFS Chunk Object Structure + */ +Chunk.prototype.buildMongoObject = function(callback) { + var mongoObject = { + 'files_id': this.file.fileId, + 'n': this.chunkNumber, + 'data': this.data}; + // If we are saving using a specific ObjectId + if(this.objectId != null) mongoObject._id = this.objectId; + + callback(mongoObject); +}; + +/** + * @return {number} the length of the data + */ +Chunk.prototype.length = function() { + return this.data.length(); +}; + +/** + * The position of the read/write head + * @name position + * @lends Chunk# + * @field + */ +Object.defineProperty(Chunk.prototype, "position", { enumerable: true + , get: function () { + return this.internalPosition; + } + , set: function(value) { + this.internalPosition = value; + } +}); + +/** + * The default chunk size + * @constant + */ +Chunk.DEFAULT_CHUNK_SIZE = 1024 * 255; diff --git a/node_modules/mongodb/lib/mongodb/gridfs/grid.js b/node_modules/mongodb/lib/mongodb/gridfs/grid.js new file mode 100644 index 0000000..00db0ef --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/gridfs/grid.js @@ -0,0 +1,104 @@ +var GridStore = require('./gridstore').GridStore, + ObjectID = require('bson').ObjectID; + +/** + * A class representation of a simple Grid interface. + * + * @class Represents the Grid. + * @param {Db} db A database instance to interact with. + * @param {String} [fsName] optional different root collection for GridFS. + * @return {Grid} + */ +function Grid(db, fsName) { + + if(!(this instanceof Grid)) return new Grid(db, fsName); + + this.db = db; + this.fsName = fsName == null ? GridStore.DEFAULT_ROOT_COLLECTION : fsName; +} + +/** + * Puts binary data to the grid + * + * Options + * - **_id** {Any}, unique id for this file + * - **filename** {String}, name for this file. + * - **root** {String}, root collection to use. Defaults to **{GridStore.DEFAULT_ROOT_COLLECTION}**. + * - **content_type** {String}, mime type of the file. Defaults to **{GridStore.DEFAULT_CONTENT_TYPE}**. + * - **chunk_size** {Number}, size for the chunk. Defaults to **{Chunk.DEFAULT_CHUNK_SIZE}**. + * - **metadata** {Object}, arbitrary data the user wants to store. + * + * @param {Buffer} data buffer with Binary Data. + * @param {Object} [options] the options for the files. + * @param {Function} callback this will be called after this method is executed. The first parameter will contain an Error object if an error occured or null otherwise. The second parameter will contain a reference to this object. + * @return {null} + * @api public + */ +Grid.prototype.put = function(data, options, callback) { + var self = this; + var args = Array.prototype.slice.call(arguments, 1); + callback = args.pop(); + options = args.length ? args.shift() : {}; + // If root is not defined add our default one + options['root'] = options['root'] == null ? this.fsName : options['root']; + + // Return if we don't have a buffer object as data + if(!(Buffer.isBuffer(data))) return callback(new Error("Data object must be a buffer object"), null); + // Get filename if we are using it + var filename = options['filename'] || null; + // Get id if we are using it + var id = options['_id'] || null; + // Create gridstore + var gridStore = new GridStore(this.db, id, filename, "w", options); + gridStore.open(function(err, gridStore) { + if(err) return callback(err, null); + + gridStore.write(data, function(err, result) { + if(err) return callback(err, null); + + gridStore.close(function(err, result) { + if(err) return callback(err, null); + callback(null, result); + }) + }) + }) +} + +/** + * Get binary data to the grid + * + * @param {Any} id for file. + * @param {Function} callback this will be called after this method is executed. The first parameter will contain an Error object if an error occured or null otherwise. The second parameter will contain a reference to this object. + * @return {null} + * @api public + */ +Grid.prototype.get = function(id, callback) { + // Create gridstore + var gridStore = new GridStore(this.db, id, null, "r", {root:this.fsName}); + gridStore.open(function(err, gridStore) { + if(err) return callback(err, null); + + // Return the data + gridStore.read(function(err, data) { + return callback(err, data) + }); + }) +} + +/** + * Delete file from grid + * + * @param {Any} id for file. + * @param {Function} callback this will be called after this method is executed. The first parameter will contain an Error object if an error occured or null otherwise. The second parameter will contain a reference to this object. + * @return {null} + * @api public + */ +Grid.prototype.delete = function(id, callback) { + // Create gridstore + GridStore.unlink(this.db, id, {root:this.fsName}, function(err, result) { + if(err) return callback(err, false); + return callback(null, true); + }); +} + +exports.Grid = Grid; diff --git a/node_modules/mongodb/lib/mongodb/gridfs/gridstore.js b/node_modules/mongodb/lib/mongodb/gridfs/gridstore.js new file mode 100644 index 0000000..c6b9894 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/gridfs/gridstore.js @@ -0,0 +1,1570 @@ +/** + * @fileOverview GridFS is a tool for MongoDB to store files to the database. + * Because of the restrictions of the object size the database can hold, a + * facility to split a file into several chunks is needed. The {@link GridStore} + * class offers a simplified api to interact with files while managing the + * chunks of split files behind the scenes. More information about GridFS can be + * found here. + */ +var Chunk = require('./chunk').Chunk, + DbCommand = require('../commands/db_command').DbCommand, + ObjectID = require('bson').ObjectID, + Buffer = require('buffer').Buffer, + fs = require('fs'), + timers = require('timers'), + util = require('util'), + inherits = util.inherits, + ReadStream = require('./readstream').ReadStream, + Stream = require('stream'); + +// Set processor, setImmediate if 0.10 otherwise nextTick +var processor = require('../utils').processor(); + +var REFERENCE_BY_FILENAME = 0, + REFERENCE_BY_ID = 1; + +/** + * A class representation of a file stored in GridFS. + * + * Modes + * - **"r"** - read only. This is the default mode. + * - **"w"** - write in truncate mode. Existing data will be overwriten. + * - **w+"** - write in edit mode (append is not guaranteed for concurrent operations) + * + * Options + * - **root** {String}, root collection to use. Defaults to **{GridStore.DEFAULT_ROOT_COLLECTION}**. + * - **content_type** {String}, mime type of the file. Defaults to **{GridStore.DEFAULT_CONTENT_TYPE}**. + * - **chunk_size** {Number}, size for the chunk. Defaults to **{Chunk.DEFAULT_CHUNK_SIZE}**. + * - **metadata** {Object}, arbitrary data the user wants to store. + * - **readPreference** {String}, the prefered read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). + * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal + * - **j**, (Boolean, default:false) write waits for journal sync before returning + * + * @class Represents the GridStore. + * @param {Db} db A database instance to interact with. + * @param {Any} [id] optional unique id for this file + * @param {String} [filename] optional filename for this file, no unique constrain on the field + * @param {String} mode set the mode for this file. + * @param {Object} options optional properties to specify. + * @return {GridStore} + */ +var GridStore = function GridStore(db, id, filename, mode, options) { + if(!(this instanceof GridStore)) return new GridStore(db, id, filename, mode, options); + + var self = this; + this.db = db; + + // Call stream constructor + if(typeof Stream == 'function') { + Stream.call(this); + } + + // Handle options + if(typeof options === 'undefined') options = {}; + // Handle mode + if(typeof mode === 'undefined') { + mode = filename; + filename = undefined; + } else if(typeof mode == 'object') { + options = mode; + mode = filename; + filename = undefined; + } + + if(id instanceof ObjectID) { + this.referenceBy = REFERENCE_BY_ID; + this.fileId = id; + this.filename = filename; + } else if(typeof filename == 'undefined') { + this.referenceBy = REFERENCE_BY_FILENAME; + this.filename = id; + if (mode.indexOf('w') != null) { + this.fileId = new ObjectID(); + } + } else { + this.referenceBy = REFERENCE_BY_ID; + this.fileId = id; + this.filename = filename; + } + + // Set up the rest + this.mode = mode == null ? "r" : mode; + this.options = options || {}; + + // Set the root if overridden + this.root = this.options['root'] == null ? exports.GridStore.DEFAULT_ROOT_COLLECTION : this.options['root']; + this.position = 0; + this.readPreference = this.options.readPreference || 'primary'; + this.writeConcern = _getWriteConcern(db, this.options); + + // Set default chunk size + this.internalChunkSize = this.options['chunkSize'] == null ? Chunk.DEFAULT_CHUNK_SIZE : this.options['chunkSize']; +} + +/** + * Code for the streaming capabilities of the gridstore object + * Most code from Aaron heckmanns project https://github.com/aheckmann/gridfs-stream + * Modified to work on the gridstore object itself + * @ignore + */ +if(typeof Stream == 'function') { + GridStore.prototype = { __proto__: Stream.prototype } +} else { + // Node 0.4.X compatibility code + GridStore.prototype = { __proto__: Stream.Stream.prototype } +} + +// Move pipe to _pipe +GridStore.prototype._pipe = GridStore.prototype.pipe; + +/** + * Opens the file from the database and initialize this object. Also creates a + * new one if file does not exist. + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain an **{Error}** object and the second parameter will be null if an error occured. Otherwise, the first parameter will be null and the second will contain the reference to this object. + * @return {null} + * @api public + */ +GridStore.prototype.open = function(callback) { + if( this.mode != "w" && this.mode != "w+" && this.mode != "r"){ + callback(new Error("Illegal mode " + this.mode), null); + return; + } + + var self = this; + + // Get the write concern + var writeConcern = _getWriteConcern(this.db, this.options); + + // If we are writing we need to ensure we have the right indexes for md5's + if((self.mode == "w" || self.mode == "w+")) { + // Get files collection + var collection = self.collection(); + // Put index on filename + collection.ensureIndex([['filename', 1]], writeConcern, function(err, index) { + // if(err) return callback(err); + + // Get chunk collection + var chunkCollection = self.chunkCollection(); + // Ensure index on chunk collection + chunkCollection.ensureIndex([['files_id', 1], ['n', 1]], writeConcern, function(err, index) { + // if(err) return callback(err); + _open(self, writeConcern, callback); + }); + }); + } else { + // Open the gridstore + _open(self, writeConcern, callback); + } +}; + +/** + * Hidding the _open function + * @ignore + * @api private + */ +var _open = function(self, options, callback) { + var collection = self.collection(); + // Create the query + var query = self.referenceBy == REFERENCE_BY_ID ? {_id:self.fileId} : {filename:self.filename}; + query = null == self.fileId && self.filename == null ? null : query; + options.readPreference = self.readPreference; + + // Fetch the chunks + if(query != null) { + collection.findOne(query, options, function(err, doc) { + if(err) return error(err); + + // Check if the collection for the files exists otherwise prepare the new one + if(doc != null) { + self.fileId = doc._id; + // Prefer a new filename over the existing one if this is a write + self.filename = ((self.mode == 'r') || (self.filename == undefined)) ? doc.filename : self.filename; + self.contentType = doc.contentType; + self.internalChunkSize = doc.chunkSize; + self.uploadDate = doc.uploadDate; + self.aliases = doc.aliases; + self.length = doc.length; + self.metadata = doc.metadata; + self.internalMd5 = doc.md5; + } else if (self.mode != 'r') { + self.fileId = self.fileId == null ? new ObjectID() : self.fileId; + self.contentType = exports.GridStore.DEFAULT_CONTENT_TYPE; + self.internalChunkSize = self.internalChunkSize == null ? Chunk.DEFAULT_CHUNK_SIZE : self.internalChunkSize; + self.length = 0; + } else { + self.length = 0; + var txtId = self.fileId instanceof ObjectID ? self.fileId.toHexString() : self.fileId; + return error(new Error((self.referenceBy == REFERENCE_BY_ID ? txtId : self.filename) + " does not exist", self)); + } + + // Process the mode of the object + if(self.mode == "r") { + nthChunk(self, 0, options, function(err, chunk) { + if(err) return error(err); + self.currentChunk = chunk; + self.position = 0; + callback(null, self); + }); + } else if(self.mode == "w") { + // Delete any existing chunks + deleteChunks(self, options, function(err, result) { + if(err) return error(err); + self.currentChunk = new Chunk(self, {'n':0}, self.writeConcern); + self.contentType = self.options['content_type'] == null ? self.contentType : self.options['content_type']; + self.internalChunkSize = self.options['chunk_size'] == null ? self.internalChunkSize : self.options['chunk_size']; + self.metadata = self.options['metadata'] == null ? self.metadata : self.options['metadata']; + self.aliases = self.options['aliases'] == null ? self.aliases : self.options['aliases']; + self.position = 0; + callback(null, self); + }); + } else if(self.mode == "w+") { + nthChunk(self, lastChunkNumber(self), options, function(err, chunk) { + if(err) return error(err); + // Set the current chunk + self.currentChunk = chunk == null ? new Chunk(self, {'n':0}, self.writeConcern) : chunk; + self.currentChunk.position = self.currentChunk.data.length(); + self.metadata = self.options['metadata'] == null ? self.metadata : self.options['metadata']; + self.aliases = self.options['aliases'] == null ? self.aliases : self.options['aliases']; + self.position = self.length; + callback(null, self); + }); + } + }); + } else { + // Write only mode + self.fileId = null == self.fileId ? new ObjectID() : self.fileId; + self.contentType = exports.GridStore.DEFAULT_CONTENT_TYPE; + self.internalChunkSize = self.internalChunkSize == null ? Chunk.DEFAULT_CHUNK_SIZE : self.internalChunkSize; + self.length = 0; + + var collection2 = self.chunkCollection(); + // No file exists set up write mode + if(self.mode == "w") { + // Delete any existing chunks + deleteChunks(self, options, function(err, result) { + if(err) return error(err); + self.currentChunk = new Chunk(self, {'n':0}, self.writeConcern); + self.contentType = self.options['content_type'] == null ? self.contentType : self.options['content_type']; + self.internalChunkSize = self.options['chunk_size'] == null ? self.internalChunkSize : self.options['chunk_size']; + self.metadata = self.options['metadata'] == null ? self.metadata : self.options['metadata']; + self.aliases = self.options['aliases'] == null ? self.aliases : self.options['aliases']; + self.position = 0; + callback(null, self); + }); + } else if(self.mode == "w+") { + nthChunk(self, lastChunkNumber(self), options, function(err, chunk) { + if(err) return error(err); + // Set the current chunk + self.currentChunk = chunk == null ? new Chunk(self, {'n':0}, self.writeConcern) : chunk; + self.currentChunk.position = self.currentChunk.data.length(); + self.metadata = self.options['metadata'] == null ? self.metadata : self.options['metadata']; + self.aliases = self.options['aliases'] == null ? self.aliases : self.options['aliases']; + self.position = self.length; + callback(null, self); + }); + } + } + + // only pass error to callback once + function error (err) { + if(error.err) return; + callback(error.err = err); + } +}; + +/** + * Stores a file from the file system to the GridFS database. + * + * @param {String|Buffer|FileHandle} file the file to store. + * @param {Function} callback this will be called after this method is executed. The first parameter will be null and the the second will contain the reference to this object. + * @return {null} + * @api public + */ +GridStore.prototype.writeFile = function (file, callback) { + var self = this; + if (typeof file === 'string') { + fs.open(file, 'r', function (err, fd) { + if(err) return callback(err); + self.writeFile(fd, callback); + }); + return; + } + + self.open(function (err, self) { + if(err) return callback(err, self); + + fs.fstat(file, function (err, stats) { + if(err) return callback(err, self); + + var offset = 0; + var index = 0; + var numberOfChunksLeft = Math.min(stats.size / self.chunkSize); + + // Write a chunk + var writeChunk = function() { + fs.read(file, self.chunkSize, offset, 'binary', function(err, data, bytesRead) { + if(err) return callback(err, self); + + offset = offset + bytesRead; + + // Create a new chunk for the data + var chunk = new Chunk(self, {n:index++}, self.writeConcern); + chunk.write(data, function(err, chunk) { + if(err) return callback(err, self); + + chunk.save({}, function(err, result) { + if(err) return callback(err, self); + + self.position = self.position + data.length; + + // Point to current chunk + self.currentChunk = chunk; + + if(offset >= stats.size) { + fs.close(file); + self.close(function(err, result) { + if(err) return callback(err, self); + return callback(null, self); + }); + } else { + return processor(writeChunk); + } + }); + }); + }); + } + + // Process the first write + processor(writeChunk); + }); + }); +}; + +/** + * Writes some data. This method will work properly only if initialized with mode + * "w" or "w+". + * + * @param string {string} The data to write. + * @param close {boolean=false} opt_argument Closes this file after writing if + * true. + * @param callback {function(*, GridStore)} This will be called after executing + * this method. The first parameter will contain null and the second one + * will contain a reference to this object. + * + * @ignore + * @api private + */ +var writeBuffer = function(self, buffer, close, callback) { + if(typeof close === "function") { callback = close; close = null; } + var finalClose = typeof close == 'boolean' ? close : false; + + if(self.mode[0] != "w") { + callback(new Error((self.referenceBy == REFERENCE_BY_ID ? self.toHexString() : self.filename) + " not opened for writing"), null); + } else { + if(self.currentChunk.position + buffer.length >= self.chunkSize) { + // Write out the current Chunk and then keep writing until we have less data left than a chunkSize left + // to a new chunk (recursively) + var previousChunkNumber = self.currentChunk.chunkNumber; + var leftOverDataSize = self.chunkSize - self.currentChunk.position; + var firstChunkData = buffer.slice(0, leftOverDataSize); + var leftOverData = buffer.slice(leftOverDataSize); + // A list of chunks to write out + var chunksToWrite = [self.currentChunk.write(firstChunkData)]; + // If we have more data left than the chunk size let's keep writing new chunks + while(leftOverData.length >= self.chunkSize) { + // Create a new chunk and write to it + var newChunk = new Chunk(self, {'n': (previousChunkNumber + 1)}, self.writeConcern); + var firstChunkData = leftOverData.slice(0, self.chunkSize); + leftOverData = leftOverData.slice(self.chunkSize); + // Update chunk number + previousChunkNumber = previousChunkNumber + 1; + // Write data + newChunk.write(firstChunkData); + // Push chunk to save list + chunksToWrite.push(newChunk); + } + + // Set current chunk with remaining data + self.currentChunk = new Chunk(self, {'n': (previousChunkNumber + 1)}, self.writeConcern); + // If we have left over data write it + if(leftOverData.length > 0) self.currentChunk.write(leftOverData); + + // Update the position for the gridstore + self.position = self.position + buffer.length; + // Total number of chunks to write + var numberOfChunksToWrite = chunksToWrite.length; + + for(var i = 0; i < chunksToWrite.length; i++) { + chunksToWrite[i].save({}, function(err, result) { + if(err) return callback(err); + + numberOfChunksToWrite = numberOfChunksToWrite - 1; + + if(numberOfChunksToWrite <= 0) { + // We care closing the file before returning + if(finalClose) { + return self.close(function(err, result) { + callback(err, self); + }); + } + + // Return normally + return callback(null, self); + } + }); + } + } else { + // Update the position for the gridstore + self.position = self.position + buffer.length; + // We have less data than the chunk size just write it and callback + self.currentChunk.write(buffer); + // We care closing the file before returning + if(finalClose) { + return self.close(function(err, result) { + callback(err, self); + }); + } + // Return normally + return callback(null, self); + } + } +}; + +/** + * Creates a mongoDB object representation of this object. + * + * @param callback {function(object)} This will be called after executing this + * method. The object will be passed to the first parameter and will have + * the structure: + * + *

+ *        {
+ *          '_id' : , // {number} id for this file
+ *          'filename' : , // {string} name for this file
+ *          'contentType' : , // {string} mime type for this file
+ *          'length' : , // {number} size of this file?
+ *          'chunksize' : , // {number} chunk size used by this file
+ *          'uploadDate' : , // {Date}
+ *          'aliases' : , // {array of string}
+ *          'metadata' : , // {string}
+ *        }
+ *        
+ * + * @ignore + * @api private + */ +var buildMongoObject = function(self, callback) { + // Calcuate the length + var mongoObject = { + '_id': self.fileId, + 'filename': self.filename, + 'contentType': self.contentType, + 'length': self.position ? self.position : 0, + 'chunkSize': self.chunkSize, + 'uploadDate': self.uploadDate, + 'aliases': self.aliases, + 'metadata': self.metadata + }; + + var md5Command = {filemd5:self.fileId, root:self.root}; + self.db.command(md5Command, function(err, results) { + if(err) return callback(err); + + mongoObject.md5 = results.md5; + callback(null, mongoObject); + }); +}; + +/** + * Saves this file to the database. This will overwrite the old entry if it + * already exists. This will work properly only if mode was initialized to + * "w" or "w+". + * + * @param {Function} callback this will be called after executing this method. Passes an **{Error}** object to the first parameter and null to the second if an error occured. Otherwise, passes null to the first and a reference to this object to the second. + * @return {null} + * @api public + */ +GridStore.prototype.close = function(callback) { + var self = this; + + if(self.mode[0] == "w") { + // Set up options + var options = self.writeConcern; + + if(self.currentChunk != null && self.currentChunk.position > 0) { + self.currentChunk.save({}, function(err, chunk) { + if(err && typeof callback == 'function') return callback(err); + + self.collection(function(err, files) { + if(err && typeof callback == 'function') return callback(err); + + // Build the mongo object + if(self.uploadDate != null) { + files.remove({'_id':self.fileId}, self.writeConcern, function(err, collection) { + if(err && typeof callback == 'function') return callback(err); + + buildMongoObject(self, function(err, mongoObject) { + if(err) { + if(typeof callback == 'function') return callback(err); else throw err; + } + + files.save(mongoObject, options, function(err) { + if(typeof callback == 'function') + callback(err, mongoObject); + }); + }); + }); + } else { + self.uploadDate = new Date(); + buildMongoObject(self, function(err, mongoObject) { + if(err) { + if(typeof callback == 'function') return callback(err); else throw err; + } + + files.save(mongoObject, options, function(err) { + if(typeof callback == 'function') + callback(err, mongoObject); + }); + }); + } + }); + }); + } else { + self.collection(function(err, files) { + if(err && typeof callback == 'function') return callback(err); + + self.uploadDate = new Date(); + buildMongoObject(self, function(err, mongoObject) { + if(err) { + if(typeof callback == 'function') return callback(err); else throw err; + } + + files.save(mongoObject, options, function(err) { + if(typeof callback == 'function') + callback(err, mongoObject); + }); + }); + }); + } + } else if(self.mode[0] == "r") { + if(typeof callback == 'function') + callback(null, null); + } else { + if(typeof callback == 'function') + callback(new Error("Illegal mode " + self.mode), null); + } +}; + +/** + * Gets the nth chunk of this file. + * + * @param chunkNumber {number} The nth chunk to retrieve. + * @param callback {function(*, Chunk|object)} This will be called after + * executing this method. null will be passed to the first parameter while + * a new {@link Chunk} instance will be passed to the second parameter if + * the chunk was found or an empty object {} if not. + * + * @ignore + * @api private + */ +var nthChunk = function(self, chunkNumber, options, callback) { + if(typeof options == 'function') { + callback = options; + options = {}; + } + + options = options || self.writeConcern; + options.readPreference = self.readPreference; + // Get the nth chunk + self.chunkCollection().findOne({'files_id':self.fileId, 'n':chunkNumber}, options, function(err, chunk) { + if(err) return callback(err); + + var finalChunk = chunk == null ? {} : chunk; + callback(null, new Chunk(self, finalChunk, self.writeConcern)); + }); +}; + +/** + * + * @ignore + * @api private + */ +GridStore.prototype._nthChunk = function(chunkNumber, callback) { + nthChunk(this, chunkNumber, callback); +} + +/** + * @return {Number} The last chunk number of this file. + * + * @ignore + * @api private + */ +var lastChunkNumber = function(self) { + return Math.floor((self.length ? self.length - 1 : 0)/self.chunkSize); +}; + +/** + * Retrieve this file's chunks collection. + * + * @param {Function} callback this will be called after executing this method. An exception object will be passed to the first parameter when an error occured or null otherwise. A new **{Collection}** object will be passed to the second parameter if no error occured. + * @return {null} + * @api public + */ +GridStore.prototype.chunkCollection = function(callback) { + if(typeof callback == 'function') + return this.db.collection((this.root + ".chunks"), callback); + return this.db.collection((this.root + ".chunks")); +}; + +/** + * Deletes all the chunks of this file in the database. + * + * @param callback {function(*, boolean)} This will be called after this method + * executes. Passes null to the first and true to the second argument. + * + * @ignore + * @api private + */ +var deleteChunks = function(self, options, callback) { + if(typeof options == 'function') { + callback = options; + options = {}; + } + + options = options || self.writeConcern; + + if(self.fileId != null) { + self.chunkCollection().remove({'files_id':self.fileId}, options, function(err, result) { + if(err) return callback(err, false); + callback(null, true); + }); + } else { + callback(null, true); + } +}; + +/** + * Deletes all the chunks of this file in the database. + * + * @param {Function} callback this will be called after this method executes. Passes null to the first and true to the second argument. + * @return {null} + * @api public + */ +GridStore.prototype.unlink = function(callback) { + var self = this; + deleteChunks(this, function(err) { + if(err!==null) { + err.message = "at deleteChunks: " + err.message; + return callback(err); + } + + self.collection(function(err, collection) { + if(err!==null) { + err.message = "at collection: " + err.message; + return callback(err); + } + + collection.remove({'_id':self.fileId}, self.writeConcern, function(err) { + callback(err, self); + }); + }); + }); +}; + +/** + * Retrieves the file collection associated with this object. + * + * @param {Function} callback this will be called after executing this method. An exception object will be passed to the first parameter when an error occured or null otherwise. A new **{Collection}** object will be passed to the second parameter if no error occured. + * @return {null} + * @api public + */ +GridStore.prototype.collection = function(callback) { + if(typeof callback == 'function') + this.db.collection(this.root + ".files", callback); + return this.db.collection(this.root + ".files"); +}; + +/** + * Reads the data of this file. + * + * @param {String} [separator] the character to be recognized as the newline separator. + * @param {Function} callback This will be called after this method is executed. The first parameter will be null and the second parameter will contain an array of strings representing the entire data, each element representing a line including the separator character. + * @return {null} + * @api public + */ +GridStore.prototype.readlines = function(separator, callback) { + var args = Array.prototype.slice.call(arguments, 0); + callback = args.pop(); + separator = args.length ? args.shift() : "\n"; + + this.read(function(err, data) { + if(err) return callback(err); + + var items = data.toString().split(separator); + items = items.length > 0 ? items.splice(0, items.length - 1) : []; + for(var i = 0; i < items.length; i++) { + items[i] = items[i] + separator; + } + + callback(null, items); + }); +}; + +/** + * Deletes all the chunks of this file in the database if mode was set to "w" or + * "w+" and resets the read/write head to the initial position. + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain null and the second one will contain a reference to this object. + * @return {null} + * @api public + */ +GridStore.prototype.rewind = function(callback) { + var self = this; + + if(this.currentChunk.chunkNumber != 0) { + if(this.mode[0] == "w") { + deleteChunks(self, function(err, gridStore) { + if(err) return callback(err); + self.currentChunk = new Chunk(self, {'n': 0}, self.writeConcern); + self.position = 0; + callback(null, self); + }); + } else { + self.currentChunk(0, function(err, chunk) { + if(err) return callback(err); + self.currentChunk = chunk; + self.currentChunk.rewind(); + self.position = 0; + callback(null, self); + }); + } + } else { + self.currentChunk.rewind(); + self.position = 0; + callback(null, self); + } +}; + +/** + * Retrieves the contents of this file and advances the read/write head. Works with Buffers only. + * + * There are 3 signatures for this method: + * + * (callback) + * (length, callback) + * (length, buffer, callback) + * + * @param {Number} [length] the number of characters to read. Reads all the characters from the read/write head to the EOF if not specified. + * @param {String|Buffer} [buffer] a string to hold temporary data. This is used for storing the string data read so far when recursively calling this method. + * @param {Function} callback this will be called after this method is executed. null will be passed to the first parameter and a string containing the contents of the buffer concatenated with the contents read from this file will be passed to the second. + * @return {null} + * @api public + */ +GridStore.prototype.read = function(length, buffer, callback) { + var self = this; + + var args = Array.prototype.slice.call(arguments, 0); + callback = args.pop(); + length = args.length ? args.shift() : null; + buffer = args.length ? args.shift() : null; + + // The data is a c-terminated string and thus the length - 1 + var finalLength = length == null ? self.length - self.position : length; + var finalBuffer = buffer == null ? new Buffer(finalLength) : buffer; + // Add a index to buffer to keep track of writing position or apply current index + finalBuffer._index = buffer != null && buffer._index != null ? buffer._index : 0; + + if((self.currentChunk.length() - self.currentChunk.position + finalBuffer._index) >= finalLength) { + var slice = self.currentChunk.readSlice(finalLength - finalBuffer._index); + // Copy content to final buffer + slice.copy(finalBuffer, finalBuffer._index); + // Update internal position + self.position = self.position + finalBuffer.length; + // Check if we don't have a file at all + if(finalLength == 0 && finalBuffer.length == 0) return callback(new Error("File does not exist"), null); + // Else return data + callback(null, finalBuffer); + } else { + var slice = self.currentChunk.readSlice(self.currentChunk.length() - self.currentChunk.position); + // Copy content to final buffer + slice.copy(finalBuffer, finalBuffer._index); + // Update index position + finalBuffer._index += slice.length; + + // Load next chunk and read more + nthChunk(self, self.currentChunk.chunkNumber + 1, function(err, chunk) { + if(err) return callback(err); + + if(chunk.length() > 0) { + self.currentChunk = chunk; + self.read(length, finalBuffer, callback); + } else { + if (finalBuffer._index > 0) { + callback(null, finalBuffer) + } else { + callback(new Error("no chunks found for file, possibly corrupt"), null); + } + } + }); + } +} + +/** + * Retrieves the position of the read/write head of this file. + * + * @param {Function} callback This gets called after this method terminates. null is passed to the first parameter and the position is passed to the second. + * @return {null} + * @api public + */ +GridStore.prototype.tell = function(callback) { + callback(null, this.position); +}; + +/** + * Moves the read/write head to a new location. + * + * There are 3 signatures for this method + * + * Seek Location Modes + * - **GridStore.IO_SEEK_SET**, **(default)** set the position from the start of the file. + * - **GridStore.IO_SEEK_CUR**, set the position from the current position in the file. + * - **GridStore.IO_SEEK_END**, set the position from the end of the file. + * + * @param {Number} [position] the position to seek to + * @param {Number} [seekLocation] seek mode. Use one of the Seek Location modes. + * @param {Function} callback this will be called after executing this method. The first parameter will contain null and the second one will contain a reference to this object. + * @return {null} + * @api public + */ +GridStore.prototype.seek = function(position, seekLocation, callback) { + var self = this; + + var args = Array.prototype.slice.call(arguments, 1); + callback = args.pop(); + seekLocation = args.length ? args.shift() : null; + + var seekLocationFinal = seekLocation == null ? exports.GridStore.IO_SEEK_SET : seekLocation; + var finalPosition = position; + var targetPosition = 0; + + // Calculate the position + if(seekLocationFinal == exports.GridStore.IO_SEEK_CUR) { + targetPosition = self.position + finalPosition; + } else if(seekLocationFinal == exports.GridStore.IO_SEEK_END) { + targetPosition = self.length + finalPosition; + } else { + targetPosition = finalPosition; + } + + // Get the chunk + var newChunkNumber = Math.floor(targetPosition/self.chunkSize); + if(newChunkNumber != self.currentChunk.chunkNumber) { + var seekChunk = function() { + nthChunk(self, newChunkNumber, function(err, chunk) { + self.currentChunk = chunk; + self.position = targetPosition; + self.currentChunk.position = (self.position % self.chunkSize); + callback(err, self); + }); + }; + + if(self.mode[0] == 'w') { + self.currentChunk.save({}, function(err) { + if(err) return callback(err); + seekChunk(); + }); + } else { + seekChunk(); + } + } else { + self.position = targetPosition; + self.currentChunk.position = (self.position % self.chunkSize); + callback(null, self); + } +}; + +/** + * Verify if the file is at EOF. + * + * @return {Boolean} true if the read/write head is at the end of this file. + * @api public + */ +GridStore.prototype.eof = function() { + return this.position == this.length ? true : false; +}; + +/** + * Retrieves a single character from this file. + * + * @param {Function} callback this gets called after this method is executed. Passes null to the first parameter and the character read to the second or null to the second if the read/write head is at the end of the file. + * @return {null} + * @api public + */ +GridStore.prototype.getc = function(callback) { + var self = this; + + if(self.eof()) { + callback(null, null); + } else if(self.currentChunk.eof()) { + nthChunk(self, self.currentChunk.chunkNumber + 1, function(err, chunk) { + self.currentChunk = chunk; + self.position = self.position + 1; + callback(err, self.currentChunk.getc()); + }); + } else { + self.position = self.position + 1; + callback(null, self.currentChunk.getc()); + } +}; + +/** + * Writes a string to the file with a newline character appended at the end if + * the given string does not have one. + * + * @param {String} string the string to write. + * @param {Function} callback this will be called after executing this method. The first parameter will contain null and the second one will contain a reference to this object. + * @return {null} + * @api public + */ +GridStore.prototype.puts = function(string, callback) { + var finalString = string.match(/\n$/) == null ? string + "\n" : string; + this.write(finalString, callback); +}; + +/** + * Returns read stream based on this GridStore file + * + * Events + * - **data** {function(item) {}} the data event triggers when a document is ready. + * - **end** {function() {}} the end event triggers when there is no more documents available. + * - **close** {function() {}} the close event triggers when the stream is closed. + * - **error** {function(err) {}} the error event triggers if an error happens. + * + * @param {Boolean} autoclose if true current GridStore will be closed when EOF and 'close' event will be fired + * @return {null} + * @api public + */ +GridStore.prototype.stream = function(autoclose) { + return new ReadStream(autoclose, this); +}; + +/** +* The collection to be used for holding the files and chunks collection. +* +* @classconstant DEFAULT_ROOT_COLLECTION +**/ +GridStore.DEFAULT_ROOT_COLLECTION = 'fs'; + +/** +* Default file mime type +* +* @classconstant DEFAULT_CONTENT_TYPE +**/ +GridStore.DEFAULT_CONTENT_TYPE = 'binary/octet-stream'; + +/** +* Seek mode where the given length is absolute. +* +* @classconstant IO_SEEK_SET +**/ +GridStore.IO_SEEK_SET = 0; + +/** +* Seek mode where the given length is an offset to the current read/write head. +* +* @classconstant IO_SEEK_CUR +**/ +GridStore.IO_SEEK_CUR = 1; + +/** +* Seek mode where the given length is an offset to the end of the file. +* +* @classconstant IO_SEEK_END +**/ +GridStore.IO_SEEK_END = 2; + +/** + * Checks if a file exists in the database. + * + * Options + * - **readPreference** {String}, the prefered read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). + * + * @param {Db} db the database to query. + * @param {String} name the name of the file to look for. + * @param {String} [rootCollection] the root collection that holds the files and chunks collection. Defaults to **{GridStore.DEFAULT_ROOT_COLLECTION}**. + * @param {Function} callback this will be called after this method executes. Passes null to the first and passes true to the second if the file exists and false otherwise. + * @return {null} + * @api public + */ +GridStore.exist = function(db, fileIdObject, rootCollection, options, callback) { + var args = Array.prototype.slice.call(arguments, 2); + callback = args.pop(); + rootCollection = args.length ? args.shift() : null; + options = args.length ? args.shift() : {}; + + // Establish read preference + var readPreference = options.readPreference || 'primary'; + // Fetch collection + var rootCollectionFinal = rootCollection != null ? rootCollection : GridStore.DEFAULT_ROOT_COLLECTION; + db.collection(rootCollectionFinal + ".files", function(err, collection) { + if(err) return callback(err); + + // Build query + var query = (typeof fileIdObject == 'string' || Object.prototype.toString.call(fileIdObject) == '[object RegExp]' ) + ? {'filename':fileIdObject} + : {'_id':fileIdObject}; // Attempt to locate file + + collection.findOne(query, {readPreference:readPreference}, function(err, item) { + if(err) return callback(err); + + callback(null, item == null ? false : true); + }); + }); +}; + +/** + * Gets the list of files stored in the GridFS. + * + * @param {Db} db the database to query. + * @param {String} [rootCollection] the root collection that holds the files and chunks collection. Defaults to **{GridStore.DEFAULT_ROOT_COLLECTION}**. + * @param {Function} callback this will be called after this method executes. Passes null to the first and passes an array of strings containing the names of the files. + * @return {null} + * @api public + */ +GridStore.list = function(db, rootCollection, options, callback) { + var args = Array.prototype.slice.call(arguments, 1); + callback = args.pop(); + rootCollection = args.length ? args.shift() : null; + options = args.length ? args.shift() : {}; + + // Ensure we have correct values + if(rootCollection != null && typeof rootCollection == 'object') { + options = rootCollection; + rootCollection = null; + } + + // Establish read preference + var readPreference = options.readPreference || 'primary'; + // Check if we are returning by id not filename + var byId = options['id'] != null ? options['id'] : false; + // Fetch item + var rootCollectionFinal = rootCollection != null ? rootCollection : GridStore.DEFAULT_ROOT_COLLECTION; + var items = []; + db.collection((rootCollectionFinal + ".files"), function(err, collection) { + if(err) return callback(err); + + collection.find({}, {readPreference:readPreference}, function(err, cursor) { + if(err) return callback(err); + + cursor.each(function(err, item) { + if(item != null) { + items.push(byId ? item._id : item.filename); + } else { + callback(err, items); + } + }); + }); + }); +}; + +/** + * Reads the contents of a file. + * + * This method has the following signatures + * + * (db, name, callback) + * (db, name, length, callback) + * (db, name, length, offset, callback) + * (db, name, length, offset, options, callback) + * + * @param {Db} db the database to query. + * @param {String} name the name of the file. + * @param {Number} [length] the size of data to read. + * @param {Number} [offset] the offset from the head of the file of which to start reading from. + * @param {Object} [options] the options for the file. + * @param {Function} callback this will be called after this method executes. A string with an error message will be passed to the first parameter when the length and offset combination exceeds the length of the file while an Error object will be passed if other forms of error occured, otherwise, a string is passed. The second parameter will contain the data read if successful or null if an error occured. + * @return {null} + * @api public + */ +GridStore.read = function(db, name, length, offset, options, callback) { + var args = Array.prototype.slice.call(arguments, 2); + callback = args.pop(); + length = args.length ? args.shift() : null; + offset = args.length ? args.shift() : null; + options = args.length ? args.shift() : null; + + new GridStore(db, name, "r", options).open(function(err, gridStore) { + if(err) return callback(err); + // Make sure we are not reading out of bounds + if(offset && offset >= gridStore.length) return callback("offset larger than size of file", null); + if(length && length > gridStore.length) return callback("length is larger than the size of the file", null); + if(offset && length && (offset + length) > gridStore.length) return callback("offset and length is larger than the size of the file", null); + + if(offset != null) { + gridStore.seek(offset, function(err, gridStore) { + if(err) return callback(err); + gridStore.read(length, callback); + }); + } else { + gridStore.read(length, callback); + } + }); +}; + +/** + * Reads the data of this file. + * + * @param {Db} db the database to query. + * @param {String} name the name of the file. + * @param {String} [separator] the character to be recognized as the newline separator. + * @param {Object} [options] file options. + * @param {Function} callback this will be called after this method is executed. The first parameter will be null and the second parameter will contain an array of strings representing the entire data, each element representing a line including the separator character. + * @return {null} + * @api public + */ +GridStore.readlines = function(db, name, separator, options, callback) { + var args = Array.prototype.slice.call(arguments, 2); + callback = args.pop(); + separator = args.length ? args.shift() : null; + options = args.length ? args.shift() : null; + + var finalSeperator = separator == null ? "\n" : separator; + new GridStore(db, name, "r", options).open(function(err, gridStore) { + if(err) return callback(err); + gridStore.readlines(finalSeperator, callback); + }); +}; + +/** + * Deletes the chunks and metadata information of a file from GridFS. + * + * @param {Db} db the database to interact with. + * @param {String|Array} names the name/names of the files to delete. + * @param {Object} [options] the options for the files. + * @callback {Function} this will be called after this method is executed. The first parameter will contain an Error object if an error occured or null otherwise. The second parameter will contain a reference to this object. + * @return {null} + * @api public + */ +GridStore.unlink = function(db, names, options, callback) { + var self = this; + var args = Array.prototype.slice.call(arguments, 2); + callback = args.pop(); + options = args.length ? args.shift() : {}; + + // Get the write concern + var writeConcern = _getWriteConcern(db, options); + + // List of names + if(names.constructor == Array) { + var tc = 0; + for(var i = 0; i < names.length; i++) { + ++tc; + GridStore.unlink(db, names[i], options, function(result) { + if(--tc == 0) { + callback(null, self); + } + }); + } + } else { + new GridStore(db, names, "w", options).open(function(err, gridStore) { + if(err) return callback(err); + deleteChunks(gridStore, function(err, result) { + if(err) return callback(err); + gridStore.collection(function(err, collection) { + if(err) return callback(err); + collection.remove({'_id':gridStore.fileId}, writeConcern, function(err, result) { + callback(err, self); + }); + }); + }); + }); + } +}; + +/** + * Returns the current chunksize of the file. + * + * @field chunkSize + * @type {Number} + * @getter + * @setter + * @property return number of bytes in the current chunkSize. + */ +Object.defineProperty(GridStore.prototype, "chunkSize", { enumerable: true + , get: function () { + return this.internalChunkSize; + } + , set: function(value) { + if(!(this.mode[0] == "w" && this.position == 0 && this.uploadDate == null)) { + this.internalChunkSize = this.internalChunkSize; + } else { + this.internalChunkSize = value; + } + } +}); + +/** + * The md5 checksum for this file. + * + * @field md5 + * @type {Number} + * @getter + * @setter + * @property return this files md5 checksum. + */ +Object.defineProperty(GridStore.prototype, "md5", { enumerable: true + , get: function () { + return this.internalMd5; + } +}); + +/** + * GridStore Streaming methods + * Handles the correct return of the writeable stream status + * @ignore + */ +Object.defineProperty(GridStore.prototype, "writable", { enumerable: true + , get: function () { + if(this._writeable == null) { + this._writeable = this.mode != null && this.mode.indexOf("w") != -1; + } + // Return the _writeable + return this._writeable; + } + , set: function(value) { + this._writeable = value; + } +}); + +/** + * Handles the correct return of the readable stream status + * @ignore + */ +Object.defineProperty(GridStore.prototype, "readable", { enumerable: true + , get: function () { + if(this._readable == null) { + this._readable = this.mode != null && this.mode.indexOf("r") != -1; + } + return this._readable; + } + , set: function(value) { + this._readable = value; + } +}); + +GridStore.prototype.paused; + +/** + * Handles the correct setting of encoding for the stream + * @ignore + */ +GridStore.prototype.setEncoding = fs.ReadStream.prototype.setEncoding; + +/** + * Handles the end events + * @ignore + */ +GridStore.prototype.end = function end(data) { + var self = this; + // allow queued data to write before closing + if(!this.writable) return; + this.writable = false; + + if(data) { + this._q.push(data); + } + + this.on('drain', function () { + self.close(function (err) { + if (err) return _error(self, err); + self.emit('close'); + }); + }); + + _flush(self); +} + +/** + * Handles the normal writes to gridstore + * @ignore + */ +var _writeNormal = function(self, data, close, callback) { + // If we have a buffer write it using the writeBuffer method + if(Buffer.isBuffer(data)) { + return writeBuffer(self, data, close, callback); + } else { + return writeBuffer(self, new Buffer(data, 'binary'), close, callback); + } +} + +/** + * Writes some data. This method will work properly only if initialized with mode "w" or "w+". + * + * @param {String|Buffer} data the data to write. + * @param {Boolean} [close] closes this file after writing if set to true. + * @param {Function} callback this will be called after executing this method. The first parameter will contain null and the second one will contain a reference to this object. + * @return {null} + * @api public + */ +GridStore.prototype.write = function write(data, close, callback) { + // If it's a normal write delegate the call + if(typeof close == 'function' || typeof callback == 'function') { + return _writeNormal(this, data, close, callback); + } + + // Otherwise it's a stream write + var self = this; + if (!this.writable) { + throw new Error('GridWriteStream is not writable'); + } + + // queue data until we open. + if(!this._opened) { + // Set up a queue to save data until gridstore object is ready + this._q = []; + _openStream(self); + this._q.push(data); + return false; + } + + // Push data to queue + this._q.push(data); + _flush(this); + // Return write successful + return true; +} + +/** + * Handles the destroy part of a stream + * @ignore + */ +GridStore.prototype.destroy = function destroy() { + // close and do not emit any more events. queued data is not sent. + if(!this.writable) return; + this.readable = false; + if(this.writable) { + this.writable = false; + this._q.length = 0; + this.emit('close'); + } +} + +/** + * Handles the destroySoon part of a stream + * @ignore + */ +GridStore.prototype.destroySoon = function destroySoon() { + // as soon as write queue is drained, destroy. + // may call destroy immediately if no data is queued. + if(!this._q.length) { + return this.destroy(); + } + this._destroying = true; +} + +/** + * Handles the pipe part of the stream + * @ignore + */ +GridStore.prototype.pipe = function(destination, options) { + var self = this; + // Open the gridstore + this.open(function(err, result) { + if(err) _errorRead(self, err); + if(!self.readable) return; + // Set up the pipe + self._pipe(destination, options); + // Emit the stream is open + self.emit('open'); + // Read from the stream + _read(self); + }); + return destination; +} + +/** + * Internal module methods + * @ignore + */ +var _read = function _read(self) { + if (!self.readable || self.paused || self.reading) { + return; + } + + self.reading = true; + var stream = self._stream = self.stream(); + stream.paused = self.paused; + + stream.on('data', function (data) { + if (self._decoder) { + var str = self._decoder.write(data); + if (str.length) self.emit('data', str); + } else { + self.emit('data', data); + } + }); + + stream.on('end', function (data) { + self.emit('end', data); + }); + + stream.on('error', function (data) { + _errorRead(self, data); + }); + + stream.on('close', function (data) { + self.emit('close', data); + }); + + self.pause = function () { + // native doesn't always pause. + // bypass its pause() method to hack it + self.paused = stream.paused = true; + } + + self.resume = function () { + if(!self.paused) return; + + self.paused = false; + stream.resume(); + self.readable = stream.readable; + } + + self.destroy = function () { + self.readable = false; + stream.destroy(); + } +} + +/** + * pause + * @ignore + */ +GridStore.prototype.pause = function pause () { + // Overridden when the GridStore opens. + this.paused = true; +} + +/** + * resume + * @ignore + */ +GridStore.prototype.resume = function resume () { + // Overridden when the GridStore opens. + this.paused = false; +} + +/** + * Internal module methods + * @ignore + */ +var _flush = function _flush(self, _force) { + if (!self._opened) return; + if (!_force && self._flushing) return; + self._flushing = true; + + // write the entire q to gridfs + if (!self._q.length) { + self._flushing = false; + self.emit('drain'); + + if(self._destroying) { + self.destroy(); + } + return; + } + + self.write(self._q.shift(), function (err, store) { + if (err) return _error(self, err); + self.emit('progress', store.position); + _flush(self, true); + }); +} + +var _openStream = function _openStream (self) { + if(self._opening == true) return; + self._opening = true; + + // Open the store + self.open(function (err, gridstore) { + if (err) return _error(self, err); + self._opened = true; + self.emit('open'); + _flush(self); + }); +} + +var _error = function _error(self, err) { + self.destroy(); + self.emit('error', err); +} + +var _errorRead = function _errorRead (self, err) { + self.readable = false; + self.emit('error', err); +} + +/** + * @ignore + */ +var _hasWriteConcern = function(errorOptions) { + return errorOptions == true + || errorOptions.w > 0 + || errorOptions.w == 'majority' + || errorOptions.j == true + || errorOptions.journal == true + || errorOptions.fsync == true +} + +/** + * @ignore + */ +var _setWriteConcernHash = function(options) { + var finalOptions = {}; + if(options.w != null) finalOptions.w = options.w; + if(options.journal == true) finalOptions.j = options.journal; + if(options.j == true) finalOptions.j = options.j; + if(options.fsync == true) finalOptions.fsync = options.fsync; + if(options.wtimeout != null) finalOptions.wtimeout = options.wtimeout; + return finalOptions; +} + +/** + * @ignore + */ +var _getWriteConcern = function(self, options) { + // Final options + var finalOptions = {w:1}; + options = options || {}; + + // Local options verification + if(options.w != null || typeof options.j == 'boolean' || typeof options.journal == 'boolean' || typeof options.fsync == 'boolean') { + finalOptions = _setWriteConcernHash(options); + } else if(options.safe != null && typeof options.safe == 'object') { + finalOptions = _setWriteConcernHash(options.safe); + } else if(typeof options.safe == "boolean") { + finalOptions = {w: (options.safe ? 1 : 0)}; + } else if(self.options.w != null || typeof self.options.j == 'boolean' || typeof self.options.journal == 'boolean' || typeof self.options.fsync == 'boolean') { + finalOptions = _setWriteConcernHash(self.options); + } else if(self.safe.w != null || typeof self.safe.j == 'boolean' || typeof self.safe.journal == 'boolean' || typeof self.safe.fsync == 'boolean') { + finalOptions = _setWriteConcernHash(self.safe); + } else if(typeof self.safe == "boolean") { + finalOptions = {w: (self.safe ? 1 : 0)}; + } + + // Ensure we don't have an invalid combination of write concerns + if(finalOptions.w < 1 + && (finalOptions.journal == true || finalOptions.j == true || finalOptions.fsync == true)) throw new Error("No acknowledgement using w < 1 cannot be combined with journal:true or fsync:true"); + + // Return the options + return finalOptions; +} + +/** + * @ignore + * @api private + */ +exports.GridStore = GridStore; diff --git a/node_modules/mongodb/lib/mongodb/gridfs/readstream.js b/node_modules/mongodb/lib/mongodb/gridfs/readstream.js new file mode 100644 index 0000000..4a4f7ee --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/gridfs/readstream.js @@ -0,0 +1,206 @@ +var Stream = require('stream').Stream, + timers = require('timers'), + util = require('util'); + +// Set processor, setImmediate if 0.10 otherwise nextTick +var processor = require('../utils').processor(); + +/** + * ReadStream + * + * Returns a stream interface for the **file**. + * + * Events + * - **data** {function(item) {}} the data event triggers when a document is ready. + * - **end** {function() {}} the end event triggers when there is no more documents available. + * - **close** {function() {}} the close event triggers when the stream is closed. + * - **error** {function(err) {}} the error event triggers if an error happens. + * + * @class Represents a GridFS File Stream. + * @param {Boolean} autoclose automatically close file when the stream reaches the end. + * @param {GridStore} cursor a cursor object that the stream wraps. + * @return {ReadStream} + */ +function ReadStream(autoclose, gstore) { + if (!(this instanceof ReadStream)) return new ReadStream(autoclose, gstore); + Stream.call(this); + + this.autoclose = !!autoclose; + this.gstore = gstore; + + this.finalLength = gstore.length - gstore.position; + this.completedLength = 0; + this.currentChunkNumber = gstore.currentChunk.chunkNumber; + + this.paused = false; + this.readable = true; + this.pendingChunk = null; + this.executing = false; + this.destroyed = false; + + // Calculate the number of chunks + this.numberOfChunks = Math.ceil(gstore.length/gstore.chunkSize); + + // This seek start position inside the current chunk + this.seekStartPosition = gstore.position - (this.currentChunkNumber * gstore.chunkSize); + + var self = this; + processor(function() { + self._execute(); + }); +}; + +/** + * Inherit from Stream + * @ignore + * @api private + */ +ReadStream.prototype.__proto__ = Stream.prototype; + +/** + * Flag stating whether or not this stream is readable. + */ +ReadStream.prototype.readable; + +/** + * Flag stating whether or not this stream is paused. + */ +ReadStream.prototype.paused; + +/** + * @ignore + * @api private + */ +ReadStream.prototype._execute = function() { + if(this.paused === true || this.readable === false) { + return; + } + + var gstore = this.gstore; + var self = this; + // Set that we are executing + this.executing = true; + + var last = false; + var toRead = 0; + + if(gstore.currentChunk.chunkNumber >= (this.numberOfChunks - 1)) { + self.executing = false; + last = true; + } + + // Data setup + var data = null; + + // Read a slice (with seek set if none) + if(this.seekStartPosition > 0 && (gstore.currentChunk.length() - this.seekStartPosition) > 0) { + data = gstore.currentChunk.readSlice(gstore.currentChunk.length() - this.seekStartPosition); + this.seekStartPosition = 0; + } else { + data = gstore.currentChunk.readSlice(gstore.currentChunk.length()); + } + + var processNext = function() { + if(last === true) { + self.readable = false; + self.emit("end"); + + if(self.autoclose === true) { + if(gstore.mode[0] == "w") { + gstore.close(function(err, doc) { + if (err) { + self.emit("error", err); + return; + } + self.readable = false; + self.destroyed = true; + self.emit("close", doc); + }); + } else { + self.readable = false; + self.destroyed = true; + self.emit("close"); + } + } + } else { + gstore._nthChunk(gstore.currentChunk.chunkNumber + 1, function(err, chunk) { + if(err) { + self.readable = false; + if(self.listeners("error").length > 0) + self.emit("error", err); + self.executing = false; + return; + } + + self.pendingChunk = chunk; + if(self.paused === true) { + self.executing = false; + return; + } + + gstore.currentChunk = self.pendingChunk; + self._execute(); + }); + } + } + + // Return the data + if(data != null && gstore.currentChunk.chunkNumber == self.currentChunkNumber) { + self.currentChunkNumber = self.currentChunkNumber + 1; + self.completedLength += data.length; + self.pendingChunk = null; + // Send the data + process.nextTick(function() { + self.emit("data", data); + processNext(); + }) + } else { + processNext(); + } +}; + +/** + * Pauses this stream, then no farther events will be fired. + * + * @ignore + * @api public + */ +ReadStream.prototype.pause = function() { + if(!this.executing) { + this.paused = true; + } +}; + +/** + * Destroys the stream, then no farther events will be fired. + * + * @ignore + * @api public + */ +ReadStream.prototype.destroy = function() { + if(this.destroyed) return; + this.destroyed = true; + this.readable = false; + // Emit close event + this.emit("close"); +}; + +/** + * Resumes this stream. + * + * @ignore + * @api public + */ +ReadStream.prototype.resume = function() { + if(this.paused === false || !this.readable) { + return; + } + + this.paused = false; + var self = this; + processor(function() { + self._execute(); + }); +}; + +exports.ReadStream = ReadStream; diff --git a/node_modules/mongodb/lib/mongodb/index.js b/node_modules/mongodb/lib/mongodb/index.js new file mode 100644 index 0000000..05a4cde --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/index.js @@ -0,0 +1,62 @@ +try { + exports.BSONPure = require('bson').BSONPure; + exports.BSONNative = require('bson').BSONNative; +} catch(err) { + // do nothing +} + +// export the driver version +exports.version = require('../../package').version; + +[ 'commands/base_command' + , 'admin' + , 'collection' + , 'connection/read_preference' + , 'connection/connection' + , 'connection/server' + , 'connection/mongos' + , 'connection/repl_set/repl_set' + , 'mongo_client' + , 'cursor' + , 'db' + , 'mongo_client' + , 'gridfs/grid' + , 'gridfs/chunk' + , 'gridfs/gridstore'].forEach(function (path) { + var module = require('./' + path); + for (var i in module) { + exports[i] = module[i]; + } +}); + +// backwards compat +exports.ReplSetServers = exports.ReplSet; +// Add BSON Classes +exports.Binary = require('bson').Binary; +exports.Code = require('bson').Code; +exports.DBRef = require('bson').DBRef; +exports.Double = require('bson').Double; +exports.Long = require('bson').Long; +exports.MinKey = require('bson').MinKey; +exports.MaxKey = require('bson').MaxKey; +exports.ObjectID = require('bson').ObjectID; +exports.Symbol = require('bson').Symbol; +exports.Timestamp = require('bson').Timestamp; +// Add BSON Parser +exports.BSON = require('bson').BSONPure.BSON; + +// Set up the connect function +var connect = exports.Db.connect; + +// Add the pure and native backward compatible functions +exports.pure = exports.native = function() { + return connect; +} + +// Map all values to the exports value +for(var name in exports) { + connect[name] = exports[name]; +} + +// Set our exports to be the connect function +module.exports = connect; diff --git a/node_modules/mongodb/lib/mongodb/mongo_client.js b/node_modules/mongodb/lib/mongodb/mongo_client.js new file mode 100644 index 0000000..04a0fc2 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/mongo_client.js @@ -0,0 +1,482 @@ +var Db = require('./db').Db + , Server = require('./connection/server').Server + , Mongos = require('./connection/mongos').Mongos + , ReplSet = require('./connection/repl_set/repl_set').ReplSet + , ReadPreference = require('./connection/read_preference').ReadPreference + , inherits = require('util').inherits + , EventEmitter = require('events').EventEmitter + , parse = require('./connection/url_parser').parse; + +/** + * Create a new MongoClient instance. + * + * Options + * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write + * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) + * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal + * - **j**, (Boolean, default:false) write waits for journal sync before returning + * - **readPreference** {String}, the prefered read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). + * - **native_parser** {Boolean, default:false}, use c++ bson parser. + * - **forceServerObjectId** {Boolean, default:false}, force server to create _id fields instead of client. + * - **pkFactory** {Object}, object overriding the basic ObjectID primary key generation. + * - **serializeFunctions** {Boolean, default:false}, serialize functions. + * - **raw** {Boolean, default:false}, peform operations using raw bson buffers. + * - **recordQueryStats** {Boolean, default:false}, record query statistics during execution. + * - **retryMiliSeconds** {Number, default:5000}, number of miliseconds between retries. + * - **numberOfRetries** {Number, default:5}, number of retries off connection. + * - **bufferMaxEntries** {Boolean, default: -1}, sets a cap on how many operations the driver will buffer up before giving up on getting a working connection, default is -1 which is unlimited + * + * @class Represents a MongoClient + * @param {Object} serverConfig server config object. + * @param {Object} [options] additional options for the collection. + */ +function MongoClient(serverConfig, options) { + if(serverConfig != null) { + options = options ? options : {}; + // If no write concern is set set the default to w:1 + if('w' in options === false) { + options.w = 1; + } + + // The internal db instance we are wrapping + this._db = new Db('test', serverConfig, options); + } +} + +/** + * @ignore + */ +inherits(MongoClient, EventEmitter); + +/** + * Connect to MongoDB using a url as documented at + * + * docs.mongodb.org/manual/reference/connection-string/ + * + * Options + * - **uri_decode_auth** {Boolean, default:false} uri decode the user name and password for authentication + * - **db** {Object, default: null} a hash off options to set on the db object, see **Db constructor** + * - **server** {Object, default: null} a hash off options to set on the server objects, see **Server** constructor** + * - **replSet** {Object, default: null} a hash off options to set on the replSet object, see **ReplSet** constructor** + * - **mongos** {Object, default: null} a hash off options to set on the mongos object, see **Mongos** constructor** + * + * @param {String} url connection url for MongoDB. + * @param {Object} [options] optional options for insert command + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the initialized db object or null if an error occured. + * @return {null} + * @api public + */ +MongoClient.prototype.connect = function(url, options, callback) { + var self = this; + + if(typeof options == 'function') { + callback = options; + options = {}; + } + + MongoClient.connect(url, options, function(err, db) { + if(err) return callback(err, db); + // Store internal db instance reference + self._db = db; + // Emit open and perform callback + self.emit("open", err, db); + callback(err, db); + }); +} + +/** + * Initialize the database connection. + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the connected mongoclient or null if an error occured. + * @return {null} + * @api public + */ +MongoClient.prototype.open = function(callback) { + // Self reference + var self = this; + // Open the db + this._db.open(function(err, db) { + if(err) return callback(err, null); + // Emit open event + self.emit("open", err, db); + // Callback + callback(null, self); + }) +} + +/** + * Close the current db connection, including all the child db instances. Emits close event and calls optional callback. + * + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the close method or null if an error occured. + * @return {null} + * @api public + */ +MongoClient.prototype.close = function(callback) { + this._db.close(callback); +} + +/** + * Create a new Db instance sharing the current socket connections. + * + * @param {String} dbName the name of the database we want to use. + * @return {Db} a db instance using the new database. + * @api public + */ +MongoClient.prototype.db = function(dbName) { + return this._db.db(dbName); +} + +/** + * Connect to MongoDB using a url as documented at + * + * docs.mongodb.org/manual/reference/connection-string/ + * + * Options + * - **uri_decode_auth** {Boolean, default:false} uri decode the user name and password for authentication + * - **db** {Object, default: null} a hash off options to set on the db object, see **Db constructor** + * - **server** {Object, default: null} a hash off options to set on the server objects, see **Server** constructor** + * - **replSet** {Object, default: null} a hash off options to set on the replSet object, see **ReplSet** constructor** + * - **mongos** {Object, default: null} a hash off options to set on the mongos object, see **Mongos** constructor** + * + * @param {String} url connection url for MongoDB. + * @param {Object} [options] optional options for insert command + * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the initialized db object or null if an error occured. + * @return {null} + * @api public + */ +MongoClient.connect = function(url, options, callback) { + var args = Array.prototype.slice.call(arguments, 1); + callback = typeof args[args.length - 1] == 'function' ? args.pop() : null; + options = args.length ? args.shift() : null; + options = options || {}; + + // Set default empty server options + var serverOptions = options.server || {}; + var mongosOptions = options.mongos || {}; + var replSetServersOptions = options.replSet || options.replSetServers || {}; + var dbOptions = options.db || {}; + + // If callback is null throw an exception + if(callback == null) + throw new Error("no callback function provided"); + + // Parse the string + var object = parse(url, options); + + // Merge in any options for db in options object + if(dbOptions) { + for(var name in dbOptions) object.db_options[name] = dbOptions[name]; + } + + // Added the url to the options + object.db_options.url = url; + + // Merge in any options for server in options object + if(serverOptions) { + for(var name in serverOptions) object.server_options[name] = serverOptions[name]; + } + + // Merge in any replicaset server options + if(replSetServersOptions) { + for(var name in replSetServersOptions) object.rs_options[name] = replSetServersOptions[name]; + } + + // Merge in any replicaset server options + if(mongosOptions) { + for(var name in mongosOptions) object.mongos_options[name] = mongosOptions[name]; + } + + // We need to ensure that the list of servers are only either direct members or mongos + // they cannot be a mix of monogs and mongod's + var totalNumberOfServers = object.servers.length; + var totalNumberOfMongosServers = 0; + var totalNumberOfMongodServers = 0; + var serverConfig = null; + var errorServers = {}; + + // Failure modes + if(object.servers.length == 0) throw new Error("connection string must contain at least one seed host"); + + // If we have no db setting for the native parser try to set the c++ one first + object.db_options.native_parser = _setNativeParser(object.db_options); + // If no auto_reconnect is set, set it to true as default for single servers + if(typeof object.server_options.auto_reconnect != 'boolean') { + object.server_options.auto_reconnect = true; + } + + // Establish the correct socketTimeout + var connectTimeoutMS = 30000; + var socketTimeoutMS = 0; + + // We have a server connection timeout setting + if(object.server_options && object.server_options.socketOptions && object.server_options.socketOptions.connectTimeoutMS) { + connectTimeoutMS = object.server_options.socketOptions.connectTimeoutMS; + } + + // We have a rs options set for connection timeout, override any server ones + if(object.rs_options && object.rs_options.socketOptions && object.rs_options.socketOptions.connectTimeoutMS) { + connectTimeoutMS = object.rs_options.socketOptions.connectTimeoutMS; + } + + // If we have no socket settings set the default values + if(object.rs_options.socketOptions.connectTimeoutMS == null) { + object.rs_options.socketOptions.connectTimeoutMS = connectTimeoutMS; + } + + if(object.rs_options.socketOptions.socketTimeoutMS == null) { + object.rs_options.socketOptions.socketTimeoutMS = socketTimeoutMS; + } + + if(object.server_options.socketOptions.connectTimeoutMS == null) { + object.server_options.socketOptions.connectTimeoutMS = connectTimeoutMS; + } + + if(object.server_options.socketOptions.socketTimeoutMS == null) { + object.server_options.socketOptions.socketTimeoutMS = socketTimeoutMS; + } + + // If we have more than a server, it could be replicaset or mongos list + // need to verify that it's one or the other and fail if it's a mix + // Connect to all servers and run ismaster + for(var i = 0; i < object.servers.length; i++) { + // Set up socket options + var _server_options = { + poolSize:1 + , socketOptions: { + connectTimeoutMS: connectTimeoutMS + , socketTimeoutMS: socketTimeoutMS + } + , auto_reconnect:false}; + + // Ensure we have ssl setup for the servers + if(object.rs_options.ssl) { + _server_options.ssl = object.rs_options.ssl; + _server_options.sslValidate = object.rs_options.sslValidate; + _server_options.sslCA = object.rs_options.sslCA; + _server_options.sslCert = object.rs_options.sslCert; + _server_options.sslKey = object.rs_options.sslKey; + _server_options.sslPass = object.rs_options.sslPass; + } else if(object.server_options.ssl) { + _server_options.ssl = object.server_options.ssl; + _server_options.sslValidate = object.server_options.sslValidate; + _server_options.sslCA = object.server_options.sslCA; + _server_options.sslCert = object.server_options.sslCert; + _server_options.sslKey = object.server_options.sslKey; + _server_options.sslPass = object.server_options.sslPass; + } + + // Set up the Server object + var _server = object.servers[i].domain_socket + ? new Server(object.servers[i].domain_socket, _server_options) + : new Server(object.servers[i].host, object.servers[i].port, _server_options); + + var connectFunction = function(__server) { + // Attempt connect + new Db(object.dbName, __server, {w:1, native_parser:false}).open(function(err, db) { + // Update number of servers + totalNumberOfServers = totalNumberOfServers - 1; + // If no error do the correct checks + if(!err) { + // Close the connection + db.close(true); + var isMasterDoc = db.serverConfig.isMasterDoc; + // Check what type of server we have + if(isMasterDoc.setName) totalNumberOfMongodServers++; + if(isMasterDoc.msg && isMasterDoc.msg == "isdbgrid") totalNumberOfMongosServers++; + } else { + errorServers[__server.host + ":" + __server.port] = __server; + } + + if(totalNumberOfServers == 0) { + // If we have a mix of mongod and mongos, throw an error + if(totalNumberOfMongosServers > 0 && totalNumberOfMongodServers > 0) { + return process.nextTick(function() { + try { + callback(new Error("cannot combine a list of replicaset seeds and mongos seeds")); + } catch (err) { + if(db) db.close(); + throw err + } + }) + } + + if(totalNumberOfMongodServers == 0 && object.servers.length == 1) { + var obj = object.servers[0]; + serverConfig = obj.domain_socket ? + new Server(obj.domain_socket, object.server_options) + : new Server(obj.host, obj.port, object.server_options); + } else if(totalNumberOfMongodServers > 0 || totalNumberOfMongosServers > 0) { + var finalServers = object.servers + .filter(function(serverObj) { + return errorServers[serverObj.host + ":" + serverObj.port] == null; + }) + .map(function(serverObj) { + return new Server(serverObj.host, serverObj.port, object.server_options); + }); + // Clean out any error servers + errorServers = {}; + // Set up the final configuration + if(totalNumberOfMongodServers > 0) { + serverConfig = new ReplSet(finalServers, object.rs_options); + } else { + serverConfig = new Mongos(finalServers, object.mongos_options); + } + } + + if(serverConfig == null) { + return process.nextTick(function() { + try { + callback(new Error("Could not locate any valid servers in initial seed list")); + } catch (err) { + if(db) db.close(); + throw err + } + }); + } + // Ensure no firing off open event before we are ready + serverConfig.emitOpen = false; + // Set up all options etc and connect to the database + _finishConnecting(serverConfig, object, options, callback) + } + }); + } + + // Wrap the context of the call + connectFunction(_server); + } +} + +var _setNativeParser = function(db_options) { + if(typeof db_options.native_parser == 'boolean') return db_options.native_parser; + + try { + require('bson').BSONNative.BSON; + return true; + } catch(err) { + return false; + } +} + +var _finishConnecting = function(serverConfig, object, options, callback) { + // Safe settings + var safe = {}; + // Build the safe parameter if needed + if(object.db_options.journal) safe.j = object.db_options.journal; + if(object.db_options.w) safe.w = object.db_options.w; + if(object.db_options.fsync) safe.fsync = object.db_options.fsync; + if(object.db_options.wtimeoutMS) safe.wtimeout = object.db_options.wtimeoutMS; + + // If we have a read Preference set + if(object.db_options.read_preference) { + var readPreference = new ReadPreference(object.db_options.read_preference); + // If we have the tags set up + if(object.db_options.read_preference_tags) + readPreference = new ReadPreference(object.db_options.read_preference, object.db_options.read_preference_tags); + // Add the read preference + object.db_options.readPreference = readPreference; + } + + // No safe mode if no keys + if(Object.keys(safe).length == 0) safe = false; + + // Add the safe object + object.db_options.safe = safe; + + // Get the socketTimeoutMS + var socketTimeoutMS = object.server_options.socketOptions.socketTimeoutMS || 0; + var connectTimeoutMS = object.server_options.socketOptions.connectTimeoutMS || 30000; + + // If we have a replset, override with replicaset socket timeout option if available + if(serverConfig instanceof ReplSet) { + socketTimeoutMS = object.rs_options.socketOptions.socketTimeoutMS || socketTimeoutMS; + } + + // + // Set socketTimeout to same as connectionTimeout to ensure we don't block on connect and auth + // This is a workaround for pre 2.6 servers where auth can hang when indexes are build on secondaries + serverConfig.setSocketOptions({socketTimeoutMS: connectTimeoutMS, connectTimeoutMS: connectTimeoutMS}); + + // Set up the db options + var db = new Db(object.dbName, serverConfig, object.db_options); + // Open the db + db.open(function(err, db){ + if(err) { + return process.nextTick(function() { + try { + callback(err, null); + } catch (err) { + if(db) db.close(); + throw err + } + }); + } + + // + // Set socketTimeout to same as connectionTimeout to ensure we don't block on connect and auth + // This is a workaround for pre 2.6 servers where auth can hang when indexes are build on secondaries + serverConfig.setSocketOptions({socketTimeoutMS: connectTimeoutMS, connectTimeoutMS: connectTimeoutMS}); + + // Set the provided write concern or fall back to w:1 as default + if(db.options !== null && !db.options.safe && !db.options.journal + && !db.options.w && !db.options.fsync && typeof db.options.w != 'number' + && (db.options.safe == false && object.db_options.url.indexOf("safe=") == -1)) { + db.options.w = 1; + } + + if(err == null && object.auth){ + // What db to authenticate against + var authentication_db = db; + if(object.db_options && object.db_options.authSource) { + authentication_db = db.db(object.db_options.authSource); + } + + // Build options object + var options = {}; + if(object.db_options.authMechanism) options.authMechanism = object.db_options.authMechanism; + if(object.db_options.gssapiServiceName) options.gssapiServiceName = object.db_options.gssapiServiceName; + + // Authenticate + authentication_db.authenticate(object.auth.user, object.auth.password, options, function(err, success){ + // Reset the socket timeout + serverConfig.setSocketOptions({socketTimeoutMS: socketTimeoutMS, connectTimeoutMS: connectTimeoutMS}); + + // Handle the results + if(success){ + process.nextTick(function() { + try { + callback(null, db); + } catch (err) { + if(db) db.close(); + throw err + } + }); + } else { + if(db) db.close(); + process.nextTick(function() { + try { + callback(err ? err : new Error('Could not authenticate user ' + object.auth[0]), null); + } catch (err) { + if(db) db.close(); + throw err + } + }); + } + }); + } else { + // Reset the socket timeout + serverConfig.setSocketOptions({socketTimeoutMS: socketTimeoutMS, connectTimeoutMS: connectTimeoutMS}); + + // Return connection + process.nextTick(function() { + try { + callback(err, db); + } catch (err) { + if(db) db.close(); + throw err + } + }) + } + }); +} + +exports.MongoClient = MongoClient; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/responses/mongo_reply.js b/node_modules/mongodb/lib/mongodb/responses/mongo_reply.js new file mode 100644 index 0000000..21e8cec --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/responses/mongo_reply.js @@ -0,0 +1,83 @@ +var Long = require('bson').Long + , timers = require('timers'); + +// Set processor, setImmediate if 0.10 otherwise nextTick +var processor = require('../utils').processor(); + +/** + Reply message from mongo db +**/ +var MongoReply = exports.MongoReply = function() { + this.documents = []; + this.index = 0; +}; + +MongoReply.prototype.parseHeader = function(binary_reply, bson) { + // Unpack the standard header first + this.messageLength = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24; + this.index = this.index + 4; + // Fetch the request id for this reply + this.requestId = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24; + this.index = this.index + 4; + // Fetch the id of the request that triggered the response + this.responseTo = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24; + // Skip op-code field + this.index = this.index + 4 + 4; + // Unpack the reply message + this.responseFlag = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24; + this.index = this.index + 4; + // Unpack the cursor id (a 64 bit long integer) + var low_bits = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24; + this.index = this.index + 4; + var high_bits = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24; + this.index = this.index + 4; + this.cursorId = new Long(low_bits, high_bits); + // Unpack the starting from + this.startingFrom = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24; + this.index = this.index + 4; + // Unpack the number of objects returned + this.numberReturned = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24; + this.index = this.index + 4; +} + +MongoReply.prototype.parseBody = function(binary_reply, bson, raw, callback) { + raw = raw == null ? false : raw; + + try { + // Let's unpack all the bson documents, deserialize them and store them + for(var object_index = 0; object_index < this.numberReturned; object_index++) { + var _options = {promoteLongs: bson.promoteLongs}; + + // Read the size of the bson object + var bsonObjectSize = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24; + + // If we are storing the raw responses to pipe straight through + if(raw) { + // Deserialize the object and add to the documents array + this.documents.push(binary_reply.slice(this.index, this.index + bsonObjectSize)); + } else { + // Deserialize the object and add to the documents array + this.documents.push(bson.deserialize(binary_reply.slice(this.index, this.index + bsonObjectSize), _options)); + } + + // Adjust binary index to point to next block of binary bson data + this.index = this.index + bsonObjectSize; + } + + // No error return + callback(null); + } catch(err) { + return callback(err); + } +} + +MongoReply.prototype.is_error = function(){ + if(this.documents.length == 1) { + return this.documents[0].ok == 1 ? false : true; + } + return false; +}; + +MongoReply.prototype.error_message = function() { + return this.documents.length == 1 && this.documents[0].ok == 1 ? '' : this.documents[0].errmsg; +}; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/scope.js b/node_modules/mongodb/lib/mongodb/scope.js new file mode 100644 index 0000000..19ca386 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/scope.js @@ -0,0 +1,86 @@ +var Cursor = require('./cursor').Cursor + , Readable = require('stream').Readable + , utils = require('./utils') + , inherits = require('util').inherits; + +var Scope = function(collection, _selector, _fields, _scope_options) { + var self = this; + + // Ensure we have at least an empty cursor options object + _scope_options = _scope_options || {}; + var _write_concern = _scope_options.write_concern || null; + + // Ensure default read preference + // if(!_scope_options.readPreference) _scope_options.readPreference = 'primary'; + + // Set up the cursor + var _cursor = new Cursor( + collection.db, collection, _selector + , _fields, _scope_options + ); + + // Write branch options + var writeOptions = { + insert: function(documents, callback) { + // Merge together options + var options = _write_concern || {}; + // Execute insert + collection.insert(documents, options, callback); + }, + + save: function(document, callback) { + // Merge together options + var save_options = _write_concern || {}; + // Execute save + collection.save(document, save_options, function(err, result) { + if(typeof result == 'number' && result == 1) { + return callback(null, document); + } + + return callback(null, document); + }); + }, + + find: function(selector) { + _selector = selector; + return writeOptions; + }, + + // + // Update is implicit multiple document update + update: function(operations, callback) { + // Merge together options + var update_options = _write_concern || {}; + + // Set up options, multi is default operation + update_options.multi = _scope_options.multi ? _scope_options.multi : true; + if(_scope_options.upsert) update_options.upsert = _scope_options.upsert; + + // Execute options + collection.update(_selector, operations, update_options, function(err, result, obj) { + callback(err, obj); + }); + }, + } + + // Set write concern + this.withWriteConcern = function(write_concern) { + // Save the current write concern to the Scope + _scope_options.write_concern = write_concern; + _write_concern = write_concern; + // Only allow legal options + return writeOptions; + } + + // Start find + this.find = function(selector, options) { + // Save the current selector + _selector = selector; + // Set the cursor + _cursor.selector = selector; + // Return only legal read options + return Cursor.cloneWithOptions(_cursor, _scope_options); + } +} + +exports.Scope = Scope; diff --git a/node_modules/mongodb/lib/mongodb/utils.js b/node_modules/mongodb/lib/mongodb/utils.js new file mode 100644 index 0000000..f7da514 --- /dev/null +++ b/node_modules/mongodb/lib/mongodb/utils.js @@ -0,0 +1,286 @@ +var timers = require('timers'); + +/** + * Sort functions, Normalize and prepare sort parameters + */ +var formatSortValue = exports.formatSortValue = function(sortDirection) { + var value = ("" + sortDirection).toLowerCase(); + + switch (value) { + case 'ascending': + case 'asc': + case '1': + return 1; + case 'descending': + case 'desc': + case '-1': + return -1; + default: + throw new Error("Illegal sort clause, must be of the form " + + "[['field1', '(ascending|descending)'], " + + "['field2', '(ascending|descending)']]"); + } +}; + +var formattedOrderClause = exports.formattedOrderClause = function(sortValue) { + var orderBy = {}; + if(sortValue == null) return null; + if (Array.isArray(sortValue)) { + if(sortValue.length === 0) { + return null; + } + + for(var i = 0; i < sortValue.length; i++) { + if(sortValue[i].constructor == String) { + orderBy[sortValue[i]] = 1; + } else { + orderBy[sortValue[i][0]] = formatSortValue(sortValue[i][1]); + } + } + } else if(sortValue != null && typeof sortValue == 'object') { + orderBy = sortValue; + } else if (typeof sortValue == 'string') { + orderBy[sortValue] = 1; + } else { + throw new Error("Illegal sort clause, must be of the form " + + "[['field1', '(ascending|descending)'], ['field2', '(ascending|descending)']]"); + } + + return orderBy; +}; + +exports.encodeInt = function(value) { + var buffer = new Buffer(4); + buffer[3] = (value >> 24) & 0xff; + buffer[2] = (value >> 16) & 0xff; + buffer[1] = (value >> 8) & 0xff; + buffer[0] = value & 0xff; + return buffer; +} + +exports.encodeIntInPlace = function(value, buffer, index) { + buffer[index + 3] = (value >> 24) & 0xff; + buffer[index + 2] = (value >> 16) & 0xff; + buffer[index + 1] = (value >> 8) & 0xff; + buffer[index] = value & 0xff; +} + +exports.encodeCString = function(string) { + var buf = new Buffer(string, 'utf8'); + return [buf, new Buffer([0])]; +} + +exports.decodeUInt32 = function(array, index) { + return array[index] | array[index + 1] << 8 | array[index + 2] << 16 | array[index + 3] << 24; +} + +// Decode the int +exports.decodeUInt8 = function(array, index) { + return array[index]; +} + +/** + * Context insensitive type checks + */ + +var toString = Object.prototype.toString; + +var isObject = exports.isObject = function (arg) { + return '[object Object]' == toString.call(arg) +} + +exports.isArray = function (arg) { + return Array.isArray(arg) || + 'object' == typeof arg && '[object Array]' == toString.call(arg) +} + +exports.isDate = function (arg) { + return 'object' == typeof arg && '[object Date]' == toString.call(arg) +} + +exports.isRegExp = function (arg) { + return 'object' == typeof arg && '[object RegExp]' == toString.call(arg) +} + +/** + * Wrap a Mongo error document in an Error instance + * @ignore + * @api private + */ +var toError = function(error) { + if (error instanceof Error) return error; + + var msg = error.err || error.errmsg || error.errMessage || error; + var e = new Error(msg); + e.name = 'MongoError'; + + // Get all object keys + var keys = typeof error == 'object' + ? Object.keys(error) + : []; + + for(var i = 0; i < keys.length; i++) { + e[keys[i]] = error[keys[i]]; + } + + return e; +} +exports.toError = toError; + +/** + * Convert a single level object to an array + * @ignore + * @api private + */ +exports.objectToArray = function(object) { + var list = []; + + for(var name in object) { + list.push(object[name]) + } + + return list; +} + +/** + * Handle single command document return + * @ignore + * @api private + */ +exports.handleSingleCommandResultReturn = function(override_value_true, override_value_false, callback) { + return function(err, result, connection) { + if(callback == null) return; + if(err && typeof callback == 'function') return callback(err, null); + if(!result || !result.documents || result.documents.length == 0) + if(typeof callback == 'function') return callback(toError("command failed to return results"), null) + if(result && result.documents[0].ok == 1) { + if(override_value_true) return callback(null, override_value_true) + if(typeof callback == 'function') return callback(null, result.documents[0]); + } + + // Return the error from the document + if(typeof callback == 'function') return callback(toError(result.documents[0]), override_value_false); + } +} + +/** + * Return correct processor + * @ignore + * @api private + */ +exports.processor = function() { + // Set processor, setImmediate if 0.10 otherwise nextTick + process.maxTickDepth = Infinity; + // Only use nextTick + return process.nextTick; +} + +/** + * Allow setting the socketTimeoutMS on all connections + * to work around issues such as secondaries blocking due to compaction + * + * @ignore + * @api private + */ +exports.setSocketTimeoutProperty = function(self, options) { + Object.defineProperty(self, "socketTimeoutMS", { + enumerable: true + , get: function () { return options.socketTimeoutMS; } + , set: function (value) { + // Set the socket timeoutMS value + options.socketTimeoutMS = value; + + // Get all the connections + var connections = self.allRawConnections(); + for(var i = 0; i < connections.length; i++) { + connections[i].socketTimeoutMS = value; + } + } + }); +} + +/** + * Determine if the server supports write commands + * + * @ignore + * @api private + */ +exports.hasWriteCommands = function(connection) { + return connection != null && connection.serverCapabilities != null && connection.serverCapabilities.hasWriteCommands; +} + +/** + * Fetch server capabilities + * + * @ignore + * @api private + */ +exports.serverCapabilities = function(connection) { + return connection != null && connection.serverCapabilities != null && connection.serverCapabilities.hasWriteCommands; +} + +/** + * Create index name based on field spec + * + * @ignore + * @api private + */ +exports.parseIndexOptions = function(fieldOrSpec) { + var fieldHash = {}; + var indexes = []; + var keys; + + // Get all the fields accordingly + if('string' == typeof fieldOrSpec) { + // 'type' + indexes.push(fieldOrSpec + '_' + 1); + fieldHash[fieldOrSpec] = 1; + } else if(Array.isArray(fieldOrSpec)) { + fieldOrSpec.forEach(function(f) { + if('string' == typeof f) { + // [{location:'2d'}, 'type'] + indexes.push(f + '_' + 1); + fieldHash[f] = 1; + } else if(Array.isArray(f)) { + // [['location', '2d'],['type', 1]] + indexes.push(f[0] + '_' + (f[1] || 1)); + fieldHash[f[0]] = f[1] || 1; + } else if(isObject(f)) { + // [{location:'2d'}, {type:1}] + keys = Object.keys(f); + keys.forEach(function(k) { + indexes.push(k + '_' + f[k]); + fieldHash[k] = f[k]; + }); + } else { + // undefined (ignore) + } + }); + } else if(isObject(fieldOrSpec)) { + // {location:'2d', type:1} + keys = Object.keys(fieldOrSpec); + keys.forEach(function(key) { + indexes.push(key + '_' + fieldOrSpec[key]); + fieldHash[key] = fieldOrSpec[key]; + }); + } + + return { + name: indexes.join("_"), keys: keys, fieldHash: fieldHash + } +} + +exports.decorateCommand = function(command, options, exclude) { + for(var name in options) { + if(exclude[name] == null) command[name] = options[name]; + } + + return command; +} + +exports.shallowObjectCopy = function(object) { + var c = {}; + for(var n in object) c[n] = object[n]; + return c; +} + diff --git a/node_modules/mongodb/node_modules/bson/.travis.yml b/node_modules/mongodb/node_modules/bson/.travis.yml new file mode 100644 index 0000000..471ed72 --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.10 # development version of 0.8, may be unstable + - 0.11 \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/bson/LICENSE b/node_modules/mongodb/node_modules/bson/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/node_modules/mongodb/node_modules/bson/Makefile b/node_modules/mongodb/node_modules/bson/Makefile new file mode 100644 index 0000000..77ce4e0 --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/Makefile @@ -0,0 +1,19 @@ +NODE = node +NPM = npm +NODEUNIT = node_modules/nodeunit/bin/nodeunit + +all: clean node_gyp + +test: clean node_gyp + npm test + +node_gyp: clean + node-gyp configure build + +clean: + node-gyp clean + +browserify: + node_modules/.bin/onejs build browser_build/package.json browser_build/bson.js + +.PHONY: all diff --git a/node_modules/mongodb/node_modules/bson/README.md b/node_modules/mongodb/node_modules/bson/README.md new file mode 100644 index 0000000..1a6fc2b --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/README.md @@ -0,0 +1,45 @@ +Javascript + C++ BSON parser +============================ + +This BSON parser is primarily meant for usage with the `mongodb` node.js driver. However thanks to such wonderful tools at `onejs` we are able to package up a BSON parser that will work in the browser aswell. The current build is located in the `browser_build/bson.js` file. + +A simple example on how to use it + + + + + + + + + It's got two simple methods to use in your application. + + * BSON.serialize(object, checkKeys, asBuffer, serializeFunctions) + * @param {Object} object the Javascript object to serialize. + * @param {Boolean} checkKeys the serializer will check if keys are valid. + * @param {Boolean} asBuffer return the serialized object as a Buffer object **(ignore)**. + * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)** + * @return {TypedArray/Array} returns a TypedArray or Array depending on what your browser supports + + * BSON.deserialize(buffer, options, isArray) + * Options + * **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized. + * **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse. + * **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function. + * @param {TypedArray/Array} a TypedArray/Array containing the BSON data + * @param {Object} [options] additional options used for the deserialization. + * @param {Boolean} [isArray] ignore used for recursive parsing. + * @return {Object} returns the deserialized Javascript Object. diff --git a/node_modules/mongodb/node_modules/bson/binding.gyp b/node_modules/mongodb/node_modules/bson/binding.gyp new file mode 100644 index 0000000..c4455e7 --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/binding.gyp @@ -0,0 +1,18 @@ +{ + 'targets': [ + { + 'target_name': 'bson', + 'sources': [ 'ext/bson.cc' ], + 'cflags!': [ '-fno-exceptions' ], + 'cflags_cc!': [ '-fno-exceptions' ], + 'include_dirs': [ '0){ + id = pkg.modules[i].id; + + if(id==moduleId || id == moduleIndexId){ + module = pkg.modules[i]; + break; + } + } + + return module; +} + +function newRequire(callingModule){ + function require(uri){ + var module, pkg; + + if(/^\./.test(uri)){ + module = findModule(callingModule, uri); + } else if ( ties && ties.hasOwnProperty( uri ) ) { + return ties[uri]; + } else if ( aliases && aliases.hasOwnProperty( uri ) ) { + return require(aliases[uri]); + } else { + pkg = pkgmap[uri]; + + if(!pkg && nativeRequire){ + try { + pkg = nativeRequire(uri); + } catch (nativeRequireError) {} + + if(pkg) return pkg; + } + + if(!pkg){ + throw new Error('Cannot find module "'+uri+'" @[module: '+callingModule.id+' package: '+callingModule.pkg.name+']'); + } + + module = pkg.index; + } + + if(!module){ + throw new Error('Cannot find module "'+uri+'" @[module: '+callingModule.id+' package: '+callingModule.pkg.name+']'); + } + + module.parent = callingModule; + return module.call(); + }; + + + return require; +} + + +function module(parent, id, wrapper){ + var mod = { pkg: parent, id: id, wrapper: wrapper }, + cached = false; + + mod.exports = {}; + mod.require = newRequire(mod); + + mod.call = function(){ + if(cached) { + return mod.exports; + } + + cached = true; + + global.require = mod.require; + + mod.wrapper(mod, mod.exports, global, global.require); + return mod.exports; + }; + + if(parent.mainModuleId == mod.id){ + parent.index = mod; + parent.parents.length === 0 && ( main = mod.call ); + } + + parent.modules.push(mod); +} + +function pkg(/* [ parentId ...], wrapper */){ + var wrapper = arguments[ arguments.length - 1 ], + parents = Array.prototype.slice.call(arguments, 0, arguments.length - 1), + ctx = wrapper(parents); + + + pkgmap[ctx.name] = ctx; + + arguments.length == 1 && ( pkgmap.main = ctx ); + + return function(modules){ + var id; + for(id in modules){ + module(ctx, id, modules[id]); + } + }; +} + + +}(this)); + +bson.pkg(function(parents){ + + return { + 'name' : 'bson', + 'mainModuleId' : 'bson', + 'modules' : [], + 'parents' : parents + }; + +})({ 'binary': function(module, exports, global, require, undefined){ + /** + * Module dependencies. + */ +if(typeof window === 'undefined') { + var Buffer = require('buffer').Buffer; // TODO just use global Buffer +} + +// Binary default subtype +var BSON_BINARY_SUBTYPE_DEFAULT = 0; + +/** + * @ignore + * @api private + */ +var writeStringToArray = function(data) { + // Create a buffer + var buffer = typeof Uint8Array != 'undefined' ? new Uint8Array(new ArrayBuffer(data.length)) : new Array(data.length); + // Write the content to the buffer + for(var i = 0; i < data.length; i++) { + buffer[i] = data.charCodeAt(i); + } + // Write the string to the buffer + return buffer; +} + +/** + * Convert Array ot Uint8Array to Binary String + * + * @ignore + * @api private + */ +var convertArraytoUtf8BinaryString = function(byteArray, startIndex, endIndex) { + var result = ""; + for(var i = startIndex; i < endIndex; i++) { + result = result + String.fromCharCode(byteArray[i]); + } + return result; +}; + +/** + * A class representation of the BSON Binary type. + * + * Sub types + * - **BSON.BSON_BINARY_SUBTYPE_DEFAULT**, default BSON type. + * - **BSON.BSON_BINARY_SUBTYPE_FUNCTION**, BSON function type. + * - **BSON.BSON_BINARY_SUBTYPE_BYTE_ARRAY**, BSON byte array type. + * - **BSON.BSON_BINARY_SUBTYPE_UUID**, BSON uuid type. + * - **BSON.BSON_BINARY_SUBTYPE_MD5**, BSON md5 type. + * - **BSON.BSON_BINARY_SUBTYPE_USER_DEFINED**, BSON user defined type. + * + * @class Represents the Binary BSON type. + * @param {Buffer} buffer a buffer object containing the binary data. + * @param {Number} [subType] the option binary type. + * @return {Grid} + */ +function Binary(buffer, subType) { + if(!(this instanceof Binary)) return new Binary(buffer, subType); + + this._bsontype = 'Binary'; + + if(buffer instanceof Number) { + this.sub_type = buffer; + this.position = 0; + } else { + this.sub_type = subType == null ? BSON_BINARY_SUBTYPE_DEFAULT : subType; + this.position = 0; + } + + if(buffer != null && !(buffer instanceof Number)) { + // Only accept Buffer, Uint8Array or Arrays + if(typeof buffer == 'string') { + // Different ways of writing the length of the string for the different types + if(typeof Buffer != 'undefined') { + this.buffer = new Buffer(buffer); + } else if(typeof Uint8Array != 'undefined' || (Object.prototype.toString.call(buffer) == '[object Array]')) { + this.buffer = writeStringToArray(buffer); + } else { + throw new Error("only String, Buffer, Uint8Array or Array accepted"); + } + } else { + this.buffer = buffer; + } + this.position = buffer.length; + } else { + if(typeof Buffer != 'undefined') { + this.buffer = new Buffer(Binary.BUFFER_SIZE); + } else if(typeof Uint8Array != 'undefined'){ + this.buffer = new Uint8Array(new ArrayBuffer(Binary.BUFFER_SIZE)); + } else { + this.buffer = new Array(Binary.BUFFER_SIZE); + } + // Set position to start of buffer + this.position = 0; + } +}; + +/** + * Updates this binary with byte_value. + * + * @param {Character} byte_value a single byte we wish to write. + * @api public + */ +Binary.prototype.put = function put(byte_value) { + // If it's a string and a has more than one character throw an error + if(byte_value['length'] != null && typeof byte_value != 'number' && byte_value.length != 1) throw new Error("only accepts single character String, Uint8Array or Array"); + if(typeof byte_value != 'number' && byte_value < 0 || byte_value > 255) throw new Error("only accepts number in a valid unsigned byte range 0-255"); + + // Decode the byte value once + var decoded_byte = null; + if(typeof byte_value == 'string') { + decoded_byte = byte_value.charCodeAt(0); + } else if(byte_value['length'] != null) { + decoded_byte = byte_value[0]; + } else { + decoded_byte = byte_value; + } + + if(this.buffer.length > this.position) { + this.buffer[this.position++] = decoded_byte; + } else { + if(typeof Buffer != 'undefined' && Buffer.isBuffer(this.buffer)) { + // Create additional overflow buffer + var buffer = new Buffer(Binary.BUFFER_SIZE + this.buffer.length); + // Combine the two buffers together + this.buffer.copy(buffer, 0, 0, this.buffer.length); + this.buffer = buffer; + this.buffer[this.position++] = decoded_byte; + } else { + var buffer = null; + // Create a new buffer (typed or normal array) + if(Object.prototype.toString.call(this.buffer) == '[object Uint8Array]') { + buffer = new Uint8Array(new ArrayBuffer(Binary.BUFFER_SIZE + this.buffer.length)); + } else { + buffer = new Array(Binary.BUFFER_SIZE + this.buffer.length); + } + + // We need to copy all the content to the new array + for(var i = 0; i < this.buffer.length; i++) { + buffer[i] = this.buffer[i]; + } + + // Reassign the buffer + this.buffer = buffer; + // Write the byte + this.buffer[this.position++] = decoded_byte; + } + } +}; + +/** + * Writes a buffer or string to the binary. + * + * @param {Buffer|String} string a string or buffer to be written to the Binary BSON object. + * @param {Number} offset specify the binary of where to write the content. + * @api public + */ +Binary.prototype.write = function write(string, offset) { + offset = typeof offset == 'number' ? offset : this.position; + + // If the buffer is to small let's extend the buffer + if(this.buffer.length < offset + string.length) { + var buffer = null; + // If we are in node.js + if(typeof Buffer != 'undefined' && Buffer.isBuffer(this.buffer)) { + buffer = new Buffer(this.buffer.length + string.length); + this.buffer.copy(buffer, 0, 0, this.buffer.length); + } else if(Object.prototype.toString.call(this.buffer) == '[object Uint8Array]') { + // Create a new buffer + buffer = new Uint8Array(new ArrayBuffer(this.buffer.length + string.length)) + // Copy the content + for(var i = 0; i < this.position; i++) { + buffer[i] = this.buffer[i]; + } + } + + // Assign the new buffer + this.buffer = buffer; + } + + if(typeof Buffer != 'undefined' && Buffer.isBuffer(string) && Buffer.isBuffer(this.buffer)) { + string.copy(this.buffer, offset, 0, string.length); + this.position = (offset + string.length) > this.position ? (offset + string.length) : this.position; + // offset = string.length + } else if(typeof Buffer != 'undefined' && typeof string == 'string' && Buffer.isBuffer(this.buffer)) { + this.buffer.write(string, 'binary', offset); + this.position = (offset + string.length) > this.position ? (offset + string.length) : this.position; + // offset = string.length; + } else if(Object.prototype.toString.call(string) == '[object Uint8Array]' + || Object.prototype.toString.call(string) == '[object Array]' && typeof string != 'string') { + for(var i = 0; i < string.length; i++) { + this.buffer[offset++] = string[i]; + } + + this.position = offset > this.position ? offset : this.position; + } else if(typeof string == 'string') { + for(var i = 0; i < string.length; i++) { + this.buffer[offset++] = string.charCodeAt(i); + } + + this.position = offset > this.position ? offset : this.position; + } +}; + +/** + * Reads **length** bytes starting at **position**. + * + * @param {Number} position read from the given position in the Binary. + * @param {Number} length the number of bytes to read. + * @return {Buffer} + * @api public + */ +Binary.prototype.read = function read(position, length) { + length = length && length > 0 + ? length + : this.position; + + // Let's return the data based on the type we have + if(this.buffer['slice']) { + return this.buffer.slice(position, position + length); + } else { + // Create a buffer to keep the result + var buffer = typeof Uint8Array != 'undefined' ? new Uint8Array(new ArrayBuffer(length)) : new Array(length); + for(var i = 0; i < length; i++) { + buffer[i] = this.buffer[position++]; + } + } + // Return the buffer + return buffer; +}; + +/** + * Returns the value of this binary as a string. + * + * @return {String} + * @api public + */ +Binary.prototype.value = function value(asRaw) { + asRaw = asRaw == null ? false : asRaw; + + // If it's a node.js buffer object + if(typeof Buffer != 'undefined' && Buffer.isBuffer(this.buffer)) { + return asRaw ? this.buffer.slice(0, this.position) : this.buffer.toString('binary', 0, this.position); + } else { + if(asRaw) { + // we support the slice command use it + if(this.buffer['slice'] != null) { + return this.buffer.slice(0, this.position); + } else { + // Create a new buffer to copy content to + var newBuffer = Object.prototype.toString.call(this.buffer) == '[object Uint8Array]' ? new Uint8Array(new ArrayBuffer(this.position)) : new Array(this.position); + // Copy content + for(var i = 0; i < this.position; i++) { + newBuffer[i] = this.buffer[i]; + } + // Return the buffer + return newBuffer; + } + } else { + return convertArraytoUtf8BinaryString(this.buffer, 0, this.position); + } + } +}; + +/** + * Length. + * + * @return {Number} the length of the binary. + * @api public + */ +Binary.prototype.length = function length() { + return this.position; +}; + +/** + * @ignore + * @api private + */ +Binary.prototype.toJSON = function() { + return this.buffer != null ? this.buffer.toString('base64') : ''; +} + +/** + * @ignore + * @api private + */ +Binary.prototype.toString = function(format) { + return this.buffer != null ? this.buffer.slice(0, this.position).toString(format) : ''; +} + +Binary.BUFFER_SIZE = 256; + +/** + * Default BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_DEFAULT = 0; +/** + * Function BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_FUNCTION = 1; +/** + * Byte Array BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_BYTE_ARRAY = 2; +/** + * OLD UUID BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_UUID_OLD = 3; +/** + * UUID BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_UUID = 4; +/** + * MD5 BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_MD5 = 5; +/** + * User BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_USER_DEFINED = 128; + +/** + * Expose. + */ +exports.Binary = Binary; + + +}, + + + +'binary_parser': function(module, exports, global, require, undefined){ + /** + * Binary Parser. + * Jonas Raoni Soares Silva + * http://jsfromhell.com/classes/binary-parser [v1.0] + */ +var chr = String.fromCharCode; + +var maxBits = []; +for (var i = 0; i < 64; i++) { + maxBits[i] = Math.pow(2, i); +} + +function BinaryParser (bigEndian, allowExceptions) { + if(!(this instanceof BinaryParser)) return new BinaryParser(bigEndian, allowExceptions); + + this.bigEndian = bigEndian; + this.allowExceptions = allowExceptions; +}; + +BinaryParser.warn = function warn (msg) { + if (this.allowExceptions) { + throw new Error(msg); + } + + return 1; +}; + +BinaryParser.decodeFloat = function decodeFloat (data, precisionBits, exponentBits) { + var b = new this.Buffer(this.bigEndian, data); + + b.checkBuffer(precisionBits + exponentBits + 1); + + var bias = maxBits[exponentBits - 1] - 1 + , signal = b.readBits(precisionBits + exponentBits, 1) + , exponent = b.readBits(precisionBits, exponentBits) + , significand = 0 + , divisor = 2 + , curByte = b.buffer.length + (-precisionBits >> 3) - 1; + + do { + for (var byteValue = b.buffer[ ++curByte ], startBit = precisionBits % 8 || 8, mask = 1 << startBit; mask >>= 1; ( byteValue & mask ) && ( significand += 1 / divisor ), divisor *= 2 ); + } while (precisionBits -= startBit); + + return exponent == ( bias << 1 ) + 1 ? significand ? NaN : signal ? -Infinity : +Infinity : ( 1 + signal * -2 ) * ( exponent || significand ? !exponent ? Math.pow( 2, -bias + 1 ) * significand : Math.pow( 2, exponent - bias ) * ( 1 + significand ) : 0 ); +}; + +BinaryParser.decodeInt = function decodeInt (data, bits, signed, forceBigEndian) { + var b = new this.Buffer(this.bigEndian || forceBigEndian, data) + , x = b.readBits(0, bits) + , max = maxBits[bits]; //max = Math.pow( 2, bits ); + + return signed && x >= max / 2 + ? x - max + : x; +}; + +BinaryParser.encodeFloat = function encodeFloat (data, precisionBits, exponentBits) { + var bias = maxBits[exponentBits - 1] - 1 + , minExp = -bias + 1 + , maxExp = bias + , minUnnormExp = minExp - precisionBits + , n = parseFloat(data) + , status = isNaN(n) || n == -Infinity || n == +Infinity ? n : 0 + , exp = 0 + , len = 2 * bias + 1 + precisionBits + 3 + , bin = new Array(len) + , signal = (n = status !== 0 ? 0 : n) < 0 + , intPart = Math.floor(n = Math.abs(n)) + , floatPart = n - intPart + , lastBit + , rounded + , result + , i + , j; + + for (i = len; i; bin[--i] = 0); + + for (i = bias + 2; intPart && i; bin[--i] = intPart % 2, intPart = Math.floor(intPart / 2)); + + for (i = bias + 1; floatPart > 0 && i; (bin[++i] = ((floatPart *= 2) >= 1) - 0 ) && --floatPart); + + for (i = -1; ++i < len && !bin[i];); + + if (bin[(lastBit = precisionBits - 1 + (i = (exp = bias + 1 - i) >= minExp && exp <= maxExp ? i + 1 : bias + 1 - (exp = minExp - 1))) + 1]) { + if (!(rounded = bin[lastBit])) { + for (j = lastBit + 2; !rounded && j < len; rounded = bin[j++]); + } + + for (j = lastBit + 1; rounded && --j >= 0; (bin[j] = !bin[j] - 0) && (rounded = 0)); + } + + for (i = i - 2 < 0 ? -1 : i - 3; ++i < len && !bin[i];); + + if ((exp = bias + 1 - i) >= minExp && exp <= maxExp) { + ++i; + } else if (exp < minExp) { + exp != bias + 1 - len && exp < minUnnormExp && this.warn("encodeFloat::float underflow"); + i = bias + 1 - (exp = minExp - 1); + } + + if (intPart || status !== 0) { + this.warn(intPart ? "encodeFloat::float overflow" : "encodeFloat::" + status); + exp = maxExp + 1; + i = bias + 2; + + if (status == -Infinity) { + signal = 1; + } else if (isNaN(status)) { + bin[i] = 1; + } + } + + for (n = Math.abs(exp + bias), j = exponentBits + 1, result = ""; --j; result = (n % 2) + result, n = n >>= 1); + + for (n = 0, j = 0, i = (result = (signal ? "1" : "0") + result + bin.slice(i, i + precisionBits).join("")).length, r = []; i; j = (j + 1) % 8) { + n += (1 << j) * result.charAt(--i); + if (j == 7) { + r[r.length] = String.fromCharCode(n); + n = 0; + } + } + + r[r.length] = n + ? String.fromCharCode(n) + : ""; + + return (this.bigEndian ? r.reverse() : r).join(""); +}; + +BinaryParser.encodeInt = function encodeInt (data, bits, signed, forceBigEndian) { + var max = maxBits[bits]; + + if (data >= max || data < -(max / 2)) { + this.warn("encodeInt::overflow"); + data = 0; + } + + if (data < 0) { + data += max; + } + + for (var r = []; data; r[r.length] = String.fromCharCode(data % 256), data = Math.floor(data / 256)); + + for (bits = -(-bits >> 3) - r.length; bits--; r[r.length] = "\0"); + + return ((this.bigEndian || forceBigEndian) ? r.reverse() : r).join(""); +}; + +BinaryParser.toSmall = function( data ){ return this.decodeInt( data, 8, true ); }; +BinaryParser.fromSmall = function( data ){ return this.encodeInt( data, 8, true ); }; +BinaryParser.toByte = function( data ){ return this.decodeInt( data, 8, false ); }; +BinaryParser.fromByte = function( data ){ return this.encodeInt( data, 8, false ); }; +BinaryParser.toShort = function( data ){ return this.decodeInt( data, 16, true ); }; +BinaryParser.fromShort = function( data ){ return this.encodeInt( data, 16, true ); }; +BinaryParser.toWord = function( data ){ return this.decodeInt( data, 16, false ); }; +BinaryParser.fromWord = function( data ){ return this.encodeInt( data, 16, false ); }; +BinaryParser.toInt = function( data ){ return this.decodeInt( data, 32, true ); }; +BinaryParser.fromInt = function( data ){ return this.encodeInt( data, 32, true ); }; +BinaryParser.toLong = function( data ){ return this.decodeInt( data, 64, true ); }; +BinaryParser.fromLong = function( data ){ return this.encodeInt( data, 64, true ); }; +BinaryParser.toDWord = function( data ){ return this.decodeInt( data, 32, false ); }; +BinaryParser.fromDWord = function( data ){ return this.encodeInt( data, 32, false ); }; +BinaryParser.toQWord = function( data ){ return this.decodeInt( data, 64, true ); }; +BinaryParser.fromQWord = function( data ){ return this.encodeInt( data, 64, true ); }; +BinaryParser.toFloat = function( data ){ return this.decodeFloat( data, 23, 8 ); }; +BinaryParser.fromFloat = function( data ){ return this.encodeFloat( data, 23, 8 ); }; +BinaryParser.toDouble = function( data ){ return this.decodeFloat( data, 52, 11 ); }; +BinaryParser.fromDouble = function( data ){ return this.encodeFloat( data, 52, 11 ); }; + +// Factor out the encode so it can be shared by add_header and push_int32 +BinaryParser.encode_int32 = function encode_int32 (number, asArray) { + var a, b, c, d, unsigned; + unsigned = (number < 0) ? (number + 0x100000000) : number; + a = Math.floor(unsigned / 0xffffff); + unsigned &= 0xffffff; + b = Math.floor(unsigned / 0xffff); + unsigned &= 0xffff; + c = Math.floor(unsigned / 0xff); + unsigned &= 0xff; + d = Math.floor(unsigned); + return asArray ? [chr(a), chr(b), chr(c), chr(d)] : chr(a) + chr(b) + chr(c) + chr(d); +}; + +BinaryParser.encode_int64 = function encode_int64 (number) { + var a, b, c, d, e, f, g, h, unsigned; + unsigned = (number < 0) ? (number + 0x10000000000000000) : number; + a = Math.floor(unsigned / 0xffffffffffffff); + unsigned &= 0xffffffffffffff; + b = Math.floor(unsigned / 0xffffffffffff); + unsigned &= 0xffffffffffff; + c = Math.floor(unsigned / 0xffffffffff); + unsigned &= 0xffffffffff; + d = Math.floor(unsigned / 0xffffffff); + unsigned &= 0xffffffff; + e = Math.floor(unsigned / 0xffffff); + unsigned &= 0xffffff; + f = Math.floor(unsigned / 0xffff); + unsigned &= 0xffff; + g = Math.floor(unsigned / 0xff); + unsigned &= 0xff; + h = Math.floor(unsigned); + return chr(a) + chr(b) + chr(c) + chr(d) + chr(e) + chr(f) + chr(g) + chr(h); +}; + +/** + * UTF8 methods + */ + +// Take a raw binary string and return a utf8 string +BinaryParser.decode_utf8 = function decode_utf8 (binaryStr) { + var len = binaryStr.length + , decoded = '' + , i = 0 + , c = 0 + , c1 = 0 + , c2 = 0 + , c3; + + while (i < len) { + c = binaryStr.charCodeAt(i); + if (c < 128) { + decoded += String.fromCharCode(c); + i++; + } else if ((c > 191) && (c < 224)) { + c2 = binaryStr.charCodeAt(i+1); + decoded += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); + i += 2; + } else { + c2 = binaryStr.charCodeAt(i+1); + c3 = binaryStr.charCodeAt(i+2); + decoded += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); + i += 3; + } + } + + return decoded; +}; + +// Encode a cstring +BinaryParser.encode_cstring = function encode_cstring (s) { + return unescape(encodeURIComponent(s)) + BinaryParser.fromByte(0); +}; + +// Take a utf8 string and return a binary string +BinaryParser.encode_utf8 = function encode_utf8 (s) { + var a = "" + , c; + + for (var n = 0, len = s.length; n < len; n++) { + c = s.charCodeAt(n); + + if (c < 128) { + a += String.fromCharCode(c); + } else if ((c > 127) && (c < 2048)) { + a += String.fromCharCode((c>>6) | 192) ; + a += String.fromCharCode((c&63) | 128); + } else { + a += String.fromCharCode((c>>12) | 224); + a += String.fromCharCode(((c>>6) & 63) | 128); + a += String.fromCharCode((c&63) | 128); + } + } + + return a; +}; + +BinaryParser.hprint = function hprint (s) { + var number; + + for (var i = 0, len = s.length; i < len; i++) { + if (s.charCodeAt(i) < 32) { + number = s.charCodeAt(i) <= 15 + ? "0" + s.charCodeAt(i).toString(16) + : s.charCodeAt(i).toString(16); + process.stdout.write(number + " ") + } else { + number = s.charCodeAt(i) <= 15 + ? "0" + s.charCodeAt(i).toString(16) + : s.charCodeAt(i).toString(16); + process.stdout.write(number + " ") + } + } + + process.stdout.write("\n\n"); +}; + +BinaryParser.ilprint = function hprint (s) { + var number; + + for (var i = 0, len = s.length; i < len; i++) { + if (s.charCodeAt(i) < 32) { + number = s.charCodeAt(i) <= 15 + ? "0" + s.charCodeAt(i).toString(10) + : s.charCodeAt(i).toString(10); + + require('util').debug(number+' : '); + } else { + number = s.charCodeAt(i) <= 15 + ? "0" + s.charCodeAt(i).toString(10) + : s.charCodeAt(i).toString(10); + require('util').debug(number+' : '+ s.charAt(i)); + } + } +}; + +BinaryParser.hlprint = function hprint (s) { + var number; + + for (var i = 0, len = s.length; i < len; i++) { + if (s.charCodeAt(i) < 32) { + number = s.charCodeAt(i) <= 15 + ? "0" + s.charCodeAt(i).toString(16) + : s.charCodeAt(i).toString(16); + require('util').debug(number+' : '); + } else { + number = s.charCodeAt(i) <= 15 + ? "0" + s.charCodeAt(i).toString(16) + : s.charCodeAt(i).toString(16); + require('util').debug(number+' : '+ s.charAt(i)); + } + } +}; + +/** + * BinaryParser buffer constructor. + */ +function BinaryParserBuffer (bigEndian, buffer) { + this.bigEndian = bigEndian || 0; + this.buffer = []; + this.setBuffer(buffer); +}; + +BinaryParserBuffer.prototype.setBuffer = function setBuffer (data) { + var l, i, b; + + if (data) { + i = l = data.length; + b = this.buffer = new Array(l); + for (; i; b[l - i] = data.charCodeAt(--i)); + this.bigEndian && b.reverse(); + } +}; + +BinaryParserBuffer.prototype.hasNeededBits = function hasNeededBits (neededBits) { + return this.buffer.length >= -(-neededBits >> 3); +}; + +BinaryParserBuffer.prototype.checkBuffer = function checkBuffer (neededBits) { + if (!this.hasNeededBits(neededBits)) { + throw new Error("checkBuffer::missing bytes"); + } +}; + +BinaryParserBuffer.prototype.readBits = function readBits (start, length) { + //shl fix: Henri Torgemane ~1996 (compressed by Jonas Raoni) + + function shl (a, b) { + for (; b--; a = ((a %= 0x7fffffff + 1) & 0x40000000) == 0x40000000 ? a * 2 : (a - 0x40000000) * 2 + 0x7fffffff + 1); + return a; + } + + if (start < 0 || length <= 0) { + return 0; + } + + this.checkBuffer(start + length); + + var offsetLeft + , offsetRight = start % 8 + , curByte = this.buffer.length - ( start >> 3 ) - 1 + , lastByte = this.buffer.length + ( -( start + length ) >> 3 ) + , diff = curByte - lastByte + , sum = ((this.buffer[ curByte ] >> offsetRight) & ((1 << (diff ? 8 - offsetRight : length)) - 1)) + (diff && (offsetLeft = (start + length) % 8) ? (this.buffer[lastByte++] & ((1 << offsetLeft) - 1)) << (diff-- << 3) - offsetRight : 0); + + for(; diff; sum += shl(this.buffer[lastByte++], (diff-- << 3) - offsetRight)); + + return sum; +}; + +/** + * Expose. + */ +BinaryParser.Buffer = BinaryParserBuffer; + +exports.BinaryParser = BinaryParser; + +}, + + + +'bson': function(module, exports, global, require, undefined){ + var Long = require('./long').Long + , Double = require('./double').Double + , Timestamp = require('./timestamp').Timestamp + , ObjectID = require('./objectid').ObjectID + , Symbol = require('./symbol').Symbol + , Code = require('./code').Code + , MinKey = require('./min_key').MinKey + , MaxKey = require('./max_key').MaxKey + , DBRef = require('./db_ref').DBRef + , Binary = require('./binary').Binary + , BinaryParser = require('./binary_parser').BinaryParser + , writeIEEE754 = require('./float_parser').writeIEEE754 + , readIEEE754 = require('./float_parser').readIEEE754 + +// To ensure that 0.4 of node works correctly +var isDate = function isDate(d) { + return typeof d === 'object' && Object.prototype.toString.call(d) === '[object Date]'; +} + +/** + * Create a new BSON instance + * + * @class Represents the BSON Parser + * @return {BSON} instance of BSON Parser. + */ +function BSON () {}; + +/** + * @ignore + * @api private + */ +// BSON MAX VALUES +BSON.BSON_INT32_MAX = 0x7FFFFFFF; +BSON.BSON_INT32_MIN = -0x80000000; + +BSON.BSON_INT64_MAX = Math.pow(2, 63) - 1; +BSON.BSON_INT64_MIN = -Math.pow(2, 63); + +// JS MAX PRECISE VALUES +BSON.JS_INT_MAX = 0x20000000000000; // Any integer up to 2^53 can be precisely represented by a double. +BSON.JS_INT_MIN = -0x20000000000000; // Any integer down to -2^53 can be precisely represented by a double. + +// Internal long versions +var JS_INT_MAX_LONG = Long.fromNumber(0x20000000000000); // Any integer up to 2^53 can be precisely represented by a double. +var JS_INT_MIN_LONG = Long.fromNumber(-0x20000000000000); // Any integer down to -2^53 can be precisely represented by a double. + +/** + * Number BSON Type + * + * @classconstant BSON_DATA_NUMBER + **/ +BSON.BSON_DATA_NUMBER = 1; +/** + * String BSON Type + * + * @classconstant BSON_DATA_STRING + **/ +BSON.BSON_DATA_STRING = 2; +/** + * Object BSON Type + * + * @classconstant BSON_DATA_OBJECT + **/ +BSON.BSON_DATA_OBJECT = 3; +/** + * Array BSON Type + * + * @classconstant BSON_DATA_ARRAY + **/ +BSON.BSON_DATA_ARRAY = 4; +/** + * Binary BSON Type + * + * @classconstant BSON_DATA_BINARY + **/ +BSON.BSON_DATA_BINARY = 5; +/** + * ObjectID BSON Type + * + * @classconstant BSON_DATA_OID + **/ +BSON.BSON_DATA_OID = 7; +/** + * Boolean BSON Type + * + * @classconstant BSON_DATA_BOOLEAN + **/ +BSON.BSON_DATA_BOOLEAN = 8; +/** + * Date BSON Type + * + * @classconstant BSON_DATA_DATE + **/ +BSON.BSON_DATA_DATE = 9; +/** + * null BSON Type + * + * @classconstant BSON_DATA_NULL + **/ +BSON.BSON_DATA_NULL = 10; +/** + * RegExp BSON Type + * + * @classconstant BSON_DATA_REGEXP + **/ +BSON.BSON_DATA_REGEXP = 11; +/** + * Code BSON Type + * + * @classconstant BSON_DATA_CODE + **/ +BSON.BSON_DATA_CODE = 13; +/** + * Symbol BSON Type + * + * @classconstant BSON_DATA_SYMBOL + **/ +BSON.BSON_DATA_SYMBOL = 14; +/** + * Code with Scope BSON Type + * + * @classconstant BSON_DATA_CODE_W_SCOPE + **/ +BSON.BSON_DATA_CODE_W_SCOPE = 15; +/** + * 32 bit Integer BSON Type + * + * @classconstant BSON_DATA_INT + **/ +BSON.BSON_DATA_INT = 16; +/** + * Timestamp BSON Type + * + * @classconstant BSON_DATA_TIMESTAMP + **/ +BSON.BSON_DATA_TIMESTAMP = 17; +/** + * Long BSON Type + * + * @classconstant BSON_DATA_LONG + **/ +BSON.BSON_DATA_LONG = 18; +/** + * MinKey BSON Type + * + * @classconstant BSON_DATA_MIN_KEY + **/ +BSON.BSON_DATA_MIN_KEY = 0xff; +/** + * MaxKey BSON Type + * + * @classconstant BSON_DATA_MAX_KEY + **/ +BSON.BSON_DATA_MAX_KEY = 0x7f; + +/** + * Binary Default Type + * + * @classconstant BSON_BINARY_SUBTYPE_DEFAULT + **/ +BSON.BSON_BINARY_SUBTYPE_DEFAULT = 0; +/** + * Binary Function Type + * + * @classconstant BSON_BINARY_SUBTYPE_FUNCTION + **/ +BSON.BSON_BINARY_SUBTYPE_FUNCTION = 1; +/** + * Binary Byte Array Type + * + * @classconstant BSON_BINARY_SUBTYPE_BYTE_ARRAY + **/ +BSON.BSON_BINARY_SUBTYPE_BYTE_ARRAY = 2; +/** + * Binary UUID Type + * + * @classconstant BSON_BINARY_SUBTYPE_UUID + **/ +BSON.BSON_BINARY_SUBTYPE_UUID = 3; +/** + * Binary MD5 Type + * + * @classconstant BSON_BINARY_SUBTYPE_MD5 + **/ +BSON.BSON_BINARY_SUBTYPE_MD5 = 4; +/** + * Binary User Defined Type + * + * @classconstant BSON_BINARY_SUBTYPE_USER_DEFINED + **/ +BSON.BSON_BINARY_SUBTYPE_USER_DEFINED = 128; + +/** + * Calculate the bson size for a passed in Javascript object. + * + * @param {Object} object the Javascript object to calculate the BSON byte size for. + * @param {Boolean} [serializeFunctions] serialize all functions in the object **(default:false)**. + * @return {Number} returns the number of bytes the BSON object will take up. + * @api public + */ +BSON.calculateObjectSize = function calculateObjectSize(object, serializeFunctions) { + var totalLength = (4 + 1); + + if(Array.isArray(object)) { + for(var i = 0; i < object.length; i++) { + totalLength += calculateElement(i.toString(), object[i], serializeFunctions) + } + } else { + // If we have toBSON defined, override the current object + if(object.toBSON) { + object = object.toBSON(); + } + + // Calculate size + for(var key in object) { + totalLength += calculateElement(key, object[key], serializeFunctions) + } + } + + return totalLength; +} + +/** + * @ignore + * @api private + */ +function calculateElement(name, value, serializeFunctions) { + var isBuffer = typeof Buffer !== 'undefined'; + + switch(typeof value) { + case 'string': + return 1 + (!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1 + 4 + (!isBuffer ? numberOfBytes(value) : Buffer.byteLength(value, 'utf8')) + 1; + case 'number': + if(Math.floor(value) === value && value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) { + if(value >= BSON.BSON_INT32_MIN && value <= BSON.BSON_INT32_MAX) { // 32 bit + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (4 + 1); + } else { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (8 + 1); + } + } else { // 64 bit + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (8 + 1); + } + case 'undefined': + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (1); + case 'boolean': + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (1 + 1); + case 'object': + if(value == null || value instanceof MinKey || value instanceof MaxKey || value['_bsontype'] == 'MinKey' || value['_bsontype'] == 'MaxKey') { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (1); + } else if(value instanceof ObjectID || value['_bsontype'] == 'ObjectID') { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (12 + 1); + } else if(value instanceof Date || isDate(value)) { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (8 + 1); + } else if(typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (1 + 4 + 1) + value.length; + } else if(value instanceof Long || value instanceof Double || value instanceof Timestamp + || value['_bsontype'] == 'Long' || value['_bsontype'] == 'Double' || value['_bsontype'] == 'Timestamp') { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (8 + 1); + } else if(value instanceof Code || value['_bsontype'] == 'Code') { + // Calculate size depending on the availability of a scope + if(value.scope != null && Object.keys(value.scope).length > 0) { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + 4 + 4 + (!isBuffer ? numberOfBytes(value.code.toString()) : Buffer.byteLength(value.code.toString(), 'utf8')) + 1 + BSON.calculateObjectSize(value.scope, serializeFunctions); + } else { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + 4 + (!isBuffer ? numberOfBytes(value.code.toString()) : Buffer.byteLength(value.code.toString(), 'utf8')) + 1; + } + } else if(value instanceof Binary || value['_bsontype'] == 'Binary') { + // Check what kind of subtype we have + if(value.sub_type == Binary.SUBTYPE_BYTE_ARRAY) { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (value.position + 1 + 4 + 1 + 4); + } else { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (value.position + 1 + 4 + 1); + } + } else if(value instanceof Symbol || value['_bsontype'] == 'Symbol') { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + ((!isBuffer ? numberOfBytes(value.value) : Buffer.byteLength(value.value, 'utf8')) + 4 + 1 + 1); + } else if(value instanceof DBRef || value['_bsontype'] == 'DBRef') { + // Set up correct object for serialization + var ordered_values = { + '$ref': value.namespace + , '$id' : value.oid + }; + + // Add db reference if it exists + if(null != value.db) { + ordered_values['$db'] = value.db; + } + + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + BSON.calculateObjectSize(ordered_values, serializeFunctions); + } else if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]') { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + (!isBuffer ? numberOfBytes(value.source) : Buffer.byteLength(value.source, 'utf8')) + 1 + + (value.global ? 1 : 0) + (value.ignoreCase ? 1 : 0) + (value.multiline ? 1 : 0) + 1 + } else { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + BSON.calculateObjectSize(value, serializeFunctions) + 1; + } + case 'function': + // WTF for 0.4.X where typeof /someregexp/ === 'function' + if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]' || String.call(value) == '[object RegExp]') { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + (!isBuffer ? numberOfBytes(value.source) : Buffer.byteLength(value.source, 'utf8')) + 1 + + (value.global ? 1 : 0) + (value.ignoreCase ? 1 : 0) + (value.multiline ? 1 : 0) + 1 + } else { + if(serializeFunctions && value.scope != null && Object.keys(value.scope).length > 0) { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + 4 + 4 + (!isBuffer ? numberOfBytes(value.toString()) : Buffer.byteLength(value.toString(), 'utf8')) + 1 + BSON.calculateObjectSize(value.scope, serializeFunctions); + } else if(serializeFunctions) { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + 4 + (!isBuffer ? numberOfBytes(value.toString()) : Buffer.byteLength(value.toString(), 'utf8')) + 1; + } + } + } + + return 0; +} + +/** + * Serialize a Javascript object using a predefined Buffer and index into the buffer, useful when pre-allocating the space for serialization. + * + * @param {Object} object the Javascript object to serialize. + * @param {Boolean} checkKeys the serializer will check if keys are valid. + * @param {Buffer} buffer the Buffer you pre-allocated to store the serialized BSON object. + * @param {Number} index the index in the buffer where we wish to start serializing into. + * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**. + * @return {Number} returns the new write index in the Buffer. + * @api public + */ +BSON.serializeWithBufferAndIndex = function serializeWithBufferAndIndex(object, checkKeys, buffer, index, serializeFunctions) { + // Default setting false + serializeFunctions = serializeFunctions == null ? false : serializeFunctions; + // Write end information (length of the object) + var size = buffer.length; + // Write the size of the object + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + return serializeObject(object, checkKeys, buffer, index, serializeFunctions) - 1; +} + +/** + * @ignore + * @api private + */ +var serializeObject = function(object, checkKeys, buffer, index, serializeFunctions) { + // Process the object + if(Array.isArray(object)) { + for(var i = 0; i < object.length; i++) { + index = packElement(i.toString(), object[i], checkKeys, buffer, index, serializeFunctions); + } + } else { + // If we have toBSON defined, override the current object + if(object.toBSON) { + object = object.toBSON(); + } + + // Serialize the object + for(var key in object) { + // Check the key and throw error if it's illegal + if (key != '$db' && key != '$ref' && key != '$id') { + // dollars and dots ok + BSON.checkKey(key, !checkKeys); + } + + // Pack the element + index = packElement(key, object[key], checkKeys, buffer, index, serializeFunctions); + } + } + + // Write zero + buffer[index++] = 0; + return index; +} + +var stringToBytes = function(str) { + var ch, st, re = []; + for (var i = 0; i < str.length; i++ ) { + ch = str.charCodeAt(i); // get char + st = []; // set up "stack" + do { + st.push( ch & 0xFF ); // push byte to stack + ch = ch >> 8; // shift value down by 1 byte + } + while ( ch ); + // add stack contents to result + // done because chars have "wrong" endianness + re = re.concat( st.reverse() ); + } + // return an array of bytes + return re; +} + +var numberOfBytes = function(str) { + var ch, st, re = 0; + for (var i = 0; i < str.length; i++ ) { + ch = str.charCodeAt(i); // get char + st = []; // set up "stack" + do { + st.push( ch & 0xFF ); // push byte to stack + ch = ch >> 8; // shift value down by 1 byte + } + while ( ch ); + // add stack contents to result + // done because chars have "wrong" endianness + re = re + st.length; + } + // return an array of bytes + return re; +} + +/** + * @ignore + * @api private + */ +var writeToTypedArray = function(buffer, string, index) { + var bytes = stringToBytes(string); + for(var i = 0; i < bytes.length; i++) { + buffer[index + i] = bytes[i]; + } + return bytes.length; +} + +/** + * @ignore + * @api private + */ +var supportsBuffer = typeof Buffer != 'undefined'; + +/** + * @ignore + * @api private + */ +var packElement = function(name, value, checkKeys, buffer, index, serializeFunctions) { + var startIndex = index; + + switch(typeof value) { + case 'string': + // Encode String type + buffer[index++] = BSON.BSON_DATA_STRING; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + + // Calculate size + var size = supportsBuffer ? Buffer.byteLength(value) + 1 : numberOfBytes(value) + 1; + // Write the size of the string to buffer + buffer[index + 3] = (size >> 24) & 0xff; + buffer[index + 2] = (size >> 16) & 0xff; + buffer[index + 1] = (size >> 8) & 0xff; + buffer[index] = size & 0xff; + // Ajust the index + index = index + 4; + // Write the string + supportsBuffer ? buffer.write(value, index, 'utf8') : writeToTypedArray(buffer, value, index); + // Update index + index = index + size - 1; + // Write zero + buffer[index++] = 0; + // Return index + return index; + case 'number': + // We have an integer value + if(Math.floor(value) === value && value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) { + // If the value fits in 32 bits encode as int, if it fits in a double + // encode it as a double, otherwise long + if(value >= BSON.BSON_INT32_MIN && value <= BSON.BSON_INT32_MAX) { + // Set int type 32 bits or less + buffer[index++] = BSON.BSON_DATA_INT; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Write the int value + buffer[index++] = value & 0xff; + buffer[index++] = (value >> 8) & 0xff; + buffer[index++] = (value >> 16) & 0xff; + buffer[index++] = (value >> 24) & 0xff; + } else if(value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) { + // Encode as double + buffer[index++] = BSON.BSON_DATA_NUMBER; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Write float + writeIEEE754(buffer, value, index, 'little', 52, 8); + // Ajust index + index = index + 8; + } else { + // Set long type + buffer[index++] = BSON.BSON_DATA_LONG; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + var longVal = Long.fromNumber(value); + var lowBits = longVal.getLowBits(); + var highBits = longVal.getHighBits(); + // Encode low bits + buffer[index++] = lowBits & 0xff; + buffer[index++] = (lowBits >> 8) & 0xff; + buffer[index++] = (lowBits >> 16) & 0xff; + buffer[index++] = (lowBits >> 24) & 0xff; + // Encode high bits + buffer[index++] = highBits & 0xff; + buffer[index++] = (highBits >> 8) & 0xff; + buffer[index++] = (highBits >> 16) & 0xff; + buffer[index++] = (highBits >> 24) & 0xff; + } + } else { + // Encode as double + buffer[index++] = BSON.BSON_DATA_NUMBER; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Write float + writeIEEE754(buffer, value, index, 'little', 52, 8); + // Ajust index + index = index + 8; + } + + return index; + case 'undefined': + // Set long type + buffer[index++] = BSON.BSON_DATA_NULL; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + return index; + case 'boolean': + // Write the type + buffer[index++] = BSON.BSON_DATA_BOOLEAN; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Encode the boolean value + buffer[index++] = value ? 1 : 0; + return index; + case 'object': + if(value === null || value instanceof MinKey || value instanceof MaxKey + || value['_bsontype'] == 'MinKey' || value['_bsontype'] == 'MaxKey') { + // Write the type of either min or max key + if(value === null) { + buffer[index++] = BSON.BSON_DATA_NULL; + } else if(value instanceof MinKey) { + buffer[index++] = BSON.BSON_DATA_MIN_KEY; + } else { + buffer[index++] = BSON.BSON_DATA_MAX_KEY; + } + + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + return index; + } else if(value instanceof ObjectID || value['_bsontype'] == 'ObjectID') { + // Write the type + buffer[index++] = BSON.BSON_DATA_OID; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + + // Write objectid + supportsBuffer ? buffer.write(value.id, index, 'binary') : writeToTypedArray(buffer, value.id, index); + // Ajust index + index = index + 12; + return index; + } else if(value instanceof Date || isDate(value)) { + // Write the type + buffer[index++] = BSON.BSON_DATA_DATE; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + + // Write the date + var dateInMilis = Long.fromNumber(value.getTime()); + var lowBits = dateInMilis.getLowBits(); + var highBits = dateInMilis.getHighBits(); + // Encode low bits + buffer[index++] = lowBits & 0xff; + buffer[index++] = (lowBits >> 8) & 0xff; + buffer[index++] = (lowBits >> 16) & 0xff; + buffer[index++] = (lowBits >> 24) & 0xff; + // Encode high bits + buffer[index++] = highBits & 0xff; + buffer[index++] = (highBits >> 8) & 0xff; + buffer[index++] = (highBits >> 16) & 0xff; + buffer[index++] = (highBits >> 24) & 0xff; + return index; + } else if(typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) { + // Write the type + buffer[index++] = BSON.BSON_DATA_BINARY; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Get size of the buffer (current write point) + var size = value.length; + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + // Write the default subtype + buffer[index++] = BSON.BSON_BINARY_SUBTYPE_DEFAULT; + // Copy the content form the binary field to the buffer + value.copy(buffer, index, 0, size); + // Adjust the index + index = index + size; + return index; + } else if(value instanceof Long || value instanceof Timestamp || value['_bsontype'] == 'Long' || value['_bsontype'] == 'Timestamp') { + // Write the type + buffer[index++] = value instanceof Long ? BSON.BSON_DATA_LONG : BSON.BSON_DATA_TIMESTAMP; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Write the date + var lowBits = value.getLowBits(); + var highBits = value.getHighBits(); + // Encode low bits + buffer[index++] = lowBits & 0xff; + buffer[index++] = (lowBits >> 8) & 0xff; + buffer[index++] = (lowBits >> 16) & 0xff; + buffer[index++] = (lowBits >> 24) & 0xff; + // Encode high bits + buffer[index++] = highBits & 0xff; + buffer[index++] = (highBits >> 8) & 0xff; + buffer[index++] = (highBits >> 16) & 0xff; + buffer[index++] = (highBits >> 24) & 0xff; + return index; + } else if(value instanceof Double || value['_bsontype'] == 'Double') { + // Encode as double + buffer[index++] = BSON.BSON_DATA_NUMBER; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Write float + writeIEEE754(buffer, value, index, 'little', 52, 8); + // Ajust index + index = index + 8; + return index; + } else if(value instanceof Code || value['_bsontype'] == 'Code') { + if(value.scope != null && Object.keys(value.scope).length > 0) { + // Write the type + buffer[index++] = BSON.BSON_DATA_CODE_W_SCOPE; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Calculate the scope size + var scopeSize = BSON.calculateObjectSize(value.scope, serializeFunctions); + // Function string + var functionString = value.code.toString(); + // Function Size + var codeSize = supportsBuffer ? Buffer.byteLength(functionString) + 1 : numberOfBytes(functionString) + 1; + + // Calculate full size of the object + var totalSize = 4 + codeSize + scopeSize + 4; + + // Write the total size of the object + buffer[index++] = totalSize & 0xff; + buffer[index++] = (totalSize >> 8) & 0xff; + buffer[index++] = (totalSize >> 16) & 0xff; + buffer[index++] = (totalSize >> 24) & 0xff; + + // Write the size of the string to buffer + buffer[index++] = codeSize & 0xff; + buffer[index++] = (codeSize >> 8) & 0xff; + buffer[index++] = (codeSize >> 16) & 0xff; + buffer[index++] = (codeSize >> 24) & 0xff; + + // Write the string + supportsBuffer ? buffer.write(functionString, index, 'utf8') : writeToTypedArray(buffer, functionString, index); + // Update index + index = index + codeSize - 1; + // Write zero + buffer[index++] = 0; + // Serialize the scope object + var scopeObjectBuffer = supportsBuffer ? new Buffer(scopeSize) : new Uint8Array(new ArrayBuffer(scopeSize)); + // Execute the serialization into a seperate buffer + serializeObject(value.scope, checkKeys, scopeObjectBuffer, 0, serializeFunctions); + + // Adjusted scope Size (removing the header) + var scopeDocSize = scopeSize; + // Write scope object size + buffer[index++] = scopeDocSize & 0xff; + buffer[index++] = (scopeDocSize >> 8) & 0xff; + buffer[index++] = (scopeDocSize >> 16) & 0xff; + buffer[index++] = (scopeDocSize >> 24) & 0xff; + + // Write the scopeObject into the buffer + supportsBuffer ? scopeObjectBuffer.copy(buffer, index, 0, scopeSize) : buffer.set(scopeObjectBuffer, index); + // Adjust index, removing the empty size of the doc (5 bytes 0000000005) + index = index + scopeDocSize - 5; + // Write trailing zero + buffer[index++] = 0; + return index + } else { + buffer[index++] = BSON.BSON_DATA_CODE; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Function string + var functionString = value.code.toString(); + // Function Size + var size = supportsBuffer ? Buffer.byteLength(functionString) + 1 : numberOfBytes(functionString) + 1; + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + // Write the string + supportsBuffer ? buffer.write(functionString, index, 'utf8') : writeToTypedArray(buffer, functionString, index); + // Update index + index = index + size - 1; + // Write zero + buffer[index++] = 0; + return index; + } + } else if(value instanceof Binary || value['_bsontype'] == 'Binary') { + // Write the type + buffer[index++] = BSON.BSON_DATA_BINARY; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Extract the buffer + var data = value.value(true); + // Calculate size + var size = value.position; + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + // Write the subtype to the buffer + buffer[index++] = value.sub_type; + + // If we have binary type 2 the 4 first bytes are the size + if(value.sub_type == Binary.SUBTYPE_BYTE_ARRAY) { + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + } + + // Write the data to the object + supportsBuffer ? data.copy(buffer, index, 0, value.position) : buffer.set(data, index); + // Ajust index + index = index + value.position; + return index; + } else if(value instanceof Symbol || value['_bsontype'] == 'Symbol') { + // Write the type + buffer[index++] = BSON.BSON_DATA_SYMBOL; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Calculate size + var size = supportsBuffer ? Buffer.byteLength(value.value) + 1 : numberOfBytes(value.value) + 1; + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + // Write the string + buffer.write(value.value, index, 'utf8'); + // Update index + index = index + size - 1; + // Write zero + buffer[index++] = 0x00; + return index; + } else if(value instanceof DBRef || value['_bsontype'] == 'DBRef') { + // Write the type + buffer[index++] = BSON.BSON_DATA_OBJECT; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Set up correct object for serialization + var ordered_values = { + '$ref': value.namespace + , '$id' : value.oid + }; + + // Add db reference if it exists + if(null != value.db) { + ordered_values['$db'] = value.db; + } + + // Message size + var size = BSON.calculateObjectSize(ordered_values, serializeFunctions); + // Serialize the object + var endIndex = BSON.serializeWithBufferAndIndex(ordered_values, checkKeys, buffer, index, serializeFunctions); + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + // Write zero for object + buffer[endIndex++] = 0x00; + // Return the end index + return endIndex; + } else if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]') { + // Write the type + buffer[index++] = BSON.BSON_DATA_REGEXP; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + + // Write the regular expression string + supportsBuffer ? buffer.write(value.source, index, 'utf8') : writeToTypedArray(buffer, value.source, index); + // Adjust the index + index = index + (supportsBuffer ? Buffer.byteLength(value.source) : numberOfBytes(value.source)); + // Write zero + buffer[index++] = 0x00; + // Write the parameters + if(value.global) buffer[index++] = 0x73; // s + if(value.ignoreCase) buffer[index++] = 0x69; // i + if(value.multiline) buffer[index++] = 0x6d; // m + // Add ending zero + buffer[index++] = 0x00; + return index; + } else { + // Write the type + buffer[index++] = Array.isArray(value) ? BSON.BSON_DATA_ARRAY : BSON.BSON_DATA_OBJECT; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Adjust the index + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + var endIndex = serializeObject(value, checkKeys, buffer, index + 4, serializeFunctions); + // Write size + var size = endIndex - index; + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + return endIndex; + } + case 'function': + // WTF for 0.4.X where typeof /someregexp/ === 'function' + if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]' || String.call(value) == '[object RegExp]') { + // Write the type + buffer[index++] = BSON.BSON_DATA_REGEXP; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + + // Write the regular expression string + buffer.write(value.source, index, 'utf8'); + // Adjust the index + index = index + (supportsBuffer ? Buffer.byteLength(value.source) : numberOfBytes(value.source)); + // Write zero + buffer[index++] = 0x00; + // Write the parameters + if(value.global) buffer[index++] = 0x73; // s + if(value.ignoreCase) buffer[index++] = 0x69; // i + if(value.multiline) buffer[index++] = 0x6d; // m + // Add ending zero + buffer[index++] = 0x00; + return index; + } else { + if(serializeFunctions && value.scope != null && Object.keys(value.scope).length > 0) { + // Write the type + buffer[index++] = BSON.BSON_DATA_CODE_W_SCOPE; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Calculate the scope size + var scopeSize = BSON.calculateObjectSize(value.scope, serializeFunctions); + // Function string + var functionString = value.toString(); + // Function Size + var codeSize = supportsBuffer ? Buffer.byteLength(functionString) + 1 : numberOfBytes(functionString) + 1; + + // Calculate full size of the object + var totalSize = 4 + codeSize + scopeSize; + + // Write the total size of the object + buffer[index++] = totalSize & 0xff; + buffer[index++] = (totalSize >> 8) & 0xff; + buffer[index++] = (totalSize >> 16) & 0xff; + buffer[index++] = (totalSize >> 24) & 0xff; + + // Write the size of the string to buffer + buffer[index++] = codeSize & 0xff; + buffer[index++] = (codeSize >> 8) & 0xff; + buffer[index++] = (codeSize >> 16) & 0xff; + buffer[index++] = (codeSize >> 24) & 0xff; + + // Write the string + supportsBuffer ? buffer.write(functionString, index, 'utf8') : writeToTypedArray(buffer, functionString, index); + // Update index + index = index + codeSize - 1; + // Write zero + buffer[index++] = 0; + // Serialize the scope object + var scopeObjectBuffer = new Buffer(scopeSize); + // Execute the serialization into a seperate buffer + serializeObject(value.scope, checkKeys, scopeObjectBuffer, 0, serializeFunctions); + + // Adjusted scope Size (removing the header) + var scopeDocSize = scopeSize - 4; + // Write scope object size + buffer[index++] = scopeDocSize & 0xff; + buffer[index++] = (scopeDocSize >> 8) & 0xff; + buffer[index++] = (scopeDocSize >> 16) & 0xff; + buffer[index++] = (scopeDocSize >> 24) & 0xff; + + // Write the scopeObject into the buffer + scopeObjectBuffer.copy(buffer, index, 0, scopeSize); + + // Adjust index, removing the empty size of the doc (5 bytes 0000000005) + index = index + scopeDocSize - 5; + // Write trailing zero + buffer[index++] = 0; + return index + } else if(serializeFunctions) { + buffer[index++] = BSON.BSON_DATA_CODE; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Function string + var functionString = value.toString(); + // Function Size + var size = supportsBuffer ? Buffer.byteLength(functionString) + 1 : numberOfBytes(functionString) + 1; + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + // Write the string + supportsBuffer ? buffer.write(functionString, index, 'utf8') : writeToTypedArray(buffer, functionString, index); + // Update index + index = index + size - 1; + // Write zero + buffer[index++] = 0; + return index; + } + } + } + + // If no value to serialize + return index; +} + +/** + * Serialize a Javascript object. + * + * @param {Object} object the Javascript object to serialize. + * @param {Boolean} checkKeys the serializer will check if keys are valid. + * @param {Boolean} asBuffer return the serialized object as a Buffer object **(ignore)**. + * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**. + * @return {Buffer} returns the Buffer object containing the serialized object. + * @api public + */ +BSON.serialize = function(object, checkKeys, asBuffer, serializeFunctions) { + // Throw error if we are trying serialize an illegal type + if(object == null || typeof object != 'object' || Array.isArray(object)) + throw new Error("Only javascript objects supported"); + + // Emoty target buffer + var buffer = null; + // Calculate the size of the object + var size = BSON.calculateObjectSize(object, serializeFunctions); + // Fetch the best available type for storing the binary data + if(buffer = typeof Buffer != 'undefined') { + buffer = new Buffer(size); + asBuffer = true; + } else if(typeof Uint8Array != 'undefined') { + buffer = new Uint8Array(new ArrayBuffer(size)); + } else { + buffer = new Array(size); + } + + // If asBuffer is false use typed arrays + BSON.serializeWithBufferAndIndex(object, checkKeys, buffer, 0, serializeFunctions); + return buffer; +} + +/** + * Contains the function cache if we have that enable to allow for avoiding the eval step on each deserialization, comparison is by md5 + * + * @ignore + * @api private + */ +var functionCache = BSON.functionCache = {}; + +/** + * Crc state variables shared by function + * + * @ignore + * @api private + */ +var table = [0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D]; + +/** + * CRC32 hash method, Fast and enough versitility for our usage + * + * @ignore + * @api private + */ +var crc32 = function(string, start, end) { + var crc = 0 + var x = 0; + var y = 0; + crc = crc ^ (-1); + + for(var i = start, iTop = end; i < iTop;i++) { + y = (crc ^ string[i]) & 0xFF; + x = table[y]; + crc = (crc >>> 8) ^ x; + } + + return crc ^ (-1); +} + +/** + * Deserialize stream data as BSON documents. + * + * Options + * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized. + * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse. + * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function. + * - **promoteLongs** {Boolean, default:true}, when deserializing a Long will fit it into a Number if it's smaller than 53 bits + * + * @param {Buffer} data the buffer containing the serialized set of BSON documents. + * @param {Number} startIndex the start index in the data Buffer where the deserialization is to start. + * @param {Number} numberOfDocuments number of documents to deserialize. + * @param {Array} documents an array where to store the deserialized documents. + * @param {Number} docStartIndex the index in the documents array from where to start inserting documents. + * @param {Object} [options] additional options used for the deserialization. + * @return {Number} returns the next index in the buffer after deserialization **x** numbers of documents. + * @api public + */ +BSON.deserializeStream = function(data, startIndex, numberOfDocuments, documents, docStartIndex, options) { + // if(numberOfDocuments !== documents.length) throw new Error("Number of expected results back is less than the number of documents"); + options = options != null ? options : {}; + var index = startIndex; + // Loop over all documents + for(var i = 0; i < numberOfDocuments; i++) { + // Find size of the document + var size = data[index] | data[index + 1] << 8 | data[index + 2] << 16 | data[index + 3] << 24; + // Update options with index + options['index'] = index; + // Parse the document at this point + documents[docStartIndex + i] = BSON.deserialize(data, options); + // Adjust index by the document size + index = index + size; + } + + // Return object containing end index of parsing and list of documents + return index; +} + +/** + * Ensure eval is isolated. + * + * @ignore + * @api private + */ +var isolateEvalWithHash = function(functionCache, hash, functionString, object) { + // Contains the value we are going to set + var value = null; + + // Check for cache hit, eval if missing and return cached function + if(functionCache[hash] == null) { + eval("value = " + functionString); + functionCache[hash] = value; + } + // Set the object + return functionCache[hash].bind(object); +} + +/** + * Ensure eval is isolated. + * + * @ignore + * @api private + */ +var isolateEval = function(functionString) { + // Contains the value we are going to set + var value = null; + // Eval the function + eval("value = " + functionString); + return value; +} + +/** + * Convert Uint8Array to String + * + * @ignore + * @api private + */ +var convertUint8ArrayToUtf8String = function(byteArray, startIndex, endIndex) { + return BinaryParser.decode_utf8(convertArraytoUtf8BinaryString(byteArray, startIndex, endIndex)); +} + +var convertArraytoUtf8BinaryString = function(byteArray, startIndex, endIndex) { + var result = ""; + for(var i = startIndex; i < endIndex; i++) { + result = result + String.fromCharCode(byteArray[i]); + } + + return result; +}; + +/** + * Deserialize data as BSON. + * + * Options + * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized. + * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse. + * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function. + * - **promoteLongs** {Boolean, default:true}, when deserializing a Long will fit it into a Number if it's smaller than 53 bits + * + * @param {Buffer} buffer the buffer containing the serialized set of BSON documents. + * @param {Object} [options] additional options used for the deserialization. + * @param {Boolean} [isArray] ignore used for recursive parsing. + * @return {Object} returns the deserialized Javascript Object. + * @api public + */ +BSON.deserialize = function(buffer, options, isArray) { + // Options + options = options == null ? {} : options; + var evalFunctions = options['evalFunctions'] == null ? false : options['evalFunctions']; + var cacheFunctions = options['cacheFunctions'] == null ? false : options['cacheFunctions']; + var cacheFunctionsCrc32 = options['cacheFunctionsCrc32'] == null ? false : options['cacheFunctionsCrc32']; + var promoteLongs = options['promoteLongs'] || true; + + // Validate that we have at least 4 bytes of buffer + if(buffer.length < 5) throw new Error("corrupt bson message < 5 bytes long"); + + // Set up index + var index = typeof options['index'] == 'number' ? options['index'] : 0; + // Reads in a C style string + var readCStyleString = function() { + // Get the start search index + var i = index; + // Locate the end of the c string + while(buffer[i] !== 0x00) { i++ } + // Grab utf8 encoded string + var string = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('utf8', index, i) : convertUint8ArrayToUtf8String(buffer, index, i); + // Update index position + index = i + 1; + // Return string + return string; + } + + // Create holding object + var object = isArray ? [] : {}; + + // Read the document size + var size = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + + // Ensure buffer is valid size + if(size < 5 || size > buffer.length) throw new Error("corrupt bson message"); + + // While we have more left data left keep parsing + while(true) { + // Read the type + var elementType = buffer[index++]; + // If we get a zero it's the last byte, exit + if(elementType == 0) break; + // Read the name of the field + var name = readCStyleString(); + // Switch on the type + switch(elementType) { + case BSON.BSON_DATA_OID: + var string = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('binary', index, index + 12) : convertArraytoUtf8BinaryString(buffer, index, index + 12); + // Decode the oid + object[name] = new ObjectID(string); + // Update index + index = index + 12; + break; + case BSON.BSON_DATA_STRING: + // Read the content of the field + var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Add string to object + object[name] = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('utf8', index, index + stringSize - 1) : convertUint8ArrayToUtf8String(buffer, index, index + stringSize - 1); + // Update parse index position + index = index + stringSize; + break; + case BSON.BSON_DATA_INT: + // Decode the 32bit value + object[name] = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + break; + case BSON.BSON_DATA_NUMBER: + // Decode the double value + object[name] = readIEEE754(buffer, index, 'little', 52, 8); + // Update the index + index = index + 8; + break; + case BSON.BSON_DATA_DATE: + // Unpack the low and high bits + var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Set date object + object[name] = new Date(new Long(lowBits, highBits).toNumber()); + break; + case BSON.BSON_DATA_BOOLEAN: + // Parse the boolean value + object[name] = buffer[index++] == 1; + break; + case BSON.BSON_DATA_NULL: + // Parse the boolean value + object[name] = null; + break; + case BSON.BSON_DATA_BINARY: + // Decode the size of the binary blob + var binarySize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Decode the subtype + var subType = buffer[index++]; + // Decode as raw Buffer object if options specifies it + if(buffer['slice'] != null) { + // If we have subtype 2 skip the 4 bytes for the size + if(subType == Binary.SUBTYPE_BYTE_ARRAY) { + binarySize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + } + // Slice the data + object[name] = new Binary(buffer.slice(index, index + binarySize), subType); + } else { + var _buffer = typeof Uint8Array != 'undefined' ? new Uint8Array(new ArrayBuffer(binarySize)) : new Array(binarySize); + // If we have subtype 2 skip the 4 bytes for the size + if(subType == Binary.SUBTYPE_BYTE_ARRAY) { + binarySize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + } + // Copy the data + for(var i = 0; i < binarySize; i++) { + _buffer[i] = buffer[index + i]; + } + // Create the binary object + object[name] = new Binary(_buffer, subType); + } + // Update the index + index = index + binarySize; + break; + case BSON.BSON_DATA_ARRAY: + options['index'] = index; + // Decode the size of the array document + var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24; + // Set the array to the object + object[name] = BSON.deserialize(buffer, options, true); + // Adjust the index + index = index + objectSize; + break; + case BSON.BSON_DATA_OBJECT: + options['index'] = index; + // Decode the size of the object document + var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24; + // Set the array to the object + object[name] = BSON.deserialize(buffer, options, false); + // Adjust the index + index = index + objectSize; + break; + case BSON.BSON_DATA_REGEXP: + // Create the regexp + var source = readCStyleString(); + var regExpOptions = readCStyleString(); + // For each option add the corresponding one for javascript + var optionsArray = new Array(regExpOptions.length); + + // Parse options + for(var i = 0; i < regExpOptions.length; i++) { + switch(regExpOptions[i]) { + case 'm': + optionsArray[i] = 'm'; + break; + case 's': + optionsArray[i] = 'g'; + break; + case 'i': + optionsArray[i] = 'i'; + break; + } + } + + object[name] = new RegExp(source, optionsArray.join('')); + break; + case BSON.BSON_DATA_LONG: + // Unpack the low and high bits + var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Create long object + var long = new Long(lowBits, highBits); + // Promote the long if possible + if(promoteLongs) { + object[name] = long.lessThanOrEqual(JS_INT_MAX_LONG) && long.greaterThanOrEqual(JS_INT_MIN_LONG) ? long.toNumber() : long; + } else { + object[name] = long; + } + break; + case BSON.BSON_DATA_SYMBOL: + // Read the content of the field + var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Add string to object + object[name] = new Symbol(buffer.toString('utf8', index, index + stringSize - 1)); + // Update parse index position + index = index + stringSize; + break; + case BSON.BSON_DATA_TIMESTAMP: + // Unpack the low and high bits + var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Set the object + object[name] = new Timestamp(lowBits, highBits); + break; + case BSON.BSON_DATA_MIN_KEY: + // Parse the object + object[name] = new MinKey(); + break; + case BSON.BSON_DATA_MAX_KEY: + // Parse the object + object[name] = new MaxKey(); + break; + case BSON.BSON_DATA_CODE: + // Read the content of the field + var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Function string + var functionString = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('utf8', index, index + stringSize - 1) : convertUint8ArrayToUtf8String(buffer, index, index + stringSize - 1); + + // If we are evaluating the functions + if(evalFunctions) { + // Contains the value we are going to set + var value = null; + // If we have cache enabled let's look for the md5 of the function in the cache + if(cacheFunctions) { + var hash = cacheFunctionsCrc32 ? crc32(functionString) : functionString; + // Got to do this to avoid V8 deoptimizing the call due to finding eval + object[name] = isolateEvalWithHash(functionCache, hash, functionString, object); + } else { + // Set directly + object[name] = isolateEval(functionString); + } + } else { + object[name] = new Code(functionString, {}); + } + + // Update parse index position + index = index + stringSize; + break; + case BSON.BSON_DATA_CODE_W_SCOPE: + // Read the content of the field + var totalSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Javascript function + var functionString = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('utf8', index, index + stringSize - 1) : convertUint8ArrayToUtf8String(buffer, index, index + stringSize - 1); + // Update parse index position + index = index + stringSize; + // Parse the element + options['index'] = index; + // Decode the size of the object document + var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24; + // Decode the scope object + var scopeObject = BSON.deserialize(buffer, options, false); + // Adjust the index + index = index + objectSize; + + // If we are evaluating the functions + if(evalFunctions) { + // Contains the value we are going to set + var value = null; + // If we have cache enabled let's look for the md5 of the function in the cache + if(cacheFunctions) { + var hash = cacheFunctionsCrc32 ? crc32(functionString) : functionString; + // Got to do this to avoid V8 deoptimizing the call due to finding eval + object[name] = isolateEvalWithHash(functionCache, hash, functionString, object); + } else { + // Set directly + object[name] = isolateEval(functionString); + } + + // Set the scope on the object + object[name].scope = scopeObject; + } else { + object[name] = new Code(functionString, scopeObject); + } + + // Add string to object + break; + } + } + + // Check if we have a db ref object + if(object['$id'] != null) object = new DBRef(object['$ref'], object['$id'], object['$db']); + + // Return the final objects + return object; +} + +/** + * Check if key name is valid. + * + * @ignore + * @api private + */ +BSON.checkKey = function checkKey (key, dollarsAndDotsOk) { + if (!key.length) return; + // Check if we have a legal key for the object + if (!!~key.indexOf("\x00")) { + // The BSON spec doesn't allow keys with null bytes because keys are + // null-terminated. + throw Error("key " + key + " must not contain null bytes"); + } + if (!dollarsAndDotsOk) { + if('$' == key[0]) { + throw Error("key " + key + " must not start with '$'"); + } else if (!!~key.indexOf('.')) { + throw Error("key " + key + " must not contain '.'"); + } + } +}; + +/** + * Deserialize data as BSON. + * + * Options + * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized. + * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse. + * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function. + * + * @param {Buffer} buffer the buffer containing the serialized set of BSON documents. + * @param {Object} [options] additional options used for the deserialization. + * @param {Boolean} [isArray] ignore used for recursive parsing. + * @return {Object} returns the deserialized Javascript Object. + * @api public + */ +BSON.prototype.deserialize = function(data, options) { + return BSON.deserialize(data, options); +} + +/** + * Deserialize stream data as BSON documents. + * + * Options + * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized. + * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse. + * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function. + * + * @param {Buffer} data the buffer containing the serialized set of BSON documents. + * @param {Number} startIndex the start index in the data Buffer where the deserialization is to start. + * @param {Number} numberOfDocuments number of documents to deserialize. + * @param {Array} documents an array where to store the deserialized documents. + * @param {Number} docStartIndex the index in the documents array from where to start inserting documents. + * @param {Object} [options] additional options used for the deserialization. + * @return {Number} returns the next index in the buffer after deserialization **x** numbers of documents. + * @api public + */ +BSON.prototype.deserializeStream = function(data, startIndex, numberOfDocuments, documents, docStartIndex, options) { + return BSON.deserializeStream(data, startIndex, numberOfDocuments, documents, docStartIndex, options); +} + +/** + * Serialize a Javascript object. + * + * @param {Object} object the Javascript object to serialize. + * @param {Boolean} checkKeys the serializer will check if keys are valid. + * @param {Boolean} asBuffer return the serialized object as a Buffer object **(ignore)**. + * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**. + * @return {Buffer} returns the Buffer object containing the serialized object. + * @api public + */ +BSON.prototype.serialize = function(object, checkKeys, asBuffer, serializeFunctions) { + return BSON.serialize(object, checkKeys, asBuffer, serializeFunctions); +} + +/** + * Calculate the bson size for a passed in Javascript object. + * + * @param {Object} object the Javascript object to calculate the BSON byte size for. + * @param {Boolean} [serializeFunctions] serialize all functions in the object **(default:false)**. + * @return {Number} returns the number of bytes the BSON object will take up. + * @api public + */ +BSON.prototype.calculateObjectSize = function(object, serializeFunctions) { + return BSON.calculateObjectSize(object, serializeFunctions); +} + +/** + * Serialize a Javascript object using a predefined Buffer and index into the buffer, useful when pre-allocating the space for serialization. + * + * @param {Object} object the Javascript object to serialize. + * @param {Boolean} checkKeys the serializer will check if keys are valid. + * @param {Buffer} buffer the Buffer you pre-allocated to store the serialized BSON object. + * @param {Number} index the index in the buffer where we wish to start serializing into. + * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**. + * @return {Number} returns the new write index in the Buffer. + * @api public + */ +BSON.prototype.serializeWithBufferAndIndex = function(object, checkKeys, buffer, startIndex, serializeFunctions) { + return BSON.serializeWithBufferAndIndex(object, checkKeys, buffer, startIndex, serializeFunctions); +} + +/** + * @ignore + * @api private + */ +exports.Code = Code; +exports.Symbol = Symbol; +exports.BSON = BSON; +exports.DBRef = DBRef; +exports.Binary = Binary; +exports.ObjectID = ObjectID; +exports.Long = Long; +exports.Timestamp = Timestamp; +exports.Double = Double; +exports.MinKey = MinKey; +exports.MaxKey = MaxKey; + +}, + + + +'code': function(module, exports, global, require, undefined){ + /** + * A class representation of the BSON Code type. + * + * @class Represents the BSON Code type. + * @param {String|Function} code a string or function. + * @param {Object} [scope] an optional scope for the function. + * @return {Code} + */ +function Code(code, scope) { + if(!(this instanceof Code)) return new Code(code, scope); + + this._bsontype = 'Code'; + this.code = code; + this.scope = scope == null ? {} : scope; +}; + +/** + * @ignore + * @api private + */ +Code.prototype.toJSON = function() { + return {scope:this.scope, code:this.code}; +} + +exports.Code = Code; +}, + + + +'db_ref': function(module, exports, global, require, undefined){ + /** + * A class representation of the BSON DBRef type. + * + * @class Represents the BSON DBRef type. + * @param {String} namespace the collection name. + * @param {ObjectID} oid the reference ObjectID. + * @param {String} [db] optional db name, if omitted the reference is local to the current db. + * @return {DBRef} + */ +function DBRef(namespace, oid, db) { + if(!(this instanceof DBRef)) return new DBRef(namespace, oid, db); + + this._bsontype = 'DBRef'; + this.namespace = namespace; + this.oid = oid; + this.db = db; +}; + +/** + * @ignore + * @api private + */ +DBRef.prototype.toJSON = function() { + return { + '$ref':this.namespace, + '$id':this.oid, + '$db':this.db == null ? '' : this.db + }; +} + +exports.DBRef = DBRef; +}, + + + +'double': function(module, exports, global, require, undefined){ + /** + * A class representation of the BSON Double type. + * + * @class Represents the BSON Double type. + * @param {Number} value the number we want to represent as a double. + * @return {Double} + */ +function Double(value) { + if(!(this instanceof Double)) return new Double(value); + + this._bsontype = 'Double'; + this.value = value; +} + +/** + * Access the number value. + * + * @return {Number} returns the wrapped double number. + * @api public + */ +Double.prototype.valueOf = function() { + return this.value; +}; + +/** + * @ignore + * @api private + */ +Double.prototype.toJSON = function() { + return this.value; +} + +exports.Double = Double; +}, + + + +'float_parser': function(module, exports, global, require, undefined){ + // Copyright (c) 2008, Fair Oaks Labs, Inc. +// All rights reserved. +// +// 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. +// +// * Neither the name of Fair Oaks Labs, Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 OWNER OR CONTRIBUTORS 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. +// +// +// Modifications to writeIEEE754 to support negative zeroes made by Brian White + +var readIEEE754 = function(buffer, offset, endian, mLen, nBytes) { + var e, m, + bBE = (endian === 'big'), + eLen = nBytes * 8 - mLen - 1, + eMax = (1 << eLen) - 1, + eBias = eMax >> 1, + nBits = -7, + i = bBE ? 0 : (nBytes - 1), + d = bBE ? 1 : -1, + s = buffer[offset + i]; + + i += d; + + e = s & ((1 << (-nBits)) - 1); + s >>= (-nBits); + nBits += eLen; + for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8); + + m = e & ((1 << (-nBits)) - 1); + e >>= (-nBits); + nBits += mLen; + for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8); + + if (e === 0) { + e = 1 - eBias; + } else if (e === eMax) { + return m ? NaN : ((s ? -1 : 1) * Infinity); + } else { + m = m + Math.pow(2, mLen); + e = e - eBias; + } + return (s ? -1 : 1) * m * Math.pow(2, e - mLen); +}; + +var writeIEEE754 = function(buffer, value, offset, endian, mLen, nBytes) { + var e, m, c, + bBE = (endian === 'big'), + eLen = nBytes * 8 - mLen - 1, + eMax = (1 << eLen) - 1, + eBias = eMax >> 1, + rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0), + i = bBE ? (nBytes-1) : 0, + d = bBE ? -1 : 1, + s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0; + + value = Math.abs(value); + + if (isNaN(value) || value === Infinity) { + m = isNaN(value) ? 1 : 0; + e = eMax; + } else { + e = Math.floor(Math.log(value) / Math.LN2); + if (value * (c = Math.pow(2, -e)) < 1) { + e--; + c *= 2; + } + if (e+eBias >= 1) { + value += rt / c; + } else { + value += rt * Math.pow(2, 1 - eBias); + } + if (value * c >= 2) { + e++; + c /= 2; + } + + if (e + eBias >= eMax) { + m = 0; + e = eMax; + } else if (e + eBias >= 1) { + m = (value * c - 1) * Math.pow(2, mLen); + e = e + eBias; + } else { + m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen); + e = 0; + } + } + + for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8); + + e = (e << mLen) | m; + eLen += mLen; + for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8); + + buffer[offset + i - d] |= s * 128; +}; + +exports.readIEEE754 = readIEEE754; +exports.writeIEEE754 = writeIEEE754; +}, + + + +'index': function(module, exports, global, require, undefined){ + try { + exports.BSONPure = require('./bson'); + exports.BSONNative = require('../../ext'); +} catch(err) { + // do nothing +} + +[ './binary_parser' + , './binary' + , './code' + , './db_ref' + , './double' + , './max_key' + , './min_key' + , './objectid' + , './symbol' + , './timestamp' + , './long'].forEach(function (path) { + var module = require('./' + path); + for (var i in module) { + exports[i] = module[i]; + } +}); + +// Exports all the classes for the NATIVE JS BSON Parser +exports.native = function() { + var classes = {}; + // Map all the classes + [ './binary_parser' + , './binary' + , './code' + , './db_ref' + , './double' + , './max_key' + , './min_key' + , './objectid' + , './symbol' + , './timestamp' + , './long' + , '../../ext' +].forEach(function (path) { + var module = require('./' + path); + for (var i in module) { + classes[i] = module[i]; + } + }); + // Return classes list + return classes; +} + +// Exports all the classes for the PURE JS BSON Parser +exports.pure = function() { + var classes = {}; + // Map all the classes + [ './binary_parser' + , './binary' + , './code' + , './db_ref' + , './double' + , './max_key' + , './min_key' + , './objectid' + , './symbol' + , './timestamp' + , './long' + , '././bson'].forEach(function (path) { + var module = require('./' + path); + for (var i in module) { + classes[i] = module[i]; + } + }); + // Return classes list + return classes; +} + +}, + + + +'long': function(module, exports, global, require, undefined){ + // Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Copyright 2009 Google Inc. All Rights Reserved + +/** + * Defines a Long class for representing a 64-bit two's-complement + * integer value, which faithfully simulates the behavior of a Java "Long". This + * implementation is derived from LongLib in GWT. + * + * Constructs a 64-bit two's-complement integer, given its low and high 32-bit + * values as *signed* integers. See the from* functions below for more + * convenient ways of constructing Longs. + * + * The internal representation of a Long is the two given signed, 32-bit values. + * We use 32-bit pieces because these are the size of integers on which + * Javascript performs bit-operations. For operations like addition and + * multiplication, we split each number into 16-bit pieces, which can easily be + * multiplied within Javascript's floating-point representation without overflow + * or change in sign. + * + * In the algorithms below, we frequently reduce the negative case to the + * positive case by negating the input(s) and then post-processing the result. + * Note that we must ALWAYS check specially whether those values are MIN_VALUE + * (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as + * a positive number, it overflows back into a negative). Not handling this + * case would often result in infinite recursion. + * + * @class Represents the BSON Long type. + * @param {Number} low the low (signed) 32 bits of the Long. + * @param {Number} high the high (signed) 32 bits of the Long. + */ +function Long(low, high) { + if(!(this instanceof Long)) return new Long(low, high); + + this._bsontype = 'Long'; + /** + * @type {number} + * @api private + */ + this.low_ = low | 0; // force into 32 signed bits. + + /** + * @type {number} + * @api private + */ + this.high_ = high | 0; // force into 32 signed bits. +}; + +/** + * Return the int value. + * + * @return {Number} the value, assuming it is a 32-bit integer. + * @api public + */ +Long.prototype.toInt = function() { + return this.low_; +}; + +/** + * Return the Number value. + * + * @return {Number} the closest floating-point representation to this value. + * @api public + */ +Long.prototype.toNumber = function() { + return this.high_ * Long.TWO_PWR_32_DBL_ + + this.getLowBitsUnsigned(); +}; + +/** + * Return the JSON value. + * + * @return {String} the JSON representation. + * @api public + */ +Long.prototype.toJSON = function() { + return this.toString(); +} + +/** + * Return the String value. + * + * @param {Number} [opt_radix] the radix in which the text should be written. + * @return {String} the textual representation of this value. + * @api public + */ +Long.prototype.toString = function(opt_radix) { + var radix = opt_radix || 10; + if (radix < 2 || 36 < radix) { + throw Error('radix out of range: ' + radix); + } + + if (this.isZero()) { + return '0'; + } + + if (this.isNegative()) { + if (this.equals(Long.MIN_VALUE)) { + // We need to change the Long value before it can be negated, so we remove + // the bottom-most digit in this base and then recurse to do the rest. + var radixLong = Long.fromNumber(radix); + var div = this.div(radixLong); + var rem = div.multiply(radixLong).subtract(this); + return div.toString(radix) + rem.toInt().toString(radix); + } else { + return '-' + this.negate().toString(radix); + } + } + + // Do several (6) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = Long.fromNumber(Math.pow(radix, 6)); + + var rem = this; + var result = ''; + while (true) { + var remDiv = rem.div(radixToPower); + var intval = rem.subtract(remDiv.multiply(radixToPower)).toInt(); + var digits = intval.toString(radix); + + rem = remDiv; + if (rem.isZero()) { + return digits + result; + } else { + while (digits.length < 6) { + digits = '0' + digits; + } + result = '' + digits + result; + } + } +}; + +/** + * Return the high 32-bits value. + * + * @return {Number} the high 32-bits as a signed value. + * @api public + */ +Long.prototype.getHighBits = function() { + return this.high_; +}; + +/** + * Return the low 32-bits value. + * + * @return {Number} the low 32-bits as a signed value. + * @api public + */ +Long.prototype.getLowBits = function() { + return this.low_; +}; + +/** + * Return the low unsigned 32-bits value. + * + * @return {Number} the low 32-bits as an unsigned value. + * @api public + */ +Long.prototype.getLowBitsUnsigned = function() { + return (this.low_ >= 0) ? + this.low_ : Long.TWO_PWR_32_DBL_ + this.low_; +}; + +/** + * Returns the number of bits needed to represent the absolute value of this Long. + * + * @return {Number} Returns the number of bits needed to represent the absolute value of this Long. + * @api public + */ +Long.prototype.getNumBitsAbs = function() { + if (this.isNegative()) { + if (this.equals(Long.MIN_VALUE)) { + return 64; + } else { + return this.negate().getNumBitsAbs(); + } + } else { + var val = this.high_ != 0 ? this.high_ : this.low_; + for (var bit = 31; bit > 0; bit--) { + if ((val & (1 << bit)) != 0) { + break; + } + } + return this.high_ != 0 ? bit + 33 : bit + 1; + } +}; + +/** + * Return whether this value is zero. + * + * @return {Boolean} whether this value is zero. + * @api public + */ +Long.prototype.isZero = function() { + return this.high_ == 0 && this.low_ == 0; +}; + +/** + * Return whether this value is negative. + * + * @return {Boolean} whether this value is negative. + * @api public + */ +Long.prototype.isNegative = function() { + return this.high_ < 0; +}; + +/** + * Return whether this value is odd. + * + * @return {Boolean} whether this value is odd. + * @api public + */ +Long.prototype.isOdd = function() { + return (this.low_ & 1) == 1; +}; + +/** + * Return whether this Long equals the other + * + * @param {Long} other Long to compare against. + * @return {Boolean} whether this Long equals the other + * @api public + */ +Long.prototype.equals = function(other) { + return (this.high_ == other.high_) && (this.low_ == other.low_); +}; + +/** + * Return whether this Long does not equal the other. + * + * @param {Long} other Long to compare against. + * @return {Boolean} whether this Long does not equal the other. + * @api public + */ +Long.prototype.notEquals = function(other) { + return (this.high_ != other.high_) || (this.low_ != other.low_); +}; + +/** + * Return whether this Long is less than the other. + * + * @param {Long} other Long to compare against. + * @return {Boolean} whether this Long is less than the other. + * @api public + */ +Long.prototype.lessThan = function(other) { + return this.compare(other) < 0; +}; + +/** + * Return whether this Long is less than or equal to the other. + * + * @param {Long} other Long to compare against. + * @return {Boolean} whether this Long is less than or equal to the other. + * @api public + */ +Long.prototype.lessThanOrEqual = function(other) { + return this.compare(other) <= 0; +}; + +/** + * Return whether this Long is greater than the other. + * + * @param {Long} other Long to compare against. + * @return {Boolean} whether this Long is greater than the other. + * @api public + */ +Long.prototype.greaterThan = function(other) { + return this.compare(other) > 0; +}; + +/** + * Return whether this Long is greater than or equal to the other. + * + * @param {Long} other Long to compare against. + * @return {Boolean} whether this Long is greater than or equal to the other. + * @api public + */ +Long.prototype.greaterThanOrEqual = function(other) { + return this.compare(other) >= 0; +}; + +/** + * Compares this Long with the given one. + * + * @param {Long} other Long to compare against. + * @return {Boolean} 0 if they are the same, 1 if the this is greater, and -1 if the given one is greater. + * @api public + */ +Long.prototype.compare = function(other) { + if (this.equals(other)) { + return 0; + } + + var thisNeg = this.isNegative(); + var otherNeg = other.isNegative(); + if (thisNeg && !otherNeg) { + return -1; + } + if (!thisNeg && otherNeg) { + return 1; + } + + // at this point, the signs are the same, so subtraction will not overflow + if (this.subtract(other).isNegative()) { + return -1; + } else { + return 1; + } +}; + +/** + * The negation of this value. + * + * @return {Long} the negation of this value. + * @api public + */ +Long.prototype.negate = function() { + if (this.equals(Long.MIN_VALUE)) { + return Long.MIN_VALUE; + } else { + return this.not().add(Long.ONE); + } +}; + +/** + * Returns the sum of this and the given Long. + * + * @param {Long} other Long to add to this one. + * @return {Long} the sum of this and the given Long. + * @api public + */ +Long.prototype.add = function(other) { + // Divide each number into 4 chunks of 16 bits, and then sum the chunks. + + var a48 = this.high_ >>> 16; + var a32 = this.high_ & 0xFFFF; + var a16 = this.low_ >>> 16; + var a00 = this.low_ & 0xFFFF; + + var b48 = other.high_ >>> 16; + var b32 = other.high_ & 0xFFFF; + var b16 = other.low_ >>> 16; + var b00 = other.low_ & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 + b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 + b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 + b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 + b48; + c48 &= 0xFFFF; + return Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32); +}; + +/** + * Returns the difference of this and the given Long. + * + * @param {Long} other Long to subtract from this. + * @return {Long} the difference of this and the given Long. + * @api public + */ +Long.prototype.subtract = function(other) { + return this.add(other.negate()); +}; + +/** + * Returns the product of this and the given Long. + * + * @param {Long} other Long to multiply with this. + * @return {Long} the product of this and the other. + * @api public + */ +Long.prototype.multiply = function(other) { + if (this.isZero()) { + return Long.ZERO; + } else if (other.isZero()) { + return Long.ZERO; + } + + if (this.equals(Long.MIN_VALUE)) { + return other.isOdd() ? Long.MIN_VALUE : Long.ZERO; + } else if (other.equals(Long.MIN_VALUE)) { + return this.isOdd() ? Long.MIN_VALUE : Long.ZERO; + } + + if (this.isNegative()) { + if (other.isNegative()) { + return this.negate().multiply(other.negate()); + } else { + return this.negate().multiply(other).negate(); + } + } else if (other.isNegative()) { + return this.multiply(other.negate()).negate(); + } + + // If both Longs are small, use float multiplication + if (this.lessThan(Long.TWO_PWR_24_) && + other.lessThan(Long.TWO_PWR_24_)) { + return Long.fromNumber(this.toNumber() * other.toNumber()); + } + + // Divide each Long into 4 chunks of 16 bits, and then add up 4x4 products. + // We can skip products that would overflow. + + var a48 = this.high_ >>> 16; + var a32 = this.high_ & 0xFFFF; + var a16 = this.low_ >>> 16; + var a00 = this.low_ & 0xFFFF; + + var b48 = other.high_ >>> 16; + var b32 = other.high_ & 0xFFFF; + var b16 = other.low_ >>> 16; + var b00 = other.low_ & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 * b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 * b00; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c16 += a00 * b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 * b00; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a16 * b16; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a00 * b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48; + c48 &= 0xFFFF; + return Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32); +}; + +/** + * Returns this Long divided by the given one. + * + * @param {Long} other Long by which to divide. + * @return {Long} this Long divided by the given one. + * @api public + */ +Long.prototype.div = function(other) { + if (other.isZero()) { + throw Error('division by zero'); + } else if (this.isZero()) { + return Long.ZERO; + } + + if (this.equals(Long.MIN_VALUE)) { + if (other.equals(Long.ONE) || + other.equals(Long.NEG_ONE)) { + return Long.MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE + } else if (other.equals(Long.MIN_VALUE)) { + return Long.ONE; + } else { + // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|. + var halfThis = this.shiftRight(1); + var approx = halfThis.div(other).shiftLeft(1); + if (approx.equals(Long.ZERO)) { + return other.isNegative() ? Long.ONE : Long.NEG_ONE; + } else { + var rem = this.subtract(other.multiply(approx)); + var result = approx.add(rem.div(other)); + return result; + } + } + } else if (other.equals(Long.MIN_VALUE)) { + return Long.ZERO; + } + + if (this.isNegative()) { + if (other.isNegative()) { + return this.negate().div(other.negate()); + } else { + return this.negate().div(other).negate(); + } + } else if (other.isNegative()) { + return this.div(other.negate()).negate(); + } + + // Repeat the following until the remainder is less than other: find a + // floating-point that approximates remainder / other *from below*, add this + // into the result, and subtract it from the remainder. It is critical that + // the approximate value is less than or equal to the real value so that the + // remainder never becomes negative. + var res = Long.ZERO; + var rem = this; + while (rem.greaterThanOrEqual(other)) { + // Approximate the result of division. This may be a little greater or + // smaller than the actual value. + var approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber())); + + // We will tweak the approximate result by changing it in the 48-th digit or + // the smallest non-fractional digit, whichever is larger. + var log2 = Math.ceil(Math.log(approx) / Math.LN2); + var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48); + + // Decrease the approximation until it is smaller than the remainder. Note + // that if it is too large, the product overflows and is negative. + var approxRes = Long.fromNumber(approx); + var approxRem = approxRes.multiply(other); + while (approxRem.isNegative() || approxRem.greaterThan(rem)) { + approx -= delta; + approxRes = Long.fromNumber(approx); + approxRem = approxRes.multiply(other); + } + + // We know the answer can't be zero... and actually, zero would cause + // infinite recursion since we would make no progress. + if (approxRes.isZero()) { + approxRes = Long.ONE; + } + + res = res.add(approxRes); + rem = rem.subtract(approxRem); + } + return res; +}; + +/** + * Returns this Long modulo the given one. + * + * @param {Long} other Long by which to mod. + * @return {Long} this Long modulo the given one. + * @api public + */ +Long.prototype.modulo = function(other) { + return this.subtract(this.div(other).multiply(other)); +}; + +/** + * The bitwise-NOT of this value. + * + * @return {Long} the bitwise-NOT of this value. + * @api public + */ +Long.prototype.not = function() { + return Long.fromBits(~this.low_, ~this.high_); +}; + +/** + * Returns the bitwise-AND of this Long and the given one. + * + * @param {Long} other the Long with which to AND. + * @return {Long} the bitwise-AND of this and the other. + * @api public + */ +Long.prototype.and = function(other) { + return Long.fromBits(this.low_ & other.low_, this.high_ & other.high_); +}; + +/** + * Returns the bitwise-OR of this Long and the given one. + * + * @param {Long} other the Long with which to OR. + * @return {Long} the bitwise-OR of this and the other. + * @api public + */ +Long.prototype.or = function(other) { + return Long.fromBits(this.low_ | other.low_, this.high_ | other.high_); +}; + +/** + * Returns the bitwise-XOR of this Long and the given one. + * + * @param {Long} other the Long with which to XOR. + * @return {Long} the bitwise-XOR of this and the other. + * @api public + */ +Long.prototype.xor = function(other) { + return Long.fromBits(this.low_ ^ other.low_, this.high_ ^ other.high_); +}; + +/** + * Returns this Long with bits shifted to the left by the given amount. + * + * @param {Number} numBits the number of bits by which to shift. + * @return {Long} this shifted to the left by the given amount. + * @api public + */ +Long.prototype.shiftLeft = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var low = this.low_; + if (numBits < 32) { + var high = this.high_; + return Long.fromBits( + low << numBits, + (high << numBits) | (low >>> (32 - numBits))); + } else { + return Long.fromBits(0, low << (numBits - 32)); + } + } +}; + +/** + * Returns this Long with bits shifted to the right by the given amount. + * + * @param {Number} numBits the number of bits by which to shift. + * @return {Long} this shifted to the right by the given amount. + * @api public + */ +Long.prototype.shiftRight = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var high = this.high_; + if (numBits < 32) { + var low = this.low_; + return Long.fromBits( + (low >>> numBits) | (high << (32 - numBits)), + high >> numBits); + } else { + return Long.fromBits( + high >> (numBits - 32), + high >= 0 ? 0 : -1); + } + } +}; + +/** + * Returns this Long with bits shifted to the right by the given amount, with the new top bits matching the current sign bit. + * + * @param {Number} numBits the number of bits by which to shift. + * @return {Long} this shifted to the right by the given amount, with zeros placed into the new leading bits. + * @api public + */ +Long.prototype.shiftRightUnsigned = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var high = this.high_; + if (numBits < 32) { + var low = this.low_; + return Long.fromBits( + (low >>> numBits) | (high << (32 - numBits)), + high >>> numBits); + } else if (numBits == 32) { + return Long.fromBits(high, 0); + } else { + return Long.fromBits(high >>> (numBits - 32), 0); + } + } +}; + +/** + * Returns a Long representing the given (32-bit) integer value. + * + * @param {Number} value the 32-bit integer in question. + * @return {Long} the corresponding Long value. + * @api public + */ +Long.fromInt = function(value) { + if (-128 <= value && value < 128) { + var cachedObj = Long.INT_CACHE_[value]; + if (cachedObj) { + return cachedObj; + } + } + + var obj = new Long(value | 0, value < 0 ? -1 : 0); + if (-128 <= value && value < 128) { + Long.INT_CACHE_[value] = obj; + } + return obj; +}; + +/** + * Returns a Long representing the given value, provided that it is a finite number. Otherwise, zero is returned. + * + * @param {Number} value the number in question. + * @return {Long} the corresponding Long value. + * @api public + */ +Long.fromNumber = function(value) { + if (isNaN(value) || !isFinite(value)) { + return Long.ZERO; + } else if (value <= -Long.TWO_PWR_63_DBL_) { + return Long.MIN_VALUE; + } else if (value + 1 >= Long.TWO_PWR_63_DBL_) { + return Long.MAX_VALUE; + } else if (value < 0) { + return Long.fromNumber(-value).negate(); + } else { + return new Long( + (value % Long.TWO_PWR_32_DBL_) | 0, + (value / Long.TWO_PWR_32_DBL_) | 0); + } +}; + +/** + * Returns a Long representing the 64-bit integer that comes by concatenating the given high and low bits. Each is assumed to use 32 bits. + * + * @param {Number} lowBits the low 32-bits. + * @param {Number} highBits the high 32-bits. + * @return {Long} the corresponding Long value. + * @api public + */ +Long.fromBits = function(lowBits, highBits) { + return new Long(lowBits, highBits); +}; + +/** + * Returns a Long representation of the given string, written using the given radix. + * + * @param {String} str the textual representation of the Long. + * @param {Number} opt_radix the radix in which the text is written. + * @return {Long} the corresponding Long value. + * @api public + */ +Long.fromString = function(str, opt_radix) { + if (str.length == 0) { + throw Error('number format error: empty string'); + } + + var radix = opt_radix || 10; + if (radix < 2 || 36 < radix) { + throw Error('radix out of range: ' + radix); + } + + if (str.charAt(0) == '-') { + return Long.fromString(str.substring(1), radix).negate(); + } else if (str.indexOf('-') >= 0) { + throw Error('number format error: interior "-" character: ' + str); + } + + // Do several (8) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = Long.fromNumber(Math.pow(radix, 8)); + + var result = Long.ZERO; + for (var i = 0; i < str.length; i += 8) { + var size = Math.min(8, str.length - i); + var value = parseInt(str.substring(i, i + size), radix); + if (size < 8) { + var power = Long.fromNumber(Math.pow(radix, size)); + result = result.multiply(power).add(Long.fromNumber(value)); + } else { + result = result.multiply(radixToPower); + result = result.add(Long.fromNumber(value)); + } + } + return result; +}; + +// NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the +// from* methods on which they depend. + + +/** + * A cache of the Long representations of small integer values. + * @type {Object} + * @api private + */ +Long.INT_CACHE_ = {}; + +// NOTE: the compiler should inline these constant values below and then remove +// these variables, so there should be no runtime penalty for these. + +/** + * Number used repeated below in calculations. This must appear before the + * first call to any from* function below. + * @type {number} + * @api private + */ +Long.TWO_PWR_16_DBL_ = 1 << 16; + +/** + * @type {number} + * @api private + */ +Long.TWO_PWR_24_DBL_ = 1 << 24; + +/** + * @type {number} + * @api private + */ +Long.TWO_PWR_32_DBL_ = Long.TWO_PWR_16_DBL_ * Long.TWO_PWR_16_DBL_; + +/** + * @type {number} + * @api private + */ +Long.TWO_PWR_31_DBL_ = Long.TWO_PWR_32_DBL_ / 2; + +/** + * @type {number} + * @api private + */ +Long.TWO_PWR_48_DBL_ = Long.TWO_PWR_32_DBL_ * Long.TWO_PWR_16_DBL_; + +/** + * @type {number} + * @api private + */ +Long.TWO_PWR_64_DBL_ = Long.TWO_PWR_32_DBL_ * Long.TWO_PWR_32_DBL_; + +/** + * @type {number} + * @api private + */ +Long.TWO_PWR_63_DBL_ = Long.TWO_PWR_64_DBL_ / 2; + +/** @type {Long} */ +Long.ZERO = Long.fromInt(0); + +/** @type {Long} */ +Long.ONE = Long.fromInt(1); + +/** @type {Long} */ +Long.NEG_ONE = Long.fromInt(-1); + +/** @type {Long} */ +Long.MAX_VALUE = + Long.fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0); + +/** @type {Long} */ +Long.MIN_VALUE = Long.fromBits(0, 0x80000000 | 0); + +/** + * @type {Long} + * @api private + */ +Long.TWO_PWR_24_ = Long.fromInt(1 << 24); + +/** + * Expose. + */ +exports.Long = Long; +}, + + + +'max_key': function(module, exports, global, require, undefined){ + /** + * A class representation of the BSON MaxKey type. + * + * @class Represents the BSON MaxKey type. + * @return {MaxKey} + */ +function MaxKey() { + if(!(this instanceof MaxKey)) return new MaxKey(); + + this._bsontype = 'MaxKey'; +} + +exports.MaxKey = MaxKey; +}, + + + +'min_key': function(module, exports, global, require, undefined){ + /** + * A class representation of the BSON MinKey type. + * + * @class Represents the BSON MinKey type. + * @return {MinKey} + */ +function MinKey() { + if(!(this instanceof MinKey)) return new MinKey(); + + this._bsontype = 'MinKey'; +} + +exports.MinKey = MinKey; +}, + + + +'objectid': function(module, exports, global, require, undefined){ + /** + * Module dependencies. + */ +var BinaryParser = require('./binary_parser').BinaryParser; + +/** + * Machine id. + * + * Create a random 3-byte value (i.e. unique for this + * process). Other drivers use a md5 of the machine id here, but + * that would mean an asyc call to gethostname, so we don't bother. + */ +var MACHINE_ID = parseInt(Math.random() * 0xFFFFFF, 10); + +// Regular expression that checks for hex value +var checkForHexRegExp = new RegExp("^[0-9a-fA-F]{24}$"); + +/** +* Create a new ObjectID instance +* +* @class Represents the BSON ObjectID type +* @param {String|Number} id Can be a 24 byte hex string, 12 byte binary string or a Number. +* @return {Object} instance of ObjectID. +*/ +var ObjectID = function ObjectID(id, _hex) { + if(!(this instanceof ObjectID)) return new ObjectID(id, _hex); + + this._bsontype = 'ObjectID'; + var __id = null; + + // Throw an error if it's not a valid setup + if(id != null && 'number' != typeof id && (id.length != 12 && id.length != 24)) + throw new Error("Argument passed in must be a single String of 12 bytes or a string of 24 hex characters"); + + // Generate id based on the input + if(id == null || typeof id == 'number') { + // convert to 12 byte binary string + this.id = this.generate(id); + } else if(id != null && id.length === 12) { + // assume 12 byte string + this.id = id; + } else if(checkForHexRegExp.test(id)) { + return ObjectID.createFromHexString(id); + } else { + throw new Error("Value passed in is not a valid 24 character hex string"); + } + + if(ObjectID.cacheHexString) this.__id = this.toHexString(); +}; + +// Allow usage of ObjectId as well as ObjectID +var ObjectId = ObjectID; + +// Precomputed hex table enables speedy hex string conversion +var hexTable = []; +for (var i = 0; i < 256; i++) { + hexTable[i] = (i <= 15 ? '0' : '') + i.toString(16); +} + +/** +* Return the ObjectID id as a 24 byte hex string representation +* +* @return {String} return the 24 byte hex string representation. +* @api public +*/ +ObjectID.prototype.toHexString = function() { + if(ObjectID.cacheHexString && this.__id) return this.__id; + + var hexString = ''; + + for (var i = 0; i < this.id.length; i++) { + hexString += hexTable[this.id.charCodeAt(i)]; + } + + if(ObjectID.cacheHexString) this.__id = hexString; + return hexString; +}; + +/** +* Update the ObjectID index used in generating new ObjectID's on the driver +* +* @return {Number} returns next index value. +* @api private +*/ +ObjectID.prototype.get_inc = function() { + return ObjectID.index = (ObjectID.index + 1) % 0xFFFFFF; +}; + +/** +* Update the ObjectID index used in generating new ObjectID's on the driver +* +* @return {Number} returns next index value. +* @api private +*/ +ObjectID.prototype.getInc = function() { + return this.get_inc(); +}; + +/** +* Generate a 12 byte id string used in ObjectID's +* +* @param {Number} [time] optional parameter allowing to pass in a second based timestamp. +* @return {String} return the 12 byte id binary string. +* @api private +*/ +ObjectID.prototype.generate = function(time) { + if ('number' == typeof time) { + var time4Bytes = BinaryParser.encodeInt(time, 32, true, true); + /* for time-based ObjectID the bytes following the time will be zeroed */ + var machine3Bytes = BinaryParser.encodeInt(MACHINE_ID, 24, false); + var pid2Bytes = BinaryParser.fromShort(typeof process === 'undefined' ? Math.floor(Math.random() * 100000) : process.pid); + var index3Bytes = BinaryParser.encodeInt(this.get_inc(), 24, false, true); + } else { + var unixTime = parseInt(Date.now()/1000,10); + var time4Bytes = BinaryParser.encodeInt(unixTime, 32, true, true); + var machine3Bytes = BinaryParser.encodeInt(MACHINE_ID, 24, false); + var pid2Bytes = BinaryParser.fromShort(typeof process === 'undefined' ? Math.floor(Math.random() * 100000) : process.pid); + var index3Bytes = BinaryParser.encodeInt(this.get_inc(), 24, false, true); + } + + return time4Bytes + machine3Bytes + pid2Bytes + index3Bytes; +}; + +/** +* Converts the id into a 24 byte hex string for printing +* +* @return {String} return the 24 byte hex string representation. +* @api private +*/ +ObjectID.prototype.toString = function() { + return this.toHexString(); +}; + +/** +* Converts to a string representation of this Id. +* +* @return {String} return the 24 byte hex string representation. +* @api private +*/ +ObjectID.prototype.inspect = ObjectID.prototype.toString; + +/** +* Converts to its JSON representation. +* +* @return {String} return the 24 byte hex string representation. +* @api private +*/ +ObjectID.prototype.toJSON = function() { + return this.toHexString(); +}; + +/** +* Compares the equality of this ObjectID with `otherID`. +* +* @param {Object} otherID ObjectID instance to compare against. +* @return {Bool} the result of comparing two ObjectID's +* @api public +*/ +ObjectID.prototype.equals = function equals (otherID) { + var id = (otherID instanceof ObjectID || otherID.toHexString) + ? otherID.id + : ObjectID.createFromHexString(otherID).id; + + return this.id === id; +} + +/** +* Returns the generation date (accurate up to the second) that this ID was generated. +* +* @return {Date} the generation date +* @api public +*/ +ObjectID.prototype.getTimestamp = function() { + var timestamp = new Date(); + timestamp.setTime(Math.floor(BinaryParser.decodeInt(this.id.substring(0,4), 32, true, true)) * 1000); + return timestamp; +} + +/** +* @ignore +* @api private +*/ +ObjectID.index = parseInt(Math.random() * 0xFFFFFF, 10); + +ObjectID.createPk = function createPk () { + return new ObjectID(); +}; + +/** +* Creates an ObjectID from a second based number, with the rest of the ObjectID zeroed out. Used for comparisons or sorting the ObjectID. +* +* @param {Number} time an integer number representing a number of seconds. +* @return {ObjectID} return the created ObjectID +* @api public +*/ +ObjectID.createFromTime = function createFromTime (time) { + var id = BinaryParser.encodeInt(time, 32, true, true) + + BinaryParser.encodeInt(0, 64, true, true); + return new ObjectID(id); +}; + +/** +* Creates an ObjectID from a hex string representation of an ObjectID. +* +* @param {String} hexString create a ObjectID from a passed in 24 byte hexstring. +* @return {ObjectID} return the created ObjectID +* @api public +*/ +ObjectID.createFromHexString = function createFromHexString (hexString) { + // Throw an error if it's not a valid setup + if(typeof hexString === 'undefined' || hexString != null && hexString.length != 24) + throw new Error("Argument passed in must be a single String of 12 bytes or a string of 24 hex characters"); + + var len = hexString.length; + + if(len > 12*2) { + throw new Error('Id cannot be longer than 12 bytes'); + } + + var result = '' + , string + , number; + + for (var index = 0; index < len; index += 2) { + string = hexString.substr(index, 2); + number = parseInt(string, 16); + result += BinaryParser.fromByte(number); + } + + return new ObjectID(result, hexString); +}; + +/** +* @ignore +*/ +Object.defineProperty(ObjectID.prototype, "generationTime", { + enumerable: true + , get: function () { + return Math.floor(BinaryParser.decodeInt(this.id.substring(0,4), 32, true, true)); + } + , set: function (value) { + var value = BinaryParser.encodeInt(value, 32, true, true); + this.id = value + this.id.substr(4); + // delete this.__id; + this.toHexString(); + } +}); + +/** + * Expose. + */ +exports.ObjectID = ObjectID; +exports.ObjectId = ObjectID; + +}, + + + +'symbol': function(module, exports, global, require, undefined){ + /** + * A class representation of the BSON Symbol type. + * + * @class Represents the BSON Symbol type. + * @param {String} value the string representing the symbol. + * @return {Symbol} + */ +function Symbol(value) { + if(!(this instanceof Symbol)) return new Symbol(value); + this._bsontype = 'Symbol'; + this.value = value; +} + +/** + * Access the wrapped string value. + * + * @return {String} returns the wrapped string. + * @api public + */ +Symbol.prototype.valueOf = function() { + return this.value; +}; + +/** + * @ignore + * @api private + */ +Symbol.prototype.toString = function() { + return this.value; +} + +/** + * @ignore + * @api private + */ +Symbol.prototype.inspect = function() { + return this.value; +} + +/** + * @ignore + * @api private + */ +Symbol.prototype.toJSON = function() { + return this.value; +} + +exports.Symbol = Symbol; +}, + + + +'timestamp': function(module, exports, global, require, undefined){ + // Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Copyright 2009 Google Inc. All Rights Reserved + +/** + * Defines a Timestamp class for representing a 64-bit two's-complement + * integer value, which faithfully simulates the behavior of a Java "Timestamp". This + * implementation is derived from TimestampLib in GWT. + * + * Constructs a 64-bit two's-complement integer, given its low and high 32-bit + * values as *signed* integers. See the from* functions below for more + * convenient ways of constructing Timestamps. + * + * The internal representation of a Timestamp is the two given signed, 32-bit values. + * We use 32-bit pieces because these are the size of integers on which + * Javascript performs bit-operations. For operations like addition and + * multiplication, we split each number into 16-bit pieces, which can easily be + * multiplied within Javascript's floating-point representation without overflow + * or change in sign. + * + * In the algorithms below, we frequently reduce the negative case to the + * positive case by negating the input(s) and then post-processing the result. + * Note that we must ALWAYS check specially whether those values are MIN_VALUE + * (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as + * a positive number, it overflows back into a negative). Not handling this + * case would often result in infinite recursion. + * + * @class Represents the BSON Timestamp type. + * @param {Number} low the low (signed) 32 bits of the Timestamp. + * @param {Number} high the high (signed) 32 bits of the Timestamp. + */ +function Timestamp(low, high) { + if(!(this instanceof Timestamp)) return new Timestamp(low, high); + this._bsontype = 'Timestamp'; + /** + * @type {number} + * @api private + */ + this.low_ = low | 0; // force into 32 signed bits. + + /** + * @type {number} + * @api private + */ + this.high_ = high | 0; // force into 32 signed bits. +}; + +/** + * Return the int value. + * + * @return {Number} the value, assuming it is a 32-bit integer. + * @api public + */ +Timestamp.prototype.toInt = function() { + return this.low_; +}; + +/** + * Return the Number value. + * + * @return {Number} the closest floating-point representation to this value. + * @api public + */ +Timestamp.prototype.toNumber = function() { + return this.high_ * Timestamp.TWO_PWR_32_DBL_ + + this.getLowBitsUnsigned(); +}; + +/** + * Return the JSON value. + * + * @return {String} the JSON representation. + * @api public + */ +Timestamp.prototype.toJSON = function() { + return this.toString(); +} + +/** + * Return the String value. + * + * @param {Number} [opt_radix] the radix in which the text should be written. + * @return {String} the textual representation of this value. + * @api public + */ +Timestamp.prototype.toString = function(opt_radix) { + var radix = opt_radix || 10; + if (radix < 2 || 36 < radix) { + throw Error('radix out of range: ' + radix); + } + + if (this.isZero()) { + return '0'; + } + + if (this.isNegative()) { + if (this.equals(Timestamp.MIN_VALUE)) { + // We need to change the Timestamp value before it can be negated, so we remove + // the bottom-most digit in this base and then recurse to do the rest. + var radixTimestamp = Timestamp.fromNumber(radix); + var div = this.div(radixTimestamp); + var rem = div.multiply(radixTimestamp).subtract(this); + return div.toString(radix) + rem.toInt().toString(radix); + } else { + return '-' + this.negate().toString(radix); + } + } + + // Do several (6) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = Timestamp.fromNumber(Math.pow(radix, 6)); + + var rem = this; + var result = ''; + while (true) { + var remDiv = rem.div(radixToPower); + var intval = rem.subtract(remDiv.multiply(radixToPower)).toInt(); + var digits = intval.toString(radix); + + rem = remDiv; + if (rem.isZero()) { + return digits + result; + } else { + while (digits.length < 6) { + digits = '0' + digits; + } + result = '' + digits + result; + } + } +}; + +/** + * Return the high 32-bits value. + * + * @return {Number} the high 32-bits as a signed value. + * @api public + */ +Timestamp.prototype.getHighBits = function() { + return this.high_; +}; + +/** + * Return the low 32-bits value. + * + * @return {Number} the low 32-bits as a signed value. + * @api public + */ +Timestamp.prototype.getLowBits = function() { + return this.low_; +}; + +/** + * Return the low unsigned 32-bits value. + * + * @return {Number} the low 32-bits as an unsigned value. + * @api public + */ +Timestamp.prototype.getLowBitsUnsigned = function() { + return (this.low_ >= 0) ? + this.low_ : Timestamp.TWO_PWR_32_DBL_ + this.low_; +}; + +/** + * Returns the number of bits needed to represent the absolute value of this Timestamp. + * + * @return {Number} Returns the number of bits needed to represent the absolute value of this Timestamp. + * @api public + */ +Timestamp.prototype.getNumBitsAbs = function() { + if (this.isNegative()) { + if (this.equals(Timestamp.MIN_VALUE)) { + return 64; + } else { + return this.negate().getNumBitsAbs(); + } + } else { + var val = this.high_ != 0 ? this.high_ : this.low_; + for (var bit = 31; bit > 0; bit--) { + if ((val & (1 << bit)) != 0) { + break; + } + } + return this.high_ != 0 ? bit + 33 : bit + 1; + } +}; + +/** + * Return whether this value is zero. + * + * @return {Boolean} whether this value is zero. + * @api public + */ +Timestamp.prototype.isZero = function() { + return this.high_ == 0 && this.low_ == 0; +}; + +/** + * Return whether this value is negative. + * + * @return {Boolean} whether this value is negative. + * @api public + */ +Timestamp.prototype.isNegative = function() { + return this.high_ < 0; +}; + +/** + * Return whether this value is odd. + * + * @return {Boolean} whether this value is odd. + * @api public + */ +Timestamp.prototype.isOdd = function() { + return (this.low_ & 1) == 1; +}; + +/** + * Return whether this Timestamp equals the other + * + * @param {Timestamp} other Timestamp to compare against. + * @return {Boolean} whether this Timestamp equals the other + * @api public + */ +Timestamp.prototype.equals = function(other) { + return (this.high_ == other.high_) && (this.low_ == other.low_); +}; + +/** + * Return whether this Timestamp does not equal the other. + * + * @param {Timestamp} other Timestamp to compare against. + * @return {Boolean} whether this Timestamp does not equal the other. + * @api public + */ +Timestamp.prototype.notEquals = function(other) { + return (this.high_ != other.high_) || (this.low_ != other.low_); +}; + +/** + * Return whether this Timestamp is less than the other. + * + * @param {Timestamp} other Timestamp to compare against. + * @return {Boolean} whether this Timestamp is less than the other. + * @api public + */ +Timestamp.prototype.lessThan = function(other) { + return this.compare(other) < 0; +}; + +/** + * Return whether this Timestamp is less than or equal to the other. + * + * @param {Timestamp} other Timestamp to compare against. + * @return {Boolean} whether this Timestamp is less than or equal to the other. + * @api public + */ +Timestamp.prototype.lessThanOrEqual = function(other) { + return this.compare(other) <= 0; +}; + +/** + * Return whether this Timestamp is greater than the other. + * + * @param {Timestamp} other Timestamp to compare against. + * @return {Boolean} whether this Timestamp is greater than the other. + * @api public + */ +Timestamp.prototype.greaterThan = function(other) { + return this.compare(other) > 0; +}; + +/** + * Return whether this Timestamp is greater than or equal to the other. + * + * @param {Timestamp} other Timestamp to compare against. + * @return {Boolean} whether this Timestamp is greater than or equal to the other. + * @api public + */ +Timestamp.prototype.greaterThanOrEqual = function(other) { + return this.compare(other) >= 0; +}; + +/** + * Compares this Timestamp with the given one. + * + * @param {Timestamp} other Timestamp to compare against. + * @return {Boolean} 0 if they are the same, 1 if the this is greater, and -1 if the given one is greater. + * @api public + */ +Timestamp.prototype.compare = function(other) { + if (this.equals(other)) { + return 0; + } + + var thisNeg = this.isNegative(); + var otherNeg = other.isNegative(); + if (thisNeg && !otherNeg) { + return -1; + } + if (!thisNeg && otherNeg) { + return 1; + } + + // at this point, the signs are the same, so subtraction will not overflow + if (this.subtract(other).isNegative()) { + return -1; + } else { + return 1; + } +}; + +/** + * The negation of this value. + * + * @return {Timestamp} the negation of this value. + * @api public + */ +Timestamp.prototype.negate = function() { + if (this.equals(Timestamp.MIN_VALUE)) { + return Timestamp.MIN_VALUE; + } else { + return this.not().add(Timestamp.ONE); + } +}; + +/** + * Returns the sum of this and the given Timestamp. + * + * @param {Timestamp} other Timestamp to add to this one. + * @return {Timestamp} the sum of this and the given Timestamp. + * @api public + */ +Timestamp.prototype.add = function(other) { + // Divide each number into 4 chunks of 16 bits, and then sum the chunks. + + var a48 = this.high_ >>> 16; + var a32 = this.high_ & 0xFFFF; + var a16 = this.low_ >>> 16; + var a00 = this.low_ & 0xFFFF; + + var b48 = other.high_ >>> 16; + var b32 = other.high_ & 0xFFFF; + var b16 = other.low_ >>> 16; + var b00 = other.low_ & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 + b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 + b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 + b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 + b48; + c48 &= 0xFFFF; + return Timestamp.fromBits((c16 << 16) | c00, (c48 << 16) | c32); +}; + +/** + * Returns the difference of this and the given Timestamp. + * + * @param {Timestamp} other Timestamp to subtract from this. + * @return {Timestamp} the difference of this and the given Timestamp. + * @api public + */ +Timestamp.prototype.subtract = function(other) { + return this.add(other.negate()); +}; + +/** + * Returns the product of this and the given Timestamp. + * + * @param {Timestamp} other Timestamp to multiply with this. + * @return {Timestamp} the product of this and the other. + * @api public + */ +Timestamp.prototype.multiply = function(other) { + if (this.isZero()) { + return Timestamp.ZERO; + } else if (other.isZero()) { + return Timestamp.ZERO; + } + + if (this.equals(Timestamp.MIN_VALUE)) { + return other.isOdd() ? Timestamp.MIN_VALUE : Timestamp.ZERO; + } else if (other.equals(Timestamp.MIN_VALUE)) { + return this.isOdd() ? Timestamp.MIN_VALUE : Timestamp.ZERO; + } + + if (this.isNegative()) { + if (other.isNegative()) { + return this.negate().multiply(other.negate()); + } else { + return this.negate().multiply(other).negate(); + } + } else if (other.isNegative()) { + return this.multiply(other.negate()).negate(); + } + + // If both Timestamps are small, use float multiplication + if (this.lessThan(Timestamp.TWO_PWR_24_) && + other.lessThan(Timestamp.TWO_PWR_24_)) { + return Timestamp.fromNumber(this.toNumber() * other.toNumber()); + } + + // Divide each Timestamp into 4 chunks of 16 bits, and then add up 4x4 products. + // We can skip products that would overflow. + + var a48 = this.high_ >>> 16; + var a32 = this.high_ & 0xFFFF; + var a16 = this.low_ >>> 16; + var a00 = this.low_ & 0xFFFF; + + var b48 = other.high_ >>> 16; + var b32 = other.high_ & 0xFFFF; + var b16 = other.low_ >>> 16; + var b00 = other.low_ & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 * b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 * b00; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c16 += a00 * b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 * b00; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a16 * b16; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a00 * b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48; + c48 &= 0xFFFF; + return Timestamp.fromBits((c16 << 16) | c00, (c48 << 16) | c32); +}; + +/** + * Returns this Timestamp divided by the given one. + * + * @param {Timestamp} other Timestamp by which to divide. + * @return {Timestamp} this Timestamp divided by the given one. + * @api public + */ +Timestamp.prototype.div = function(other) { + if (other.isZero()) { + throw Error('division by zero'); + } else if (this.isZero()) { + return Timestamp.ZERO; + } + + if (this.equals(Timestamp.MIN_VALUE)) { + if (other.equals(Timestamp.ONE) || + other.equals(Timestamp.NEG_ONE)) { + return Timestamp.MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE + } else if (other.equals(Timestamp.MIN_VALUE)) { + return Timestamp.ONE; + } else { + // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|. + var halfThis = this.shiftRight(1); + var approx = halfThis.div(other).shiftLeft(1); + if (approx.equals(Timestamp.ZERO)) { + return other.isNegative() ? Timestamp.ONE : Timestamp.NEG_ONE; + } else { + var rem = this.subtract(other.multiply(approx)); + var result = approx.add(rem.div(other)); + return result; + } + } + } else if (other.equals(Timestamp.MIN_VALUE)) { + return Timestamp.ZERO; + } + + if (this.isNegative()) { + if (other.isNegative()) { + return this.negate().div(other.negate()); + } else { + return this.negate().div(other).negate(); + } + } else if (other.isNegative()) { + return this.div(other.negate()).negate(); + } + + // Repeat the following until the remainder is less than other: find a + // floating-point that approximates remainder / other *from below*, add this + // into the result, and subtract it from the remainder. It is critical that + // the approximate value is less than or equal to the real value so that the + // remainder never becomes negative. + var res = Timestamp.ZERO; + var rem = this; + while (rem.greaterThanOrEqual(other)) { + // Approximate the result of division. This may be a little greater or + // smaller than the actual value. + var approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber())); + + // We will tweak the approximate result by changing it in the 48-th digit or + // the smallest non-fractional digit, whichever is larger. + var log2 = Math.ceil(Math.log(approx) / Math.LN2); + var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48); + + // Decrease the approximation until it is smaller than the remainder. Note + // that if it is too large, the product overflows and is negative. + var approxRes = Timestamp.fromNumber(approx); + var approxRem = approxRes.multiply(other); + while (approxRem.isNegative() || approxRem.greaterThan(rem)) { + approx -= delta; + approxRes = Timestamp.fromNumber(approx); + approxRem = approxRes.multiply(other); + } + + // We know the answer can't be zero... and actually, zero would cause + // infinite recursion since we would make no progress. + if (approxRes.isZero()) { + approxRes = Timestamp.ONE; + } + + res = res.add(approxRes); + rem = rem.subtract(approxRem); + } + return res; +}; + +/** + * Returns this Timestamp modulo the given one. + * + * @param {Timestamp} other Timestamp by which to mod. + * @return {Timestamp} this Timestamp modulo the given one. + * @api public + */ +Timestamp.prototype.modulo = function(other) { + return this.subtract(this.div(other).multiply(other)); +}; + +/** + * The bitwise-NOT of this value. + * + * @return {Timestamp} the bitwise-NOT of this value. + * @api public + */ +Timestamp.prototype.not = function() { + return Timestamp.fromBits(~this.low_, ~this.high_); +}; + +/** + * Returns the bitwise-AND of this Timestamp and the given one. + * + * @param {Timestamp} other the Timestamp with which to AND. + * @return {Timestamp} the bitwise-AND of this and the other. + * @api public + */ +Timestamp.prototype.and = function(other) { + return Timestamp.fromBits(this.low_ & other.low_, this.high_ & other.high_); +}; + +/** + * Returns the bitwise-OR of this Timestamp and the given one. + * + * @param {Timestamp} other the Timestamp with which to OR. + * @return {Timestamp} the bitwise-OR of this and the other. + * @api public + */ +Timestamp.prototype.or = function(other) { + return Timestamp.fromBits(this.low_ | other.low_, this.high_ | other.high_); +}; + +/** + * Returns the bitwise-XOR of this Timestamp and the given one. + * + * @param {Timestamp} other the Timestamp with which to XOR. + * @return {Timestamp} the bitwise-XOR of this and the other. + * @api public + */ +Timestamp.prototype.xor = function(other) { + return Timestamp.fromBits(this.low_ ^ other.low_, this.high_ ^ other.high_); +}; + +/** + * Returns this Timestamp with bits shifted to the left by the given amount. + * + * @param {Number} numBits the number of bits by which to shift. + * @return {Timestamp} this shifted to the left by the given amount. + * @api public + */ +Timestamp.prototype.shiftLeft = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var low = this.low_; + if (numBits < 32) { + var high = this.high_; + return Timestamp.fromBits( + low << numBits, + (high << numBits) | (low >>> (32 - numBits))); + } else { + return Timestamp.fromBits(0, low << (numBits - 32)); + } + } +}; + +/** + * Returns this Timestamp with bits shifted to the right by the given amount. + * + * @param {Number} numBits the number of bits by which to shift. + * @return {Timestamp} this shifted to the right by the given amount. + * @api public + */ +Timestamp.prototype.shiftRight = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var high = this.high_; + if (numBits < 32) { + var low = this.low_; + return Timestamp.fromBits( + (low >>> numBits) | (high << (32 - numBits)), + high >> numBits); + } else { + return Timestamp.fromBits( + high >> (numBits - 32), + high >= 0 ? 0 : -1); + } + } +}; + +/** + * Returns this Timestamp with bits shifted to the right by the given amount, with the new top bits matching the current sign bit. + * + * @param {Number} numBits the number of bits by which to shift. + * @return {Timestamp} this shifted to the right by the given amount, with zeros placed into the new leading bits. + * @api public + */ +Timestamp.prototype.shiftRightUnsigned = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var high = this.high_; + if (numBits < 32) { + var low = this.low_; + return Timestamp.fromBits( + (low >>> numBits) | (high << (32 - numBits)), + high >>> numBits); + } else if (numBits == 32) { + return Timestamp.fromBits(high, 0); + } else { + return Timestamp.fromBits(high >>> (numBits - 32), 0); + } + } +}; + +/** + * Returns a Timestamp representing the given (32-bit) integer value. + * + * @param {Number} value the 32-bit integer in question. + * @return {Timestamp} the corresponding Timestamp value. + * @api public + */ +Timestamp.fromInt = function(value) { + if (-128 <= value && value < 128) { + var cachedObj = Timestamp.INT_CACHE_[value]; + if (cachedObj) { + return cachedObj; + } + } + + var obj = new Timestamp(value | 0, value < 0 ? -1 : 0); + if (-128 <= value && value < 128) { + Timestamp.INT_CACHE_[value] = obj; + } + return obj; +}; + +/** + * Returns a Timestamp representing the given value, provided that it is a finite number. Otherwise, zero is returned. + * + * @param {Number} value the number in question. + * @return {Timestamp} the corresponding Timestamp value. + * @api public + */ +Timestamp.fromNumber = function(value) { + if (isNaN(value) || !isFinite(value)) { + return Timestamp.ZERO; + } else if (value <= -Timestamp.TWO_PWR_63_DBL_) { + return Timestamp.MIN_VALUE; + } else if (value + 1 >= Timestamp.TWO_PWR_63_DBL_) { + return Timestamp.MAX_VALUE; + } else if (value < 0) { + return Timestamp.fromNumber(-value).negate(); + } else { + return new Timestamp( + (value % Timestamp.TWO_PWR_32_DBL_) | 0, + (value / Timestamp.TWO_PWR_32_DBL_) | 0); + } +}; + +/** + * Returns a Timestamp representing the 64-bit integer that comes by concatenating the given high and low bits. Each is assumed to use 32 bits. + * + * @param {Number} lowBits the low 32-bits. + * @param {Number} highBits the high 32-bits. + * @return {Timestamp} the corresponding Timestamp value. + * @api public + */ +Timestamp.fromBits = function(lowBits, highBits) { + return new Timestamp(lowBits, highBits); +}; + +/** + * Returns a Timestamp representation of the given string, written using the given radix. + * + * @param {String} str the textual representation of the Timestamp. + * @param {Number} opt_radix the radix in which the text is written. + * @return {Timestamp} the corresponding Timestamp value. + * @api public + */ +Timestamp.fromString = function(str, opt_radix) { + if (str.length == 0) { + throw Error('number format error: empty string'); + } + + var radix = opt_radix || 10; + if (radix < 2 || 36 < radix) { + throw Error('radix out of range: ' + radix); + } + + if (str.charAt(0) == '-') { + return Timestamp.fromString(str.substring(1), radix).negate(); + } else if (str.indexOf('-') >= 0) { + throw Error('number format error: interior "-" character: ' + str); + } + + // Do several (8) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = Timestamp.fromNumber(Math.pow(radix, 8)); + + var result = Timestamp.ZERO; + for (var i = 0; i < str.length; i += 8) { + var size = Math.min(8, str.length - i); + var value = parseInt(str.substring(i, i + size), radix); + if (size < 8) { + var power = Timestamp.fromNumber(Math.pow(radix, size)); + result = result.multiply(power).add(Timestamp.fromNumber(value)); + } else { + result = result.multiply(radixToPower); + result = result.add(Timestamp.fromNumber(value)); + } + } + return result; +}; + +// NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the +// from* methods on which they depend. + + +/** + * A cache of the Timestamp representations of small integer values. + * @type {Object} + * @api private + */ +Timestamp.INT_CACHE_ = {}; + +// NOTE: the compiler should inline these constant values below and then remove +// these variables, so there should be no runtime penalty for these. + +/** + * Number used repeated below in calculations. This must appear before the + * first call to any from* function below. + * @type {number} + * @api private + */ +Timestamp.TWO_PWR_16_DBL_ = 1 << 16; + +/** + * @type {number} + * @api private + */ +Timestamp.TWO_PWR_24_DBL_ = 1 << 24; + +/** + * @type {number} + * @api private + */ +Timestamp.TWO_PWR_32_DBL_ = Timestamp.TWO_PWR_16_DBL_ * Timestamp.TWO_PWR_16_DBL_; + +/** + * @type {number} + * @api private + */ +Timestamp.TWO_PWR_31_DBL_ = Timestamp.TWO_PWR_32_DBL_ / 2; + +/** + * @type {number} + * @api private + */ +Timestamp.TWO_PWR_48_DBL_ = Timestamp.TWO_PWR_32_DBL_ * Timestamp.TWO_PWR_16_DBL_; + +/** + * @type {number} + * @api private + */ +Timestamp.TWO_PWR_64_DBL_ = Timestamp.TWO_PWR_32_DBL_ * Timestamp.TWO_PWR_32_DBL_; + +/** + * @type {number} + * @api private + */ +Timestamp.TWO_PWR_63_DBL_ = Timestamp.TWO_PWR_64_DBL_ / 2; + +/** @type {Timestamp} */ +Timestamp.ZERO = Timestamp.fromInt(0); + +/** @type {Timestamp} */ +Timestamp.ONE = Timestamp.fromInt(1); + +/** @type {Timestamp} */ +Timestamp.NEG_ONE = Timestamp.fromInt(-1); + +/** @type {Timestamp} */ +Timestamp.MAX_VALUE = + Timestamp.fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0); + +/** @type {Timestamp} */ +Timestamp.MIN_VALUE = Timestamp.fromBits(0, 0x80000000 | 0); + +/** + * @type {Timestamp} + * @api private + */ +Timestamp.TWO_PWR_24_ = Timestamp.fromInt(1 << 24); + +/** + * Expose. + */ +exports.Timestamp = Timestamp; +}, + + }); + + +if(typeof module != 'undefined' && module.exports ){ + module.exports = bson; + + if( !module.parent ){ + bson(); + } +} + +if(typeof window != 'undefined' && typeof require == 'undefined'){ + window.require = bson.require; +} diff --git a/node_modules/mongodb/node_modules/bson/browser_build/package.json b/node_modules/mongodb/node_modules/bson/browser_build/package.json new file mode 100644 index 0000000..3ebb587 --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/browser_build/package.json @@ -0,0 +1,8 @@ +{ "name" : "bson" +, "description" : "A bson parser for node.js and the browser" +, "main": "../lib/bson/bson" +, "directories" : { "lib" : "../lib/bson" } +, "engines" : { "node" : ">=0.6.0" } +, "licenses" : [ { "type" : "Apache License, Version 2.0" + , "url" : "http://www.apache.org/licenses/LICENSE-2.0" } ] +} diff --git a/node_modules/mongodb/node_modules/bson/build/Makefile b/node_modules/mongodb/node_modules/bson/build/Makefile new file mode 100644 index 0000000..a580dc4 --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/build/Makefile @@ -0,0 +1,350 @@ +# We borrow heavily from the kernel build setup, though we are simpler since +# we don't have Kconfig tweaking settings on us. + +# The implicit make rules have it looking for RCS files, among other things. +# We instead explicitly write all the rules we care about. +# It's even quicker (saves ~200ms) to pass -r on the command line. +MAKEFLAGS=-r + +# The source directory tree. +srcdir := .. +abs_srcdir := $(abspath $(srcdir)) + +# The name of the builddir. +builddir_name ?= . + +# The V=1 flag on command line makes us verbosely print command lines. +ifdef V + quiet= +else + quiet=quiet_ +endif + +# Specify BUILDTYPE=Release on the command line for a release build. +BUILDTYPE ?= Release + +# Directory all our build output goes into. +# Note that this must be two directories beneath src/ for unit tests to pass, +# as they reach into the src/ directory for data with relative paths. +builddir ?= $(builddir_name)/$(BUILDTYPE) +abs_builddir := $(abspath $(builddir)) +depsdir := $(builddir)/.deps + +# Object output directory. +obj := $(builddir)/obj +abs_obj := $(abspath $(obj)) + +# We build up a list of every single one of the targets so we can slurp in the +# generated dependency rule Makefiles in one pass. +all_deps := + + + +CC.target ?= $(CC) +CFLAGS.target ?= $(CFLAGS) +CXX.target ?= $(CXX) +CXXFLAGS.target ?= $(CXXFLAGS) +LINK.target ?= $(LINK) +LDFLAGS.target ?= $(LDFLAGS) +AR.target ?= $(AR) + +# C++ apps need to be linked with g++. +# +# Note: flock is used to seralize linking. Linking is a memory-intensive +# process so running parallel links can often lead to thrashing. To disable +# the serialization, override LINK via an envrionment variable as follows: +# +# export LINK=g++ +# +# This will allow make to invoke N linker processes as specified in -jN. +LINK ?= ./gyp-mac-tool flock $(builddir)/linker.lock $(CXX.target) + +# TODO(evan): move all cross-compilation logic to gyp-time so we don't need +# to replicate this environment fallback in make as well. +CC.host ?= gcc +CFLAGS.host ?= +CXX.host ?= g++ +CXXFLAGS.host ?= +LINK.host ?= $(CXX.host) +LDFLAGS.host ?= +AR.host ?= ar + +# Define a dir function that can handle spaces. +# http://www.gnu.org/software/make/manual/make.html#Syntax-of-Functions +# "leading spaces cannot appear in the text of the first argument as written. +# These characters can be put into the argument value by variable substitution." +empty := +space := $(empty) $(empty) + +# http://stackoverflow.com/questions/1189781/using-make-dir-or-notdir-on-a-path-with-spaces +replace_spaces = $(subst $(space),?,$1) +unreplace_spaces = $(subst ?,$(space),$1) +dirx = $(call unreplace_spaces,$(dir $(call replace_spaces,$1))) + +# Flags to make gcc output dependency info. Note that you need to be +# careful here to use the flags that ccache and distcc can understand. +# We write to a dep file on the side first and then rename at the end +# so we can't end up with a broken dep file. +depfile = $(depsdir)/$(call replace_spaces,$@).d +DEPFLAGS = -MMD -MF $(depfile).raw + +# We have to fixup the deps output in a few ways. +# (1) the file output should mention the proper .o file. +# ccache or distcc lose the path to the target, so we convert a rule of +# the form: +# foobar.o: DEP1 DEP2 +# into +# path/to/foobar.o: DEP1 DEP2 +# (2) we want missing files not to cause us to fail to build. +# We want to rewrite +# foobar.o: DEP1 DEP2 \ +# DEP3 +# to +# DEP1: +# DEP2: +# DEP3: +# so if the files are missing, they're just considered phony rules. +# We have to do some pretty insane escaping to get those backslashes +# and dollar signs past make, the shell, and sed at the same time. +# Doesn't work with spaces, but that's fine: .d files have spaces in +# their names replaced with other characters. +define fixup_dep +# The depfile may not exist if the input file didn't have any #includes. +touch $(depfile).raw +# Fixup path as in (1). +sed -e "s|^$(notdir $@)|$@|" $(depfile).raw >> $(depfile) +# Add extra rules as in (2). +# We remove slashes and replace spaces with new lines; +# remove blank lines; +# delete the first line and append a colon to the remaining lines. +sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\ + grep -v '^$$' |\ + sed -e 1d -e 's|$$|:|' \ + >> $(depfile) +rm $(depfile).raw +endef + +# Command definitions: +# - cmd_foo is the actual command to run; +# - quiet_cmd_foo is the brief-output summary of the command. + +quiet_cmd_cc = CC($(TOOLSET)) $@ +cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $< + +quiet_cmd_cxx = CXX($(TOOLSET)) $@ +cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< + +quiet_cmd_objc = CXX($(TOOLSET)) $@ +cmd_objc = $(CC.$(TOOLSET)) $(GYP_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $< + +quiet_cmd_objcxx = CXX($(TOOLSET)) $@ +cmd_objcxx = $(CXX.$(TOOLSET)) $(GYP_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $< + +# Commands for precompiled header files. +quiet_cmd_pch_c = CXX($(TOOLSET)) $@ +cmd_pch_c = $(CC.$(TOOLSET)) $(GYP_PCH_CFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< +quiet_cmd_pch_cc = CXX($(TOOLSET)) $@ +cmd_pch_cc = $(CC.$(TOOLSET)) $(GYP_PCH_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< +quiet_cmd_pch_m = CXX($(TOOLSET)) $@ +cmd_pch_m = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $< +quiet_cmd_pch_mm = CXX($(TOOLSET)) $@ +cmd_pch_mm = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $< + +# gyp-mac-tool is written next to the root Makefile by gyp. +# Use $(4) for the command, since $(2) and $(3) are used as flag by do_cmd +# already. +quiet_cmd_mac_tool = MACTOOL $(4) $< +cmd_mac_tool = ./gyp-mac-tool $(4) $< "$@" + +quiet_cmd_mac_package_framework = PACKAGE FRAMEWORK $@ +cmd_mac_package_framework = ./gyp-mac-tool package-framework "$@" $(4) + +quiet_cmd_infoplist = INFOPLIST $@ +cmd_infoplist = $(CC.$(TOOLSET)) -E -P -Wno-trigraphs -x c $(INFOPLIST_DEFINES) "$<" -o "$@" + +quiet_cmd_touch = TOUCH $@ +cmd_touch = touch $@ + +quiet_cmd_copy = COPY $@ +# send stderr to /dev/null to ignore messages when linking directories. +cmd_copy = rm -rf "$@" && cp -af "$<" "$@" + +quiet_cmd_alink = LIBTOOL-STATIC $@ +cmd_alink = rm -f $@ && ./gyp-mac-tool filter-libtool libtool $(GYP_LIBTOOLFLAGS) -static -o $@ $(filter %.o,$^) + +quiet_cmd_link = LINK($(TOOLSET)) $@ +cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS) + +quiet_cmd_solink = SOLINK($(TOOLSET)) $@ +cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS) + +quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@ +cmd_solink_module = $(LINK.$(TOOLSET)) -bundle $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS) + + +# Define an escape_quotes function to escape single quotes. +# This allows us to handle quotes properly as long as we always use +# use single quotes and escape_quotes. +escape_quotes = $(subst ','\'',$(1)) +# This comment is here just to include a ' to unconfuse syntax highlighting. +# Define an escape_vars function to escape '$' variable syntax. +# This allows us to read/write command lines with shell variables (e.g. +# $LD_LIBRARY_PATH), without triggering make substitution. +escape_vars = $(subst $$,$$$$,$(1)) +# Helper that expands to a shell command to echo a string exactly as it is in +# make. This uses printf instead of echo because printf's behaviour with respect +# to escape sequences is more portable than echo's across different shells +# (e.g., dash, bash). +exact_echo = printf '%s\n' '$(call escape_quotes,$(1))' + +# Helper to compare the command we're about to run against the command +# we logged the last time we ran the command. Produces an empty +# string (false) when the commands match. +# Tricky point: Make has no string-equality test function. +# The kernel uses the following, but it seems like it would have false +# positives, where one string reordered its arguments. +# arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \ +# $(filter-out $(cmd_$@), $(cmd_$(1)))) +# We instead substitute each for the empty string into the other, and +# say they're equal if both substitutions produce the empty string. +# .d files contain ? instead of spaces, take that into account. +command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\ + $(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1)))) + +# Helper that is non-empty when a prerequisite changes. +# Normally make does this implicitly, but we force rules to always run +# so we can check their command lines. +# $? -- new prerequisites +# $| -- order-only dependencies +prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?)) + +# Helper that executes all postbuilds until one fails. +define do_postbuilds + @E=0;\ + for p in $(POSTBUILDS); do\ + eval $$p;\ + E=$$?;\ + if [ $$E -ne 0 ]; then\ + break;\ + fi;\ + done;\ + if [ $$E -ne 0 ]; then\ + rm -rf "$@";\ + exit $$E;\ + fi +endef + +# do_cmd: run a command via the above cmd_foo names, if necessary. +# Should always run for a given target to handle command-line changes. +# Second argument, if non-zero, makes it do asm/C/C++ dependency munging. +# Third argument, if non-zero, makes it do POSTBUILDS processing. +# Note: We intentionally do NOT call dirx for depfile, since it contains ? for +# spaces already and dirx strips the ? characters. +define do_cmd +$(if $(or $(command_changed),$(prereq_changed)), + @$(call exact_echo, $($(quiet)cmd_$(1))) + @mkdir -p "$(call dirx,$@)" "$(dir $(depfile))" + $(if $(findstring flock,$(word 2,$(cmd_$1))), + @$(cmd_$(1)) + @echo " $(quiet_cmd_$(1)): Finished", + @$(cmd_$(1)) + ) + @$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile) + @$(if $(2),$(fixup_dep)) + $(if $(and $(3), $(POSTBUILDS)), + $(call do_postbuilds) + ) +) +endef + +# Declare the "all" target first so it is the default, +# even though we don't have the deps yet. +.PHONY: all +all: + +# make looks for ways to re-generate included makefiles, but in our case, we +# don't have a direct way. Explicitly telling make that it has nothing to do +# for them makes it go faster. +%.d: ; + +# Use FORCE_DO_CMD to force a target to run. Should be coupled with +# do_cmd. +.PHONY: FORCE_DO_CMD +FORCE_DO_CMD: + +TOOLSET := target +# Suffix rules, putting all outputs into $(obj). +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.c FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cxx FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.m FORCE_DO_CMD + @$(call do_cmd,objc,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.mm FORCE_DO_CMD + @$(call do_cmd,objcxx,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.S FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.s FORCE_DO_CMD + @$(call do_cmd,cc,1) + +# Try building from generated source, too. +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cxx FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.m FORCE_DO_CMD + @$(call do_cmd,objc,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.mm FORCE_DO_CMD + @$(call do_cmd,objcxx,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.S FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.s FORCE_DO_CMD + @$(call do_cmd,cc,1) + +$(obj).$(TOOLSET)/%.o: $(obj)/%.c FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.cpp FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.cxx FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.m FORCE_DO_CMD + @$(call do_cmd,objc,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.mm FORCE_DO_CMD + @$(call do_cmd,objcxx,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.S FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.s FORCE_DO_CMD + @$(call do_cmd,cc,1) + + +ifeq ($(strip $(foreach prefix,$(NO_LOAD),\ + $(findstring $(join ^,$(prefix)),\ + $(join ^,bson.target.mk)))),) + include bson.target.mk +endif + +quiet_cmd_regen_makefile = ACTION Regenerating $@ +cmd_regen_makefile = cd $(srcdir); /usr/local/lib/node_modules/npm/node_modules/node-gyp/gyp/gyp_main.py -fmake --ignore-environment "--toplevel-dir=." -I/Users/voxfeed_1/code/offhours/argon/node_modules/mongodb/node_modules/bson/build/config.gypi -I/usr/local/lib/node_modules/npm/node_modules/node-gyp/addon.gypi -I/Users/voxfeed_1/.node-gyp/0.10.31/common.gypi "--depth=." "-Goutput_dir=." "--generator-output=build" "-Dlibrary=shared_library" "-Dvisibility=default" "-Dnode_root_dir=/Users/voxfeed_1/.node-gyp/0.10.31" "-Dmodule_root_dir=/Users/voxfeed_1/code/offhours/argon/node_modules/mongodb/node_modules/bson" binding.gyp +Makefile: $(srcdir)/../../../../../../../../../usr/local/lib/node_modules/npm/node_modules/node-gyp/addon.gypi $(srcdir)/build/config.gypi $(srcdir)/binding.gyp $(srcdir)/../../../../../../../.node-gyp/0.10.31/common.gypi + $(call do_cmd,regen_makefile) + +# "all" is a concatenation of the "all" targets from all the included +# sub-makefiles. This is just here to clarify. +all: + +# Add in dependency-tracking rules. $(all_deps) is the list of every single +# target in our tree. Only consider the ones with .d (dependency) info: +d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d)) +ifneq ($(d_files),) + include $(d_files) +endif diff --git a/node_modules/mongodb/node_modules/bson/build/Release/.deps/Release/bson.node.d b/node_modules/mongodb/node_modules/bson/build/Release/.deps/Release/bson.node.d new file mode 100644 index 0000000..b3465a6 --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/build/Release/.deps/Release/bson.node.d @@ -0,0 +1 @@ +cmd_Release/bson.node := ./gyp-mac-tool flock ./Release/linker.lock c++ -bundle -Wl,-search_paths_first -mmacosx-version-min=10.5 -arch x86_64 -L./Release -o Release/bson.node Release/obj.target/bson/ext/bson.o -undefined dynamic_lookup diff --git a/node_modules/mongodb/node_modules/bson/build/Release/.deps/Release/obj.target/bson/ext/bson.o.d b/node_modules/mongodb/node_modules/bson/build/Release/.deps/Release/obj.target/bson/ext/bson.o.d new file mode 100644 index 0000000..0198e3e --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/build/Release/.deps/Release/obj.target/bson/ext/bson.o.d @@ -0,0 +1,26 @@ +cmd_Release/obj.target/bson/ext/bson.o := c++ '-D_DARWIN_USE_64_BIT_INODE=1' '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-DBUILDING_NODE_EXTENSION' -I/Users/voxfeed_1/.node-gyp/0.10.31/src -I/Users/voxfeed_1/.node-gyp/0.10.31/deps/uv/include -I/Users/voxfeed_1/.node-gyp/0.10.31/deps/v8/include -I../node_modules/nan -Os -gdwarf-2 -mmacosx-version-min=10.5 -arch x86_64 -Wall -Wendif-labels -W -Wno-unused-parameter -fno-rtti -fno-threadsafe-statics -fno-strict-aliasing -MMD -MF ./Release/.deps/Release/obj.target/bson/ext/bson.o.d.raw -c -o Release/obj.target/bson/ext/bson.o ../ext/bson.cc +Release/obj.target/bson/ext/bson.o: ../ext/bson.cc \ + /Users/voxfeed_1/.node-gyp/0.10.31/deps/v8/include/v8.h \ + /Users/voxfeed_1/.node-gyp/0.10.31/deps/v8/include/v8stdint.h \ + /Users/voxfeed_1/.node-gyp/0.10.31/src/node.h \ + /Users/voxfeed_1/.node-gyp/0.10.31/deps/uv/include/uv.h \ + /Users/voxfeed_1/.node-gyp/0.10.31/deps/uv/include/uv-private/uv-unix.h \ + /Users/voxfeed_1/.node-gyp/0.10.31/deps/uv/include/uv-private/ngx-queue.h \ + /Users/voxfeed_1/.node-gyp/0.10.31/deps/uv/include/uv-private/uv-darwin.h \ + /Users/voxfeed_1/.node-gyp/0.10.31/src/node_object_wrap.h \ + /Users/voxfeed_1/.node-gyp/0.10.31/src/node_version.h \ + /Users/voxfeed_1/.node-gyp/0.10.31/src/node_buffer.h ../ext/bson.h \ + ../node_modules/nan/nan.h +../ext/bson.cc: +/Users/voxfeed_1/.node-gyp/0.10.31/deps/v8/include/v8.h: +/Users/voxfeed_1/.node-gyp/0.10.31/deps/v8/include/v8stdint.h: +/Users/voxfeed_1/.node-gyp/0.10.31/src/node.h: +/Users/voxfeed_1/.node-gyp/0.10.31/deps/uv/include/uv.h: +/Users/voxfeed_1/.node-gyp/0.10.31/deps/uv/include/uv-private/uv-unix.h: +/Users/voxfeed_1/.node-gyp/0.10.31/deps/uv/include/uv-private/ngx-queue.h: +/Users/voxfeed_1/.node-gyp/0.10.31/deps/uv/include/uv-private/uv-darwin.h: +/Users/voxfeed_1/.node-gyp/0.10.31/src/node_object_wrap.h: +/Users/voxfeed_1/.node-gyp/0.10.31/src/node_version.h: +/Users/voxfeed_1/.node-gyp/0.10.31/src/node_buffer.h: +../ext/bson.h: +../node_modules/nan/nan.h: diff --git a/node_modules/mongodb/node_modules/bson/build/Release/bson.node b/node_modules/mongodb/node_modules/bson/build/Release/bson.node new file mode 100755 index 0000000000000000000000000000000000000000..b15b30551aa6b005e722b07a14a3d90e786657ec GIT binary patch literal 58484 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 literal 0 HcmV?d00001 diff --git a/node_modules/mongodb/node_modules/bson/build/Release/linker.lock b/node_modules/mongodb/node_modules/bson/build/Release/linker.lock new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/mongodb/node_modules/bson/build/Release/obj.target/bson/ext/bson.o b/node_modules/mongodb/node_modules/bson/build/Release/obj.target/bson/ext/bson.o new file mode 100644 index 0000000000000000000000000000000000000000..b7754e187f6f15a5aee17a48b48542d12e2773bf GIT binary patch literal 336876 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 z z^>$X6x3j{$1%-JF3iB2e=G~`Zp;wpaEhyC6kD*tOJaPj1?my2NcvZ*Levgg208X7h z?Z?`S*W4JG6&&8}a_H^)+lv0z7o$|*?Iwq}n;cj7cgX_{HUAYTpNsw${"): + lines[i] = None + lines[i - 1] = None + lines = '\n'.join(filter(lambda x: x is not None, lines)) + + # Write out the file with variables replaced. + fd = open(dest, 'w') + fd.write(lines) + fd.close() + + # Now write out PkgInfo file now that the Info.plist file has been + # "compiled". + self._WritePkgInfo(dest) + + def _WritePkgInfo(self, info_plist): + """This writes the PkgInfo file from the data stored in Info.plist.""" + plist = plistlib.readPlist(info_plist) + if not plist: + return + + # Only create PkgInfo for executable types. + package_type = plist['CFBundlePackageType'] + if package_type != 'APPL': + return + + # The format of PkgInfo is eight characters, representing the bundle type + # and bundle signature, each four characters. If that is missing, four + # '?' characters are used instead. + signature_code = plist.get('CFBundleSignature', '????') + if len(signature_code) != 4: # Wrong length resets everything, too. + signature_code = '?' * 4 + + dest = os.path.join(os.path.dirname(info_plist), 'PkgInfo') + fp = open(dest, 'w') + fp.write('%s%s' % (package_type, signature_code)) + fp.close() + + def ExecFlock(self, lockfile, *cmd_list): + """Emulates the most basic behavior of Linux's flock(1).""" + # Rely on exception handling to report errors. + fd = os.open(lockfile, os.O_RDONLY|os.O_NOCTTY|os.O_CREAT, 0o666) + fcntl.flock(fd, fcntl.LOCK_EX) + return subprocess.call(cmd_list) + + def ExecFilterLibtool(self, *cmd_list): + """Calls libtool and filters out '/path/to/libtool: file: foo.o has no + symbols'.""" + libtool_re = re.compile(r'^.*libtool: file: .* has no symbols$') + libtoolout = subprocess.Popen(cmd_list, stderr=subprocess.PIPE) + _, err = libtoolout.communicate() + for line in err.splitlines(): + if not libtool_re.match(line): + print >>sys.stderr, line + return libtoolout.returncode + + def ExecPackageFramework(self, framework, version): + """Takes a path to Something.framework and the Current version of that and + sets up all the symlinks.""" + # Find the name of the binary based on the part before the ".framework". + binary = os.path.basename(framework).split('.')[0] + + CURRENT = 'Current' + RESOURCES = 'Resources' + VERSIONS = 'Versions' + + if not os.path.exists(os.path.join(framework, VERSIONS, version, binary)): + # Binary-less frameworks don't seem to contain symlinks (see e.g. + # chromium's out/Debug/org.chromium.Chromium.manifest/ bundle). + return + + # Move into the framework directory to set the symlinks correctly. + pwd = os.getcwd() + os.chdir(framework) + + # Set up the Current version. + self._Relink(version, os.path.join(VERSIONS, CURRENT)) + + # Set up the root symlinks. + self._Relink(os.path.join(VERSIONS, CURRENT, binary), binary) + self._Relink(os.path.join(VERSIONS, CURRENT, RESOURCES), RESOURCES) + + # Back to where we were before! + os.chdir(pwd) + + def _Relink(self, dest, link): + """Creates a symlink to |dest| named |link|. If |link| already exists, + it is overwritten.""" + if os.path.lexists(link): + os.remove(link) + os.symlink(dest, link) + + def ExecCodeSignBundle(self, key, resource_rules, entitlements, provisioning): + """Code sign a bundle. + + This function tries to code sign an iOS bundle, following the same + algorithm as Xcode: + 1. copy ResourceRules.plist from the user or the SDK into the bundle, + 2. pick the provisioning profile that best match the bundle identifier, + and copy it into the bundle as embedded.mobileprovision, + 3. copy Entitlements.plist from user or SDK next to the bundle, + 4. code sign the bundle. + """ + resource_rules_path = self._InstallResourceRules(resource_rules) + substitutions, overrides = self._InstallProvisioningProfile( + provisioning, self._GetCFBundleIdentifier()) + entitlements_path = self._InstallEntitlements( + entitlements, substitutions, overrides) + subprocess.check_call([ + 'codesign', '--force', '--sign', key, '--resource-rules', + resource_rules_path, '--entitlements', entitlements_path, + os.path.join( + os.environ['TARGET_BUILD_DIR'], + os.environ['FULL_PRODUCT_NAME'])]) + + def _InstallResourceRules(self, resource_rules): + """Installs ResourceRules.plist from user or SDK into the bundle. + + Args: + resource_rules: string, optional, path to the ResourceRules.plist file + to use, default to "${SDKROOT}/ResourceRules.plist" + + Returns: + Path to the copy of ResourceRules.plist into the bundle. + """ + source_path = resource_rules + target_path = os.path.join( + os.environ['BUILT_PRODUCTS_DIR'], + os.environ['CONTENTS_FOLDER_PATH'], + 'ResourceRules.plist') + if not source_path: + source_path = os.path.join( + os.environ['SDKROOT'], 'ResourceRules.plist') + shutil.copy2(source_path, target_path) + return target_path + + def _InstallProvisioningProfile(self, profile, bundle_identifier): + """Installs embedded.mobileprovision into the bundle. + + Args: + profile: string, optional, short name of the .mobileprovision file + to use, if empty or the file is missing, the best file installed + will be used + bundle_identifier: string, value of CFBundleIdentifier from Info.plist + + Returns: + A tuple containing two dictionary: variables substitutions and values + to overrides when generating the entitlements file. + """ + source_path, provisioning_data, team_id = self._FindProvisioningProfile( + profile, bundle_identifier) + target_path = os.path.join( + os.environ['BUILT_PRODUCTS_DIR'], + os.environ['CONTENTS_FOLDER_PATH'], + 'embedded.mobileprovision') + shutil.copy2(source_path, target_path) + substitutions = self._GetSubstitutions(bundle_identifier, team_id + '.') + return substitutions, provisioning_data['Entitlements'] + + def _FindProvisioningProfile(self, profile, bundle_identifier): + """Finds the .mobileprovision file to use for signing the bundle. + + Checks all the installed provisioning profiles (or if the user specified + the PROVISIONING_PROFILE variable, only consult it) and select the most + specific that correspond to the bundle identifier. + + Args: + profile: string, optional, short name of the .mobileprovision file + to use, if empty or the file is missing, the best file installed + will be used + bundle_identifier: string, value of CFBundleIdentifier from Info.plist + + Returns: + A tuple of the path to the selected provisioning profile, the data of + the embedded plist in the provisioning profile and the team identifier + to use for code signing. + + Raises: + SystemExit: if no .mobileprovision can be used to sign the bundle. + """ + profiles_dir = os.path.join( + os.environ['HOME'], 'Library', 'MobileDevice', 'Provisioning Profiles') + if not os.path.isdir(profiles_dir): + print >>sys.stderr, ( + 'cannot find mobile provisioning for %s' % bundle_identifier) + sys.exit(1) + provisioning_profiles = None + if profile: + profile_path = os.path.join(profiles_dir, profile + '.mobileprovision') + if os.path.exists(profile_path): + provisioning_profiles = [profile_path] + if not provisioning_profiles: + provisioning_profiles = glob.glob( + os.path.join(profiles_dir, '*.mobileprovision')) + valid_provisioning_profiles = {} + for profile_path in provisioning_profiles: + profile_data = self._LoadProvisioningProfile(profile_path) + app_id_pattern = profile_data.get( + 'Entitlements', {}).get('application-identifier', '') + for team_identifier in profile_data.get('TeamIdentifier', []): + app_id = '%s.%s' % (team_identifier, bundle_identifier) + if fnmatch.fnmatch(app_id, app_id_pattern): + valid_provisioning_profiles[app_id_pattern] = ( + profile_path, profile_data, team_identifier) + if not valid_provisioning_profiles: + print >>sys.stderr, ( + 'cannot find mobile provisioning for %s' % bundle_identifier) + sys.exit(1) + # If the user has multiple provisioning profiles installed that can be + # used for ${bundle_identifier}, pick the most specific one (ie. the + # provisioning profile whose pattern is the longest). + selected_key = max(valid_provisioning_profiles, key=lambda v: len(v)) + return valid_provisioning_profiles[selected_key] + + def _LoadProvisioningProfile(self, profile_path): + """Extracts the plist embedded in a provisioning profile. + + Args: + profile_path: string, path to the .mobileprovision file + + Returns: + Content of the plist embedded in the provisioning profile as a dictionary. + """ + with tempfile.NamedTemporaryFile() as temp: + subprocess.check_call([ + 'security', 'cms', '-D', '-i', profile_path, '-o', temp.name]) + return self._LoadPlistMaybeBinary(temp.name) + + def _LoadPlistMaybeBinary(self, plist_path): + """Loads into a memory a plist possibly encoded in binary format. + + This is a wrapper around plistlib.readPlist that tries to convert the + plist to the XML format if it can't be parsed (assuming that it is in + the binary format). + + Args: + plist_path: string, path to a plist file, in XML or binary format + + Returns: + Content of the plist as a dictionary. + """ + try: + # First, try to read the file using plistlib that only supports XML, + # and if an exception is raised, convert a temporary copy to XML and + # load that copy. + return plistlib.readPlist(plist_path) + except: + pass + with tempfile.NamedTemporaryFile() as temp: + shutil.copy2(plist_path, temp.name) + subprocess.check_call(['plutil', '-convert', 'xml1', temp.name]) + return plistlib.readPlist(temp.name) + + def _GetSubstitutions(self, bundle_identifier, app_identifier_prefix): + """Constructs a dictionary of variable substitutions for Entitlements.plist. + + Args: + bundle_identifier: string, value of CFBundleIdentifier from Info.plist + app_identifier_prefix: string, value for AppIdentifierPrefix + + Returns: + Dictionary of substitutions to apply when generating Entitlements.plist. + """ + return { + 'CFBundleIdentifier': bundle_identifier, + 'AppIdentifierPrefix': app_identifier_prefix, + } + + def _GetCFBundleIdentifier(self): + """Extracts CFBundleIdentifier value from Info.plist in the bundle. + + Returns: + Value of CFBundleIdentifier in the Info.plist located in the bundle. + """ + info_plist_path = os.path.join( + os.environ['TARGET_BUILD_DIR'], + os.environ['INFOPLIST_PATH']) + info_plist_data = self._LoadPlistMaybeBinary(info_plist_path) + return info_plist_data['CFBundleIdentifier'] + + def _InstallEntitlements(self, entitlements, substitutions, overrides): + """Generates and install the ${BundleName}.xcent entitlements file. + + Expands variables "$(variable)" pattern in the source entitlements file, + add extra entitlements defined in the .mobileprovision file and the copy + the generated plist to "${BundlePath}.xcent". + + Args: + entitlements: string, optional, path to the Entitlements.plist template + to use, defaults to "${SDKROOT}/Entitlements.plist" + substitutions: dictionary, variable substitutions + overrides: dictionary, values to add to the entitlements + + Returns: + Path to the generated entitlements file. + """ + source_path = entitlements + target_path = os.path.join( + os.environ['BUILT_PRODUCTS_DIR'], + os.environ['PRODUCT_NAME'] + '.xcent') + if not source_path: + source_path = os.path.join( + os.environ['SDKROOT'], + 'Entitlements.plist') + shutil.copy2(source_path, target_path) + data = self._LoadPlistMaybeBinary(target_path) + data = self._ExpandVariables(data, substitutions) + if overrides: + for key in overrides: + if key not in data: + data[key] = overrides[key] + plistlib.writePlist(data, target_path) + return target_path + + def _ExpandVariables(self, data, substitutions): + """Expands variables "$(variable)" in data. + + Args: + data: object, can be either string, list or dictionary + substitutions: dictionary, variable substitutions to perform + + Returns: + Copy of data where each references to "$(variable)" has been replaced + by the corresponding value found in substitutions, or left intact if + the key was not found. + """ + if isinstance(data, str): + for key, value in substitutions.iteritems(): + data = data.replace('$(%s)' % key, value) + return data + if isinstance(data, list): + return [self._ExpandVariables(v, substitutions) for v in data] + if isinstance(data, dict): + return dict((k, self._ExpandVariables(data[k], + substitutions)) for k in data) + return data + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) diff --git a/node_modules/mongodb/node_modules/bson/build_browser.js b/node_modules/mongodb/node_modules/bson/build_browser.js new file mode 100644 index 0000000..bb80238 --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/build_browser.js @@ -0,0 +1,7 @@ +require('one'); + +one('./package.json') + .tie('bson', BSON) + // .exclude('buffer') + .tie('buffer', {}) + .save('./browser_build/bson.js') \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/bson/builderror.log b/node_modules/mongodb/node_modules/bson/builderror.log new file mode 100644 index 0000000..9c12da4 --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/builderror.log @@ -0,0 +1,4 @@ +xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance + +xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance + diff --git a/node_modules/mongodb/node_modules/bson/ext/Makefile b/node_modules/mongodb/node_modules/bson/ext/Makefile new file mode 100644 index 0000000..435999e --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/ext/Makefile @@ -0,0 +1,28 @@ +NODE = node +name = all +JOBS = 1 + +all: + rm -rf build .lock-wscript bson.node + node-waf configure build + cp -R ./build/Release/bson.node . || true + +all_debug: + rm -rf build .lock-wscript bson.node + node-waf --debug configure build + cp -R ./build/Release/bson.node . || true + +clang: + rm -rf build .lock-wscript bson.node + CXX=clang node-waf configure build + cp -R ./build/Release/bson.node . || true + +clang_debug: + rm -rf build .lock-wscript bson.node + CXX=clang node-waf --debug configure build + cp -R ./build/Release/bson.node . || true + +clean: + rm -rf build .lock-wscript bson.node + +.PHONY: all \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/bson/ext/bson.cc b/node_modules/mongodb/node_modules/bson/ext/bson.cc new file mode 100644 index 0000000..90e2ef9 --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/ext/bson.cc @@ -0,0 +1,1072 @@ +//=========================================================================== + +#include +#include +#include +#include +#include + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-parameter" +#endif + +#include + +// this and the above block must be around the v8.h header otherwise +// v8 is not happy +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include + +#if defined(__sun) || defined(_AIX) + #include +#endif + +#include "bson.h" + +using namespace v8; +using namespace node; + +void die(const char *message) { + if(errno) { + perror(message); + } else { + printf("ERROR: %s\n", message); + } + + exit(1); +} + +//=========================================================================== + +void DataStream::WriteObjectId(const Handle& object, const Handle& key) +{ + uint16_t buffer[12]; + object->Get(key)->ToString()->Write(buffer, 0, 12); + for(uint32_t i = 0; i < 12; ++i) + { + *p++ = (char) buffer[i]; + } +} + +void ThrowAllocatedStringException(size_t allocationSize, const char* format, ...) +{ + va_list args; + va_start(args, format); + char* string = (char*) malloc(allocationSize); + if(string == NULL) die("Failed to allocate ThrowAllocatedStringException"); + vsprintf(string, format, args); + va_end(args); + throw string; +} + +void DataStream::CheckKey(const Local& keyName) +{ + size_t keyLength = keyName->Utf8Length(); + if(keyLength == 0) return; + + // Allocate space for the key, do not need to zero terminate as WriteUtf8 does it + char* keyStringBuffer = (char*) alloca(keyLength + 1); + // Write the key to the allocated buffer + keyName->WriteUtf8(keyStringBuffer); + // Check for the zero terminator + char* terminator = strchr(keyStringBuffer, 0x00); + + // If the location is not at the end of the string we've got an illegal 0x00 byte somewhere + if(terminator != &keyStringBuffer[keyLength]) { + ThrowAllocatedStringException(64+keyLength, "key %s must not contain null bytes", keyStringBuffer); + } + + if(keyStringBuffer[0] == '$') + { + ThrowAllocatedStringException(64+keyLength, "key %s must not start with '$'", keyStringBuffer); + } + + if(strchr(keyStringBuffer, '.') != NULL) + { + ThrowAllocatedStringException(64+keyLength, "key %s must not contain '.'", keyStringBuffer); + } +} + +template void BSONSerializer::SerializeDocument(const Handle& value) +{ + void* documentSize = this->BeginWriteSize(); + Local object = bson->GetSerializeObject(value); + + // Get the object property names + Local propertyNames = object->GetPropertyNames(); + + // Length of the property + int propertyLength = propertyNames->Length(); + for(int i = 0; i < propertyLength; ++i) + { + const Local& propertyName = propertyNames->Get(i)->ToString(); + if(checkKeys) this->CheckKey(propertyName); + + const Local& propertyValue = object->Get(propertyName); + + if(serializeFunctions || !propertyValue->IsFunction()) + { + void* typeLocation = this->BeginWriteType(); + this->WriteString(propertyName); + SerializeValue(typeLocation, propertyValue); + } + } + + this->WriteByte(0); + this->CommitSize(documentSize); +} + +template void BSONSerializer::SerializeArray(const Handle& value) +{ + void* documentSize = this->BeginWriteSize(); + + Local array = Local::Cast(value->ToObject()); + uint32_t arrayLength = array->Length(); + + for(uint32_t i = 0; i < arrayLength; ++i) + { + void* typeLocation = this->BeginWriteType(); + this->WriteUInt32String(i); + SerializeValue(typeLocation, array->Get(i)); + } + + this->WriteByte(0); + this->CommitSize(documentSize); +} + +// This is templated so that we can use this function to both count the number of bytes, and to serialize those bytes. +// The template approach eliminates almost all of the inspection of values unless they're required (eg. string lengths) +// and ensures that there is always consistency between bytes counted and bytes written by design. +template void BSONSerializer::SerializeValue(void* typeLocation, const Handle constValue) +{ + // Turn into local value + Local value = NanNew(constValue); + + // Check for toBSON function + if(value->IsObject()) { + Local object = value->ToObject(); + + // NanNew("toBSON") + // NanNew(BSON::_toBSONString) + + if(object->Has(NanNew("toBSON"))) { + const Local& toBSON = object->Get(NanNew("toBSON")); + if(!toBSON->IsFunction()) ThrowAllocatedStringException(64, "toBSON is not a function"); + value = Local::Cast(toBSON)->Call(object, 0, NULL); + } + } + + // Process all the values + if(value->IsNumber()) + { + double doubleValue = value->NumberValue(); + int intValue = (int) doubleValue; + if(intValue == doubleValue) + { + this->CommitType(typeLocation, BSON_TYPE_INT); + this->WriteInt32(intValue); + } + else + { + this->CommitType(typeLocation, BSON_TYPE_NUMBER); + this->WriteDouble(doubleValue); + } + } + else if(value->IsString()) + { + this->CommitType(typeLocation, BSON_TYPE_STRING); + this->WriteLengthPrefixedString(value->ToString()); + } + else if(value->IsBoolean()) + { + this->CommitType(typeLocation, BSON_TYPE_BOOLEAN); + this->WriteBool(value); + } + else if(value->IsArray()) + { + this->CommitType(typeLocation, BSON_TYPE_ARRAY); + SerializeArray(value); + } + else if(value->IsDate()) + { + this->CommitType(typeLocation, BSON_TYPE_DATE); + this->WriteInt64(value); + } + else if(value->IsRegExp()) + { + this->CommitType(typeLocation, BSON_TYPE_REGEXP); + const Handle& regExp = Handle::Cast(value); + + this->WriteString(regExp->GetSource()); + + int flags = regExp->GetFlags(); + if(flags & RegExp::kGlobal) this->WriteByte('s'); + if(flags & RegExp::kIgnoreCase) this->WriteByte('i'); + if(flags & RegExp::kMultiline) this->WriteByte('m'); + this->WriteByte(0); + } + else if(value->IsFunction()) + { + this->CommitType(typeLocation, BSON_TYPE_CODE); + this->WriteLengthPrefixedString(value->ToString()); + } + else if(value->IsObject()) + { + const Local& object = value->ToObject(); + if(object->Has(NanNew(bson->_bsontypeString))) + { + const Local& constructorString = object->Get(NanNew(bson->_bsontypeString))->ToString(); + if(NanNew(bson->longString)->StrictEquals(constructorString)) + { + this->CommitType(typeLocation, BSON_TYPE_LONG); + this->WriteInt32(object, NanNew(bson->_longLowString)); + this->WriteInt32(object, NanNew(bson->_longHighString)); + } + else if(NanNew(bson->timestampString)->StrictEquals(constructorString)) + { + this->CommitType(typeLocation, BSON_TYPE_TIMESTAMP); + this->WriteInt32(object, NanNew(bson->_longLowString)); + this->WriteInt32(object, NanNew(bson->_longHighString)); + } + else if(NanNew(bson->objectIDString)->StrictEquals(constructorString)) + { + this->CommitType(typeLocation, BSON_TYPE_OID); + this->WriteObjectId(object, NanNew(bson->_objectIDidString)); + } + else if(NanNew(bson->binaryString)->StrictEquals(constructorString)) + { + this->CommitType(typeLocation, BSON_TYPE_BINARY); + + uint32_t length = object->Get(NanNew(bson->_binaryPositionString))->Uint32Value(); + Local bufferObj = object->Get(NanNew(bson->_binaryBufferString))->ToObject(); + + this->WriteInt32(length); + this->WriteByte(object, NanNew(bson->_binarySubTypeString)); // write subtype + // If type 0x02 write the array length aswell + if(object->Get(NanNew(bson->_binarySubTypeString))->Int32Value() == 0x02) { + this->WriteInt32(length); + } + // Write the actual data + this->WriteData(Buffer::Data(bufferObj), length); + } + else if(NanNew(bson->doubleString)->StrictEquals(constructorString)) + { + this->CommitType(typeLocation, BSON_TYPE_NUMBER); + this->WriteDouble(object, NanNew(bson->_doubleValueString)); + } + else if(NanNew(bson->symbolString)->StrictEquals(constructorString)) + { + this->CommitType(typeLocation, BSON_TYPE_SYMBOL); + this->WriteLengthPrefixedString(object->Get(NanNew(bson->_symbolValueString))->ToString()); + } + else if(NanNew(bson->codeString)->StrictEquals(constructorString)) + { + const Local& function = object->Get(NanNew(bson->_codeCodeString))->ToString(); + const Local& scope = object->Get(NanNew(bson->_codeScopeString))->ToObject(); + + // For Node < 0.6.X use the GetPropertyNames + #if NODE_MAJOR_VERSION == 0 && NODE_MINOR_VERSION < 6 + uint32_t propertyNameLength = scope->GetPropertyNames()->Length(); + #else + uint32_t propertyNameLength = scope->GetOwnPropertyNames()->Length(); + #endif + + if(propertyNameLength > 0) + { + this->CommitType(typeLocation, BSON_TYPE_CODE_W_SCOPE); + void* codeWidthScopeSize = this->BeginWriteSize(); + this->WriteLengthPrefixedString(function->ToString()); + SerializeDocument(scope); + this->CommitSize(codeWidthScopeSize); + } + else + { + this->CommitType(typeLocation, BSON_TYPE_CODE); + this->WriteLengthPrefixedString(function->ToString()); + } + } + else if(NanNew(bson->dbrefString)->StrictEquals(constructorString)) + { + this->CommitType(typeLocation, BSON_TYPE_OBJECT); + + void* dbRefSize = this->BeginWriteSize(); + + void* refType = this->BeginWriteType(); + this->WriteData("$ref", 5); + SerializeValue(refType, object->Get(NanNew(bson->_dbRefNamespaceString))); + + void* idType = this->BeginWriteType(); + this->WriteData("$id", 4); + SerializeValue(idType, object->Get(NanNew(bson->_dbRefOidString))); + + const Local& refDbValue = object->Get(NanNew(bson->_dbRefDbString)); + if(!refDbValue->IsUndefined()) + { + void* dbType = this->BeginWriteType(); + this->WriteData("$db", 4); + SerializeValue(dbType, refDbValue); + } + + this->WriteByte(0); + this->CommitSize(dbRefSize); + } + else if(NanNew(bson->minKeyString)->StrictEquals(constructorString)) + { + this->CommitType(typeLocation, BSON_TYPE_MIN_KEY); + } + else if(NanNew(bson->maxKeyString)->StrictEquals(constructorString)) + { + this->CommitType(typeLocation, BSON_TYPE_MAX_KEY); + } + } + else if(Buffer::HasInstance(value)) + { + this->CommitType(typeLocation, BSON_TYPE_BINARY); + + #if NODE_MAJOR_VERSION == 0 && NODE_MINOR_VERSION < 3 + Local buffer = ObjectWrap::Unwrap(value->ToObject()); + uint32_t length = object->length(); + #else + uint32_t length = Buffer::Length(value->ToObject()); + #endif + + this->WriteInt32(length); + this->WriteByte(0); + this->WriteData(Buffer::Data(value->ToObject()), length); + } + else + { + this->CommitType(typeLocation, BSON_TYPE_OBJECT); + SerializeDocument(value); + } + } + else if(value->IsNull() || value->IsUndefined()) + { + this->CommitType(typeLocation, BSON_TYPE_NULL); + } +} + +// Data points to start of element list, length is length of entire document including '\0' but excluding initial size +BSONDeserializer::BSONDeserializer(BSON* aBson, char* data, size_t length) +: bson(aBson), + pStart(data), + p(data), + pEnd(data + length - 1) +{ + if(*pEnd != '\0') ThrowAllocatedStringException(64, "Missing end of document marker '\\0'"); +} + +BSONDeserializer::BSONDeserializer(BSONDeserializer& parentSerializer, size_t length) +: bson(parentSerializer.bson), + pStart(parentSerializer.p), + p(parentSerializer.p), + pEnd(parentSerializer.p + length - 1) +{ + parentSerializer.p += length; + if(pEnd > parentSerializer.pEnd) ThrowAllocatedStringException(64, "Child document exceeds parent's bounds"); + if(*pEnd != '\0') ThrowAllocatedStringException(64, "Missing end of document marker '\\0'"); +} + +Handle BSONDeserializer::ReadCString() +{ + char* start = p; + while(*p++ && (p < pEnd)) { } + if(p > pEnd) { + return NanNull(); + } + return NanNew(start, (int32_t) (p-start-1) ); +} + +int32_t BSONDeserializer::ReadRegexOptions() +{ + int32_t options = 0; + for(;;) + { + switch(*p++) + { + case '\0': return options; + case 's': options |= RegExp::kGlobal; break; + case 'i': options |= RegExp::kIgnoreCase; break; + case 'm': options |= RegExp::kMultiline; break; + } + } +} + +uint32_t BSONDeserializer::ReadIntegerString() +{ + uint32_t value = 0; + while(*p) + { + if(*p < '0' || *p > '9') ThrowAllocatedStringException(64, "Invalid key for array"); + value = value * 10 + *p++ - '0'; + } + ++p; + return value; +} + +Local BSONDeserializer::ReadString() +{ + uint32_t length = ReadUInt32(); + char* start = p; + p += length; + return NanNew(start, length-1); +} + +Local BSONDeserializer::ReadObjectId() +{ + uint16_t objectId[12]; + for(size_t i = 0; i < 12; ++i) + { + objectId[i] = *reinterpret_cast(p++); + } + return NanNew(objectId, 12); +} + +Handle BSONDeserializer::DeserializeDocument(bool promoteLongs) +{ + uint32_t length = ReadUInt32(); + if(length < 5) ThrowAllocatedStringException(64, "Bad BSON: Document is less than 5 bytes"); + + BSONDeserializer documentDeserializer(*this, length-4); + return documentDeserializer.DeserializeDocumentInternal(promoteLongs); +} + +Handle BSONDeserializer::DeserializeDocumentInternal(bool promoteLongs) +{ + Local returnObject = NanNew(); + + while(HasMoreData()) + { + BsonType type = (BsonType) ReadByte(); + const Handle& name = ReadCString(); + if(name->IsNull()) ThrowAllocatedStringException(64, "Bad BSON Document: illegal CString"); + // name->Is + const Handle& value = DeserializeValue(type, promoteLongs); + returnObject->ForceSet(name, value); + } + if(p != pEnd) ThrowAllocatedStringException(64, "Bad BSON Document: Serialize consumed unexpected number of bytes"); + + // From JavaScript: + // if(object['$id'] != null) object = new DBRef(object['$ref'], object['$id'], object['$db']); + if(returnObject->Has(NanNew(bson->_dbRefIdRefString))) + { + Local argv[] = { returnObject->Get(NanNew(bson->_dbRefRefString)), returnObject->Get(NanNew(bson->_dbRefIdRefString)), returnObject->Get(NanNew(bson->_dbRefDbRefString)) }; + return NanNew(bson->dbrefConstructor)->NewInstance(3, argv); + } + else + { + return returnObject; + } +} + +Handle BSONDeserializer::DeserializeArray(bool promoteLongs) +{ + uint32_t length = ReadUInt32(); + if(length < 5) ThrowAllocatedStringException(64, "Bad BSON: Array Document is less than 5 bytes"); + + BSONDeserializer documentDeserializer(*this, length-4); + return documentDeserializer.DeserializeArrayInternal(promoteLongs); +} + +Handle BSONDeserializer::DeserializeArrayInternal(bool promoteLongs) +{ + Local returnArray = NanNew(); + + while(HasMoreData()) + { + BsonType type = (BsonType) ReadByte(); + uint32_t index = ReadIntegerString(); + const Handle& value = DeserializeValue(type, promoteLongs); + returnArray->Set(index, value); + } + if(p != pEnd) ThrowAllocatedStringException(64, "Bad BSON Array: Serialize consumed unexpected number of bytes"); + + return returnArray; +} + +Handle BSONDeserializer::DeserializeValue(BsonType type, bool promoteLongs) +{ + switch(type) + { + case BSON_TYPE_STRING: + return ReadString(); + + case BSON_TYPE_INT: + return NanNew(ReadInt32()); + + case BSON_TYPE_NUMBER: + return NanNew(ReadDouble()); + + case BSON_TYPE_NULL: + return NanNull(); + + case BSON_TYPE_UNDEFINED: + return NanNull(); + + case BSON_TYPE_TIMESTAMP: + { + int32_t lowBits = ReadInt32(); + int32_t highBits = ReadInt32(); + Local argv[] = { NanNew(lowBits), NanNew(highBits) }; + return NanNew(bson->timestampConstructor)->NewInstance(2, argv); + } + + case BSON_TYPE_BOOLEAN: + return (ReadByte() != 0) ? NanTrue() : NanFalse(); + + case BSON_TYPE_REGEXP: + { + const Handle& regex = ReadCString(); + if(regex->IsNull()) ThrowAllocatedStringException(64, "Bad BSON Document: illegal CString"); + int32_t options = ReadRegexOptions(); + return NanNew(regex->ToString(), (RegExp::Flags) options); + } + + case BSON_TYPE_CODE: + { + const Local& code = ReadString(); + const Local& scope = NanNew(); + Local argv[] = { code, scope }; + return NanNew(bson->codeConstructor)->NewInstance(2, argv); + } + + case BSON_TYPE_CODE_W_SCOPE: + { + ReadUInt32(); + const Local& code = ReadString(); + const Handle& scope = DeserializeDocument(promoteLongs); + Local argv[] = { code, scope->ToObject() }; + return NanNew(bson->codeConstructor)->NewInstance(2, argv); + } + + case BSON_TYPE_OID: + { + Local argv[] = { ReadObjectId() }; + return NanNew(bson->objectIDConstructor)->NewInstance(1, argv); + } + + case BSON_TYPE_BINARY: + { + uint32_t length = ReadUInt32(); + uint32_t subType = ReadByte(); + if(subType == 0x02) { + length = ReadInt32(); + } + + Local buffer = NanNewBufferHandle(p, length); + p += length; + + Handle argv[] = { buffer, NanNew(subType) }; + return NanNew(bson->binaryConstructor)->NewInstance(2, argv); + } + + case BSON_TYPE_LONG: + { + // Read 32 bit integers + int32_t lowBits = (int32_t) ReadInt32(); + int32_t highBits = (int32_t) ReadInt32(); + + // Promote long is enabled + if(promoteLongs) { + // If value is < 2^53 and >-2^53 + if((highBits < 0x200000 || (highBits == 0x200000 && lowBits == 0)) && highBits >= -0x200000) { + // Adjust the pointer and read as 64 bit value + p -= 8; + // Read the 64 bit value + int64_t finalValue = (int64_t) ReadInt64(); + return NanNew(finalValue); + } + } + + // Decode the Long value + Local argv[] = { NanNew(lowBits), NanNew(highBits) }; + return NanNew(bson->longConstructor)->NewInstance(2, argv); + } + + case BSON_TYPE_DATE: + return NanNew((double) ReadInt64()); + + case BSON_TYPE_ARRAY: + return DeserializeArray(promoteLongs); + + case BSON_TYPE_OBJECT: + return DeserializeDocument(promoteLongs); + + case BSON_TYPE_SYMBOL: + { + const Local& string = ReadString(); + Local argv[] = { string }; + return NanNew(bson->symbolConstructor)->NewInstance(1, argv); + } + + case BSON_TYPE_MIN_KEY: + return NanNew(bson->minKeyConstructor)->NewInstance(); + + case BSON_TYPE_MAX_KEY: + return NanNew(bson->maxKeyConstructor)->NewInstance(); + + default: + ThrowAllocatedStringException(64, "Unhandled BSON Type: %d", type); + } + + return NanNull(); +} + +Persistent BSON::constructor_template; + +BSON::BSON() : ObjectWrap() +{ + // Setup pre-allocated comparision objects + NanAssignPersistent(_bsontypeString, NanNew("_bsontype")); + NanAssignPersistent(_longLowString, NanNew("low_")); + NanAssignPersistent(_longHighString, NanNew("high_")); + NanAssignPersistent(_objectIDidString, NanNew("id")); + NanAssignPersistent(_binaryPositionString, NanNew("position")); + NanAssignPersistent(_binarySubTypeString, NanNew("sub_type")); + NanAssignPersistent(_binaryBufferString, NanNew("buffer")); + NanAssignPersistent(_doubleValueString, NanNew("value")); + NanAssignPersistent(_symbolValueString, NanNew("value")); + NanAssignPersistent(_dbRefRefString, NanNew("$ref")); + NanAssignPersistent(_dbRefIdRefString, NanNew("$id")); + NanAssignPersistent(_dbRefDbRefString, NanNew("$db")); + NanAssignPersistent(_dbRefNamespaceString, NanNew("namespace")); + NanAssignPersistent(_dbRefDbString, NanNew("db")); + NanAssignPersistent(_dbRefOidString, NanNew("oid")); + NanAssignPersistent(_codeCodeString, NanNew("code")); + NanAssignPersistent(_codeScopeString, NanNew("scope")); + NanAssignPersistent(_toBSONString, NanNew("toBSON")); + + NanAssignPersistent(longString, NanNew("Long")); + NanAssignPersistent(objectIDString, NanNew("ObjectID")); + NanAssignPersistent(binaryString, NanNew("Binary")); + NanAssignPersistent(codeString, NanNew("Code")); + NanAssignPersistent(dbrefString, NanNew("DBRef")); + NanAssignPersistent(symbolString, NanNew("Symbol")); + NanAssignPersistent(doubleString, NanNew("Double")); + NanAssignPersistent(timestampString, NanNew("Timestamp")); + NanAssignPersistent(minKeyString, NanNew("MinKey")); + NanAssignPersistent(maxKeyString, NanNew("MaxKey")); +} + +void BSON::Initialize(v8::Handle target) +{ + // Grab the scope of the call from Node + NanScope(); + // Define a new function template + Local t = NanNew(New); + t->InstanceTemplate()->SetInternalFieldCount(1); + t->SetClassName(NanNew("BSON")); + + // Instance methods + NODE_SET_PROTOTYPE_METHOD(t, "calculateObjectSize", CalculateObjectSize); + NODE_SET_PROTOTYPE_METHOD(t, "serialize", BSONSerialize); + NODE_SET_PROTOTYPE_METHOD(t, "serializeWithBufferAndIndex", SerializeWithBufferAndIndex); + NODE_SET_PROTOTYPE_METHOD(t, "deserialize", BSONDeserialize); + NODE_SET_PROTOTYPE_METHOD(t, "deserializeStream", BSONDeserializeStream); + + NanAssignPersistent(constructor_template, t); + + target->ForceSet(NanNew("BSON"), t->GetFunction()); +} + +// Create a new instance of BSON and passing it the existing context +NAN_METHOD(BSON::New) +{ + NanScope(); + + // Check that we have an array + if(args.Length() == 1 && args[0]->IsArray()) + { + // Cast the array to a local reference + Local array = Local::Cast(args[0]); + + if(array->Length() > 0) + { + // Create a bson object instance and return it + BSON *bson = new BSON(); + + uint32_t foundClassesMask = 0; + + // Iterate over all entries to save the instantiate functions + for(uint32_t i = 0; i < array->Length(); i++) { + // Let's get a reference to the function + Local func = Local::Cast(array->Get(i)); + Local functionName = func->GetName()->ToString(); + + // Save the functions making them persistant handles (they don't get collected) + if(functionName->StrictEquals(NanNew(bson->longString))) { + NanAssignPersistent(bson->longConstructor, func); + foundClassesMask |= 1; + } else if(functionName->StrictEquals(NanNew(bson->objectIDString))) { + NanAssignPersistent(bson->objectIDConstructor, func); + foundClassesMask |= 2; + } else if(functionName->StrictEquals(NanNew(bson->binaryString))) { + NanAssignPersistent(bson->binaryConstructor, func); + foundClassesMask |= 4; + } else if(functionName->StrictEquals(NanNew(bson->codeString))) { + NanAssignPersistent(bson->codeConstructor, func); + foundClassesMask |= 8; + } else if(functionName->StrictEquals(NanNew(bson->dbrefString))) { + NanAssignPersistent(bson->dbrefConstructor, func); + foundClassesMask |= 0x10; + } else if(functionName->StrictEquals(NanNew(bson->symbolString))) { + NanAssignPersistent(bson->symbolConstructor, func); + foundClassesMask |= 0x20; + } else if(functionName->StrictEquals(NanNew(bson->doubleString))) { + NanAssignPersistent(bson->doubleConstructor, func); + foundClassesMask |= 0x40; + } else if(functionName->StrictEquals(NanNew(bson->timestampString))) { + NanAssignPersistent(bson->timestampConstructor, func); + foundClassesMask |= 0x80; + } else if(functionName->StrictEquals(NanNew(bson->minKeyString))) { + NanAssignPersistent(bson->minKeyConstructor, func); + foundClassesMask |= 0x100; + } else if(functionName->StrictEquals(NanNew(bson->maxKeyString))) { + NanAssignPersistent(bson->maxKeyConstructor, func); + foundClassesMask |= 0x200; + } + } + + // Check if we have the right number of constructors otherwise throw an error + if(foundClassesMask != 0x3ff) { + delete bson; + return NanThrowError("Missing function constructor for either [Long/ObjectID/Binary/Code/DbRef/Symbol/Double/Timestamp/MinKey/MaxKey]"); + } else { + bson->Wrap(args.This()); + NanReturnValue(args.This()); + } + } + else + { + return NanThrowError("No types passed in"); + } + } + else + { + return NanThrowTypeError("Argument passed in must be an array of types"); + } +} + +//------------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------------------------ + +NAN_METHOD(BSON::BSONDeserialize) +{ + NanScope(); + + // Fail if the first argument is not a string or a buffer + if(args.Length() > 1 && !args[0]->IsString() && !Buffer::HasInstance(args[0])) + return NanThrowError("First Argument must be a Buffer or String."); + + // Promote longs + bool promoteLongs = true; + + // If we have an options object + if(args.Length() == 2 && args[1]->IsObject()) { + Local options = args[1]->ToObject(); + + if(options->Has(NanNew("promoteLongs"))) { + promoteLongs = options->Get(NanNew("promoteLongs"))->ToBoolean()->Value(); + } + } + + // Define pointer to data + Local obj = args[0]->ToObject(); + + // Unpack the BSON parser instance + BSON *bson = ObjectWrap::Unwrap(args.This()); + + // If we passed in a buffer, let's unpack it, otherwise let's unpack the string + if(Buffer::HasInstance(obj)) + { +#if NODE_MAJOR_VERSION == 0 && NODE_MINOR_VERSION < 3 + Local buffer = ObjectWrap::Unwrap(obj); + char* data = buffer->data(); + size_t length = buffer->length(); +#else + char* data = Buffer::Data(obj); + size_t length = Buffer::Length(obj); +#endif + + // Validate that we have at least 5 bytes + if(length < 5) return NanThrowError("corrupt bson message < 5 bytes long"); + + try + { + BSONDeserializer deserializer(bson, data, length); + // deserializer.promoteLongs = promoteLongs; + NanReturnValue(deserializer.DeserializeDocument(promoteLongs)); + } + catch(char* exception) + { + Local error = NanNew(exception); + free(exception); + return NanThrowError(error); + } + + } + else + { + // The length of the data for this encoding + ssize_t len = DecodeBytes(args[0], BINARY); + + // Validate that we have at least 5 bytes + if(len < 5) return NanThrowError("corrupt bson message < 5 bytes long"); + + // Let's define the buffer size + char* data = (char *)malloc(len); + if(data == NULL) die("Failed to allocate char buffer for BSON serialization"); + DecodeWrite(data, len, args[0], BINARY); + + try + { + BSONDeserializer deserializer(bson, data, len); + // deserializer.promoteLongs = promoteLongs; + Handle result = deserializer.DeserializeDocument(promoteLongs); + free(data); + NanReturnValue(result); + + } + catch(char* exception) + { + Local error = NanNew(exception); + free(exception); + free(data); + return NanThrowError(error); + } + } +} + +Local BSON::GetSerializeObject(const Handle& argValue) +{ + Local object = argValue->ToObject(); + if(object->Has(NanNew(_toBSONString))) + { + const Local& toBSON = object->Get(NanNew(_toBSONString)); + if(!toBSON->IsFunction()) ThrowAllocatedStringException(64, "toBSON is not a function"); + + Local result = Local::Cast(toBSON)->Call(object, 0, NULL); + if(!result->IsObject()) ThrowAllocatedStringException(64, "toBSON function did not return an object"); + return result->ToObject(); + } + else + { + return object; + } +} + +NAN_METHOD(BSON::BSONSerialize) +{ + NanScope(); + + if(args.Length() == 1 && !args[0]->IsObject()) return NanThrowError("One, two or tree arguments required - [object] or [object, boolean] or [object, boolean, boolean]"); + if(args.Length() == 2 && !args[0]->IsObject() && !args[1]->IsBoolean()) return NanThrowError("One, two or tree arguments required - [object] or [object, boolean] or [object, boolean, boolean]"); + if(args.Length() == 3 && !args[0]->IsObject() && !args[1]->IsBoolean() && !args[2]->IsBoolean()) return NanThrowError("One, two or tree arguments required - [object] or [object, boolean] or [object, boolean, boolean]"); + if(args.Length() == 4 && !args[0]->IsObject() && !args[1]->IsBoolean() && !args[2]->IsBoolean() && !args[3]->IsBoolean()) return NanThrowError("One, two or tree arguments required - [object] or [object, boolean] or [object, boolean, boolean] or [object, boolean, boolean, boolean]"); + if(args.Length() > 4) return NanThrowError("One, two, tree or four arguments required - [object] or [object, boolean] or [object, boolean, boolean] or [object, boolean, boolean, boolean]"); + + // Check if we have an array as the object + if(args[0]->IsArray()) return NanThrowError("Only javascript objects supported"); + + // Unpack the BSON parser instance + BSON *bson = ObjectWrap::Unwrap(args.This()); + + // Calculate the total size of the document in binary form to ensure we only allocate memory once + // With serialize function + bool serializeFunctions = (args.Length() >= 4) && args[3]->BooleanValue(); + + char *serialized_object = NULL; + size_t object_size; + try + { + Local object = bson->GetSerializeObject(args[0]); + + BSONSerializer counter(bson, false, serializeFunctions); + counter.SerializeDocument(object); + object_size = counter.GetSerializeSize(); + + // Allocate the memory needed for the serialization + serialized_object = (char *)malloc(object_size); + if(serialized_object == NULL) die("Failed to allocate memory for object"); + + // Check if we have a boolean value + bool checkKeys = args.Length() >= 3 && args[1]->IsBoolean() && args[1]->BooleanValue(); + BSONSerializer data(bson, checkKeys, serializeFunctions, serialized_object); + data.SerializeDocument(object); + } + catch(char *err_msg) + { + free(serialized_object); + Local error = NanNew(err_msg); + free(err_msg); + return NanThrowError(error); + } + + // If we have 3 arguments + if(args.Length() == 3 || args.Length() == 4) + { + Local buffer = NanNewBufferHandle(serialized_object, object_size); + free(serialized_object); + NanReturnValue(buffer); + } + else + { + Local bin_value = Encode(serialized_object, object_size, BINARY)->ToString(); + free(serialized_object); + NanReturnValue(bin_value); + } +} + +NAN_METHOD(BSON::CalculateObjectSize) +{ + NanScope(); + // Ensure we have a valid object + if(args.Length() == 1 && !args[0]->IsObject()) return NanThrowError("One argument required - [object]"); + if(args.Length() == 2 && !args[0]->IsObject() && !args[1]->IsBoolean()) return NanThrowError("Two arguments required - [object, boolean]"); + if(args.Length() > 3) return NanThrowError("One or two arguments required - [object] or [object, boolean]"); + + // Unpack the BSON parser instance + BSON *bson = ObjectWrap::Unwrap(args.This()); + bool serializeFunctions = (args.Length() >= 2) && args[1]->BooleanValue(); + BSONSerializer countSerializer(bson, false, serializeFunctions); + countSerializer.SerializeDocument(args[0]); + + // Return the object size + NanReturnValue(NanNew((uint32_t) countSerializer.GetSerializeSize())); +} + +NAN_METHOD(BSON::SerializeWithBufferAndIndex) +{ + NanScope(); + + //BSON.serializeWithBufferAndIndex = function serializeWithBufferAndIndex(object, ->, buffer, index) { + // Ensure we have the correct values + if(args.Length() > 5) return NanThrowError("Four or five parameters required [object, boolean, Buffer, int] or [object, boolean, Buffer, int, boolean]"); + if(args.Length() == 4 && !args[0]->IsObject() && !args[1]->IsBoolean() && !Buffer::HasInstance(args[2]) && !args[3]->IsUint32()) return NanThrowError("Four parameters required [object, boolean, Buffer, int]"); + if(args.Length() == 5 && !args[0]->IsObject() && !args[1]->IsBoolean() && !Buffer::HasInstance(args[2]) && !args[3]->IsUint32() && !args[4]->IsBoolean()) return NanThrowError("Four parameters required [object, boolean, Buffer, int, boolean]"); + + uint32_t index; + size_t object_size; + + try + { + BSON *bson = ObjectWrap::Unwrap(args.This()); + + Local obj = args[2]->ToObject(); + char* data = Buffer::Data(obj); + size_t length = Buffer::Length(obj); + + index = args[3]->Uint32Value(); + bool checkKeys = args.Length() >= 4 && args[1]->IsBoolean() && args[1]->BooleanValue(); + bool serializeFunctions = (args.Length() == 5) && args[4]->BooleanValue(); + + BSONSerializer dataSerializer(bson, checkKeys, serializeFunctions, data+index); + dataSerializer.SerializeDocument(bson->GetSerializeObject(args[0])); + object_size = dataSerializer.GetSerializeSize(); + + if(object_size + index > length) return NanThrowError("Serious error - overflowed buffer!!"); + } + catch(char *exception) + { + Local error = NanNew(exception); + free(exception); + return NanThrowError(error); + } + + NanReturnValue(NanNew((uint32_t) (index + object_size - 1))); +} + +NAN_METHOD(BSON::BSONDeserializeStream) +{ + NanScope(); + + // At least 3 arguments required + if(args.Length() < 5) return NanThrowError("Arguments required (Buffer(data), Number(index in data), Number(number of documents to deserialize), Array(results), Number(index in the array), Object(optional))"); + + // If the number of argumets equals 3 + if(args.Length() >= 5) + { + if(!Buffer::HasInstance(args[0])) return NanThrowError("First argument must be Buffer instance"); + if(!args[1]->IsUint32()) return NanThrowError("Second argument must be a positive index number"); + if(!args[2]->IsUint32()) return NanThrowError("Third argument must be a positive number of documents to deserialize"); + if(!args[3]->IsArray()) return NanThrowError("Fourth argument must be an array the size of documents to deserialize"); + if(!args[4]->IsUint32()) return NanThrowError("Sixth argument must be a positive index number"); + } + + // If we have 4 arguments + if(args.Length() == 6 && !args[5]->IsObject()) return NanThrowError("Fifth argument must be an object with options"); + + // Define pointer to data + Local obj = args[0]->ToObject(); + uint32_t numberOfDocuments = args[2]->Uint32Value(); + uint32_t index = args[1]->Uint32Value(); + uint32_t resultIndex = args[4]->Uint32Value(); + bool promoteLongs = true; + + // Check for the value promoteLongs in the options object + if(args.Length() == 6) { + Local options = args[5]->ToObject(); + + // Check if we have the promoteLong variable + if(options->Has(NanNew("promoteLongs"))) { + promoteLongs = options->Get(NanNew("promoteLongs"))->ToBoolean()->Value(); + } + } + + // Unpack the BSON parser instance + BSON *bson = ObjectWrap::Unwrap(args.This()); + + // Unpack the buffer variable +#if NODE_MAJOR_VERSION == 0 && NODE_MINOR_VERSION < 3 + Local buffer = ObjectWrap::Unwrap(obj); + char* data = buffer->data(); + size_t length = buffer->length(); +#else + char* data = Buffer::Data(obj); + size_t length = Buffer::Length(obj); +#endif + + // Fetch the documents + Local documents = args[3]->ToObject(); + + BSONDeserializer deserializer(bson, data+index, length-index); + for(uint32_t i = 0; i < numberOfDocuments; i++) + { + try + { + documents->Set(i + resultIndex, deserializer.DeserializeDocument(promoteLongs)); + } + catch (char* exception) + { + Local error = NanNew(exception); + free(exception); + return NanThrowError(error); + } + } + + // Return new index of parsing + NanReturnValue(NanNew((uint32_t) (index + deserializer.GetSerializeSize()))); +} + +// Exporting function +extern "C" void init(Handle target) +{ + NanScope(); + BSON::Initialize(target); +} + +NODE_MODULE(bson, BSON::Initialize); diff --git a/node_modules/mongodb/node_modules/bson/ext/bson.h b/node_modules/mongodb/node_modules/bson/ext/bson.h new file mode 100644 index 0000000..a7feff7 --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/ext/bson.h @@ -0,0 +1,278 @@ +//=========================================================================== + +#ifndef BSON_H_ +#define BSON_H_ + +//=========================================================================== + +#ifdef __arm__ +#define USE_MISALIGNED_MEMORY_ACCESS 0 +#else +#define USE_MISALIGNED_MEMORY_ACCESS 1 +#endif + +#include +#include +#include +#include "nan.h" + +using namespace v8; +using namespace node; + +//=========================================================================== + +enum BsonType +{ + BSON_TYPE_NUMBER = 1, + BSON_TYPE_STRING = 2, + BSON_TYPE_OBJECT = 3, + BSON_TYPE_ARRAY = 4, + BSON_TYPE_BINARY = 5, + BSON_TYPE_UNDEFINED = 6, + BSON_TYPE_OID = 7, + BSON_TYPE_BOOLEAN = 8, + BSON_TYPE_DATE = 9, + BSON_TYPE_NULL = 10, + BSON_TYPE_REGEXP = 11, + BSON_TYPE_CODE = 13, + BSON_TYPE_SYMBOL = 14, + BSON_TYPE_CODE_W_SCOPE = 15, + BSON_TYPE_INT = 16, + BSON_TYPE_TIMESTAMP = 17, + BSON_TYPE_LONG = 18, + BSON_TYPE_MAX_KEY = 0x7f, + BSON_TYPE_MIN_KEY = 0xff +}; + +//=========================================================================== + +template class BSONSerializer; + +class BSON : public ObjectWrap { +public: + BSON(); + ~BSON() {} + + static void Initialize(Handle target); + static NAN_METHOD(BSONDeserializeStream); + + // JS based objects + static NAN_METHOD(BSONSerialize); + static NAN_METHOD(BSONDeserialize); + + // Calculate size of function + static NAN_METHOD(CalculateObjectSize); + static NAN_METHOD(SerializeWithBufferAndIndex); + + // Constructor used for creating new BSON objects from C++ + static Persistent constructor_template; + +private: + static NAN_METHOD(New); + static Handle deserialize(BSON *bson, char *data, uint32_t dataLength, uint32_t startIndex, bool is_array_item); + + // BSON type instantiate functions + Persistent longConstructor; + Persistent objectIDConstructor; + Persistent binaryConstructor; + Persistent codeConstructor; + Persistent dbrefConstructor; + Persistent symbolConstructor; + Persistent doubleConstructor; + Persistent timestampConstructor; + Persistent minKeyConstructor; + Persistent maxKeyConstructor; + + // Equality Objects + Persistent longString; + Persistent objectIDString; + Persistent binaryString; + Persistent codeString; + Persistent dbrefString; + Persistent symbolString; + Persistent doubleString; + Persistent timestampString; + Persistent minKeyString; + Persistent maxKeyString; + + // Equality speed up comparison objects + Persistent _bsontypeString; + Persistent _longLowString; + Persistent _longHighString; + Persistent _objectIDidString; + Persistent _binaryPositionString; + Persistent _binarySubTypeString; + Persistent _binaryBufferString; + Persistent _doubleValueString; + Persistent _symbolValueString; + + Persistent _dbRefRefString; + Persistent _dbRefIdRefString; + Persistent _dbRefDbRefString; + Persistent _dbRefNamespaceString; + Persistent _dbRefDbString; + Persistent _dbRefOidString; + + Persistent _codeCodeString; + Persistent _codeScopeString; + Persistent _toBSONString; + + Local GetSerializeObject(const Handle& object); + + template friend class BSONSerializer; + friend class BSONDeserializer; +}; + +//=========================================================================== + +class CountStream +{ +public: + CountStream() : count(0) { } + + void WriteByte(int value) { ++count; } + void WriteByte(const Handle&, const Handle&) { ++count; } + void WriteBool(const Handle& value) { ++count; } + void WriteInt32(int32_t value) { count += 4; } + void WriteInt32(const Handle& value) { count += 4; } + void WriteInt32(const Handle& object, const Handle& key) { count += 4; } + void WriteInt64(int64_t value) { count += 8; } + void WriteInt64(const Handle& value) { count += 8; } + void WriteDouble(double value) { count += 8; } + void WriteDouble(const Handle& value) { count += 8; } + void WriteDouble(const Handle&, const Handle&) { count += 8; } + void WriteUInt32String(uint32_t name) { char buffer[32]; count += sprintf(buffer, "%u", name) + 1; } + void WriteLengthPrefixedString(const Local& value) { count += value->Utf8Length()+5; } + void WriteObjectId(const Handle& object, const Handle& key) { count += 12; } + void WriteString(const Local& value) { count += value->Utf8Length() + 1; } // This returns the number of bytes exclusive of the NULL terminator + void WriteData(const char* data, size_t length) { count += length; } + + void* BeginWriteType() { ++count; return NULL; } + void CommitType(void*, BsonType) { } + void* BeginWriteSize() { count += 4; return NULL; } + void CommitSize(void*) { } + + size_t GetSerializeSize() const { return count; } + + // Do nothing. CheckKey is implemented for DataStream + void CheckKey(const Local&) { } + +private: + size_t count; +}; + +class DataStream +{ +public: + DataStream(char* aDestinationBuffer) : destinationBuffer(aDestinationBuffer), p(aDestinationBuffer) { } + + void WriteByte(int value) { *p++ = value; } + void WriteByte(const Handle& object, const Handle& key) { *p++ = object->Get(key)->Int32Value(); } +#if USE_MISALIGNED_MEMORY_ACCESS + void WriteInt32(int32_t value) { *reinterpret_cast(p) = value; p += 4; } + void WriteInt64(int64_t value) { *reinterpret_cast(p) = value; p += 8; } + void WriteDouble(double value) { *reinterpret_cast(p) = value; p += 8; } +#else + void WriteInt32(int32_t value) { memcpy(p, &value, 4); p += 4; } + void WriteInt64(int64_t value) { memcpy(p, &value, 8); p += 8; } + void WriteDouble(double value) { memcpy(p, &value, 8); p += 8; } +#endif + void WriteBool(const Handle& value) { WriteByte(value->BooleanValue() ? 1 : 0); } + void WriteInt32(const Handle& value) { WriteInt32(value->Int32Value()); } + void WriteInt32(const Handle& object, const Handle& key) { WriteInt32(object->Get(key)); } + void WriteInt64(const Handle& value) { WriteInt64(value->IntegerValue()); } + void WriteDouble(const Handle& value) { WriteDouble(value->NumberValue()); } + void WriteDouble(const Handle& object, const Handle& key) { WriteDouble(object->Get(key)); } + void WriteUInt32String(uint32_t name) { p += sprintf(p, "%u", name) + 1; } + void WriteLengthPrefixedString(const Local& value) { WriteInt32(value->Utf8Length()+1); WriteString(value); } + void WriteObjectId(const Handle& object, const Handle& key); + void WriteString(const Local& value) { p += value->WriteUtf8(p); } // This returns the number of bytes inclusive of the NULL terminator. + void WriteData(const char* data, size_t length) { memcpy(p, data, length); p += length; } + + void* BeginWriteType() { void* returnValue = p; p++; return returnValue; } + void CommitType(void* beginPoint, BsonType value) { *reinterpret_cast(beginPoint) = value; } + void* BeginWriteSize() { void* returnValue = p; p += 4; return returnValue; } + +#if USE_MISALIGNED_MEMORY_ACCESS + void CommitSize(void* beginPoint) { *reinterpret_cast(beginPoint) = (int32_t) (p - (char*) beginPoint); } +#else + void CommitSize(void* beginPoint) { int32_t value = (int32_t) (p - (char*) beginPoint); memcpy(beginPoint, &value, 4); } +#endif + + size_t GetSerializeSize() const { return p - destinationBuffer; } + + void CheckKey(const Local& keyName); + +protected: + char *const destinationBuffer; // base, never changes + char* p; // cursor into buffer +}; + +template class BSONSerializer : public T +{ +private: + typedef T Inherited; + +public: + BSONSerializer(BSON* aBson, bool aCheckKeys, bool aSerializeFunctions) : Inherited(), checkKeys(aCheckKeys), serializeFunctions(aSerializeFunctions), bson(aBson) { } + BSONSerializer(BSON* aBson, bool aCheckKeys, bool aSerializeFunctions, char* parentParam) : Inherited(parentParam), checkKeys(aCheckKeys), serializeFunctions(aSerializeFunctions), bson(aBson) { } + + void SerializeDocument(const Handle& value); + void SerializeArray(const Handle& value); + void SerializeValue(void* typeLocation, const Handle value); + +private: + bool checkKeys; + bool serializeFunctions; + BSON* bson; +}; + +//=========================================================================== + +class BSONDeserializer +{ +public: + BSONDeserializer(BSON* aBson, char* data, size_t length); + BSONDeserializer(BSONDeserializer& parentSerializer, size_t length); + + Handle DeserializeDocument(bool promoteLongs); + + bool HasMoreData() const { return p < pEnd; } + Handle ReadCString(); + uint32_t ReadIntegerString(); + int32_t ReadRegexOptions(); + Local ReadString(); + Local ReadObjectId(); + + unsigned char ReadByte() { return *reinterpret_cast(p++); } +#if USE_MISALIGNED_MEMORY_ACCESS + int32_t ReadInt32() { int32_t returnValue = *reinterpret_cast(p); p += 4; return returnValue; } + uint32_t ReadUInt32() { uint32_t returnValue = *reinterpret_cast(p); p += 4; return returnValue; } + int64_t ReadInt64() { int64_t returnValue = *reinterpret_cast(p); p += 8; return returnValue; } + double ReadDouble() { double returnValue = *reinterpret_cast(p); p += 8; return returnValue; } +#else + int32_t ReadInt32() { int32_t returnValue; memcpy(&returnValue, p, 4); p += 4; return returnValue; } + uint32_t ReadUInt32() { uint32_t returnValue; memcpy(&returnValue, p, 4); p += 4; return returnValue; } + int64_t ReadInt64() { int64_t returnValue; memcpy(&returnValue, p, 8); p += 8; return returnValue; } + double ReadDouble() { double returnValue; memcpy(&returnValue, p, 8); p += 8; return returnValue; } +#endif + + size_t GetSerializeSize() const { return p - pStart; } + +private: + Handle DeserializeArray(bool promoteLongs); + Handle DeserializeValue(BsonType type, bool promoteLongs); + Handle DeserializeDocumentInternal(bool promoteLongs); + Handle DeserializeArrayInternal(bool promoteLongs); + + BSON* bson; + char* const pStart; + char* p; + char* const pEnd; +}; + +//=========================================================================== + +#endif // BSON_H_ + +//=========================================================================== diff --git a/node_modules/mongodb/node_modules/bson/ext/index.js b/node_modules/mongodb/node_modules/bson/ext/index.js new file mode 100644 index 0000000..af4d9a5 --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/ext/index.js @@ -0,0 +1,40 @@ +var bson = null; + +try { + // Load the precompiled win32 binary + if(process.platform == "win32" && process.arch == "x64") { + bson = require('./win32/x64/bson'); + } else if(process.platform == "win32" && process.arch == "ia32") { + bson = require('./win32/ia32/bson'); + } else { + bson = require('../build/Release/bson'); + } +} catch(err) { + // Attempt to load the release bson version + try { + bson = require('../build/Release/bson'); + } catch (err) { + console.error("js-bson: Failed to load c++ bson extension, using pure JS version"); + bson = require('../lib/bson/bson'); + } +} + +exports.BSON = bson.BSON; +exports.Long = require('../lib/bson/long').Long; +exports.ObjectID = require('../lib/bson/objectid').ObjectID; +exports.DBRef = require('../lib/bson/db_ref').DBRef; +exports.Code = require('../lib/bson/code').Code; +exports.Timestamp = require('../lib/bson/timestamp').Timestamp; +exports.Binary = require('../lib/bson/binary').Binary; +exports.Double = require('../lib/bson/double').Double; +exports.MaxKey = require('../lib/bson/max_key').MaxKey; +exports.MinKey = require('../lib/bson/min_key').MinKey; +exports.Symbol = require('../lib/bson/symbol').Symbol; + +// Just add constants tot he Native BSON parser +exports.BSON.BSON_BINARY_SUBTYPE_DEFAULT = 0; +exports.BSON.BSON_BINARY_SUBTYPE_FUNCTION = 1; +exports.BSON.BSON_BINARY_SUBTYPE_BYTE_ARRAY = 2; +exports.BSON.BSON_BINARY_SUBTYPE_UUID = 3; +exports.BSON.BSON_BINARY_SUBTYPE_MD5 = 4; +exports.BSON.BSON_BINARY_SUBTYPE_USER_DEFINED = 128; diff --git a/node_modules/mongodb/node_modules/bson/ext/win32/ia32/bson.node b/node_modules/mongodb/node_modules/bson/ext/win32/ia32/bson.node new file mode 100644 index 0000000000000000000000000000000000000000..7f54835e7d9cdef60f29f9a6a6397eedc586c535 GIT binary patch literal 113664 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 255) throw new Error("only accepts number in a valid unsigned byte range 0-255"); + + // Decode the byte value once + var decoded_byte = null; + if(typeof byte_value == 'string') { + decoded_byte = byte_value.charCodeAt(0); + } else if(byte_value['length'] != null) { + decoded_byte = byte_value[0]; + } else { + decoded_byte = byte_value; + } + + if(this.buffer.length > this.position) { + this.buffer[this.position++] = decoded_byte; + } else { + if(typeof Buffer != 'undefined' && Buffer.isBuffer(this.buffer)) { + // Create additional overflow buffer + var buffer = new Buffer(Binary.BUFFER_SIZE + this.buffer.length); + // Combine the two buffers together + this.buffer.copy(buffer, 0, 0, this.buffer.length); + this.buffer = buffer; + this.buffer[this.position++] = decoded_byte; + } else { + var buffer = null; + // Create a new buffer (typed or normal array) + if(Object.prototype.toString.call(this.buffer) == '[object Uint8Array]') { + buffer = new Uint8Array(new ArrayBuffer(Binary.BUFFER_SIZE + this.buffer.length)); + } else { + buffer = new Array(Binary.BUFFER_SIZE + this.buffer.length); + } + + // We need to copy all the content to the new array + for(var i = 0; i < this.buffer.length; i++) { + buffer[i] = this.buffer[i]; + } + + // Reassign the buffer + this.buffer = buffer; + // Write the byte + this.buffer[this.position++] = decoded_byte; + } + } +}; + +/** + * Writes a buffer or string to the binary. + * + * @param {Buffer|String} string a string or buffer to be written to the Binary BSON object. + * @param {Number} offset specify the binary of where to write the content. + * @api public + */ +Binary.prototype.write = function write(string, offset) { + offset = typeof offset == 'number' ? offset : this.position; + + // If the buffer is to small let's extend the buffer + if(this.buffer.length < offset + string.length) { + var buffer = null; + // If we are in node.js + if(typeof Buffer != 'undefined' && Buffer.isBuffer(this.buffer)) { + buffer = new Buffer(this.buffer.length + string.length); + this.buffer.copy(buffer, 0, 0, this.buffer.length); + } else if(Object.prototype.toString.call(this.buffer) == '[object Uint8Array]') { + // Create a new buffer + buffer = new Uint8Array(new ArrayBuffer(this.buffer.length + string.length)) + // Copy the content + for(var i = 0; i < this.position; i++) { + buffer[i] = this.buffer[i]; + } + } + + // Assign the new buffer + this.buffer = buffer; + } + + if(typeof Buffer != 'undefined' && Buffer.isBuffer(string) && Buffer.isBuffer(this.buffer)) { + string.copy(this.buffer, offset, 0, string.length); + this.position = (offset + string.length) > this.position ? (offset + string.length) : this.position; + // offset = string.length + } else if(typeof Buffer != 'undefined' && typeof string == 'string' && Buffer.isBuffer(this.buffer)) { + this.buffer.write(string, 'binary', offset); + this.position = (offset + string.length) > this.position ? (offset + string.length) : this.position; + // offset = string.length; + } else if(Object.prototype.toString.call(string) == '[object Uint8Array]' + || Object.prototype.toString.call(string) == '[object Array]' && typeof string != 'string') { + for(var i = 0; i < string.length; i++) { + this.buffer[offset++] = string[i]; + } + + this.position = offset > this.position ? offset : this.position; + } else if(typeof string == 'string') { + for(var i = 0; i < string.length; i++) { + this.buffer[offset++] = string.charCodeAt(i); + } + + this.position = offset > this.position ? offset : this.position; + } +}; + +/** + * Reads **length** bytes starting at **position**. + * + * @param {Number} position read from the given position in the Binary. + * @param {Number} length the number of bytes to read. + * @return {Buffer} + * @api public + */ +Binary.prototype.read = function read(position, length) { + length = length && length > 0 + ? length + : this.position; + + // Let's return the data based on the type we have + if(this.buffer['slice']) { + return this.buffer.slice(position, position + length); + } else { + // Create a buffer to keep the result + var buffer = typeof Uint8Array != 'undefined' ? new Uint8Array(new ArrayBuffer(length)) : new Array(length); + for(var i = 0; i < length; i++) { + buffer[i] = this.buffer[position++]; + } + } + // Return the buffer + return buffer; +}; + +/** + * Returns the value of this binary as a string. + * + * @return {String} + * @api public + */ +Binary.prototype.value = function value(asRaw) { + asRaw = asRaw == null ? false : asRaw; + + // Optimize to serialize for the situation where the data == size of buffer + if(asRaw && typeof Buffer != 'undefined' && Buffer.isBuffer(this.buffer) && this.buffer.length == this.position) + return this.buffer; + + // If it's a node.js buffer object + if(typeof Buffer != 'undefined' && Buffer.isBuffer(this.buffer)) { + return asRaw ? this.buffer.slice(0, this.position) : this.buffer.toString('binary', 0, this.position); + } else { + if(asRaw) { + // we support the slice command use it + if(this.buffer['slice'] != null) { + return this.buffer.slice(0, this.position); + } else { + // Create a new buffer to copy content to + var newBuffer = Object.prototype.toString.call(this.buffer) == '[object Uint8Array]' ? new Uint8Array(new ArrayBuffer(this.position)) : new Array(this.position); + // Copy content + for(var i = 0; i < this.position; i++) { + newBuffer[i] = this.buffer[i]; + } + // Return the buffer + return newBuffer; + } + } else { + return convertArraytoUtf8BinaryString(this.buffer, 0, this.position); + } + } +}; + +/** + * Length. + * + * @return {Number} the length of the binary. + * @api public + */ +Binary.prototype.length = function length() { + return this.position; +}; + +/** + * @ignore + * @api private + */ +Binary.prototype.toJSON = function() { + return this.buffer != null ? this.buffer.toString('base64') : ''; +} + +/** + * @ignore + * @api private + */ +Binary.prototype.toString = function(format) { + return this.buffer != null ? this.buffer.slice(0, this.position).toString(format) : ''; +} + +Binary.BUFFER_SIZE = 256; + +/** + * Default BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_DEFAULT = 0; +/** + * Function BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_FUNCTION = 1; +/** + * Byte Array BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_BYTE_ARRAY = 2; +/** + * OLD UUID BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_UUID_OLD = 3; +/** + * UUID BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_UUID = 4; +/** + * MD5 BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_MD5 = 5; +/** + * User BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_USER_DEFINED = 128; + +/** + * Expose. + */ +exports.Binary = Binary; + diff --git a/node_modules/mongodb/node_modules/bson/lib/bson/binary_parser.js b/node_modules/mongodb/node_modules/bson/lib/bson/binary_parser.js new file mode 100644 index 0000000..d2fc811 --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/lib/bson/binary_parser.js @@ -0,0 +1,385 @@ +/** + * Binary Parser. + * Jonas Raoni Soares Silva + * http://jsfromhell.com/classes/binary-parser [v1.0] + */ +var chr = String.fromCharCode; + +var maxBits = []; +for (var i = 0; i < 64; i++) { + maxBits[i] = Math.pow(2, i); +} + +function BinaryParser (bigEndian, allowExceptions) { + if(!(this instanceof BinaryParser)) return new BinaryParser(bigEndian, allowExceptions); + + this.bigEndian = bigEndian; + this.allowExceptions = allowExceptions; +}; + +BinaryParser.warn = function warn (msg) { + if (this.allowExceptions) { + throw new Error(msg); + } + + return 1; +}; + +BinaryParser.decodeFloat = function decodeFloat (data, precisionBits, exponentBits) { + var b = new this.Buffer(this.bigEndian, data); + + b.checkBuffer(precisionBits + exponentBits + 1); + + var bias = maxBits[exponentBits - 1] - 1 + , signal = b.readBits(precisionBits + exponentBits, 1) + , exponent = b.readBits(precisionBits, exponentBits) + , significand = 0 + , divisor = 2 + , curByte = b.buffer.length + (-precisionBits >> 3) - 1; + + do { + for (var byteValue = b.buffer[ ++curByte ], startBit = precisionBits % 8 || 8, mask = 1 << startBit; mask >>= 1; ( byteValue & mask ) && ( significand += 1 / divisor ), divisor *= 2 ); + } while (precisionBits -= startBit); + + return exponent == ( bias << 1 ) + 1 ? significand ? NaN : signal ? -Infinity : +Infinity : ( 1 + signal * -2 ) * ( exponent || significand ? !exponent ? Math.pow( 2, -bias + 1 ) * significand : Math.pow( 2, exponent - bias ) * ( 1 + significand ) : 0 ); +}; + +BinaryParser.decodeInt = function decodeInt (data, bits, signed, forceBigEndian) { + var b = new this.Buffer(this.bigEndian || forceBigEndian, data) + , x = b.readBits(0, bits) + , max = maxBits[bits]; //max = Math.pow( 2, bits ); + + return signed && x >= max / 2 + ? x - max + : x; +}; + +BinaryParser.encodeFloat = function encodeFloat (data, precisionBits, exponentBits) { + var bias = maxBits[exponentBits - 1] - 1 + , minExp = -bias + 1 + , maxExp = bias + , minUnnormExp = minExp - precisionBits + , n = parseFloat(data) + , status = isNaN(n) || n == -Infinity || n == +Infinity ? n : 0 + , exp = 0 + , len = 2 * bias + 1 + precisionBits + 3 + , bin = new Array(len) + , signal = (n = status !== 0 ? 0 : n) < 0 + , intPart = Math.floor(n = Math.abs(n)) + , floatPart = n - intPart + , lastBit + , rounded + , result + , i + , j; + + for (i = len; i; bin[--i] = 0); + + for (i = bias + 2; intPart && i; bin[--i] = intPart % 2, intPart = Math.floor(intPart / 2)); + + for (i = bias + 1; floatPart > 0 && i; (bin[++i] = ((floatPart *= 2) >= 1) - 0 ) && --floatPart); + + for (i = -1; ++i < len && !bin[i];); + + if (bin[(lastBit = precisionBits - 1 + (i = (exp = bias + 1 - i) >= minExp && exp <= maxExp ? i + 1 : bias + 1 - (exp = minExp - 1))) + 1]) { + if (!(rounded = bin[lastBit])) { + for (j = lastBit + 2; !rounded && j < len; rounded = bin[j++]); + } + + for (j = lastBit + 1; rounded && --j >= 0; (bin[j] = !bin[j] - 0) && (rounded = 0)); + } + + for (i = i - 2 < 0 ? -1 : i - 3; ++i < len && !bin[i];); + + if ((exp = bias + 1 - i) >= minExp && exp <= maxExp) { + ++i; + } else if (exp < minExp) { + exp != bias + 1 - len && exp < minUnnormExp && this.warn("encodeFloat::float underflow"); + i = bias + 1 - (exp = minExp - 1); + } + + if (intPart || status !== 0) { + this.warn(intPart ? "encodeFloat::float overflow" : "encodeFloat::" + status); + exp = maxExp + 1; + i = bias + 2; + + if (status == -Infinity) { + signal = 1; + } else if (isNaN(status)) { + bin[i] = 1; + } + } + + for (n = Math.abs(exp + bias), j = exponentBits + 1, result = ""; --j; result = (n % 2) + result, n = n >>= 1); + + for (n = 0, j = 0, i = (result = (signal ? "1" : "0") + result + bin.slice(i, i + precisionBits).join("")).length, r = []; i; j = (j + 1) % 8) { + n += (1 << j) * result.charAt(--i); + if (j == 7) { + r[r.length] = String.fromCharCode(n); + n = 0; + } + } + + r[r.length] = n + ? String.fromCharCode(n) + : ""; + + return (this.bigEndian ? r.reverse() : r).join(""); +}; + +BinaryParser.encodeInt = function encodeInt (data, bits, signed, forceBigEndian) { + var max = maxBits[bits]; + + if (data >= max || data < -(max / 2)) { + this.warn("encodeInt::overflow"); + data = 0; + } + + if (data < 0) { + data += max; + } + + for (var r = []; data; r[r.length] = String.fromCharCode(data % 256), data = Math.floor(data / 256)); + + for (bits = -(-bits >> 3) - r.length; bits--; r[r.length] = "\0"); + + return ((this.bigEndian || forceBigEndian) ? r.reverse() : r).join(""); +}; + +BinaryParser.toSmall = function( data ){ return this.decodeInt( data, 8, true ); }; +BinaryParser.fromSmall = function( data ){ return this.encodeInt( data, 8, true ); }; +BinaryParser.toByte = function( data ){ return this.decodeInt( data, 8, false ); }; +BinaryParser.fromByte = function( data ){ return this.encodeInt( data, 8, false ); }; +BinaryParser.toShort = function( data ){ return this.decodeInt( data, 16, true ); }; +BinaryParser.fromShort = function( data ){ return this.encodeInt( data, 16, true ); }; +BinaryParser.toWord = function( data ){ return this.decodeInt( data, 16, false ); }; +BinaryParser.fromWord = function( data ){ return this.encodeInt( data, 16, false ); }; +BinaryParser.toInt = function( data ){ return this.decodeInt( data, 32, true ); }; +BinaryParser.fromInt = function( data ){ return this.encodeInt( data, 32, true ); }; +BinaryParser.toLong = function( data ){ return this.decodeInt( data, 64, true ); }; +BinaryParser.fromLong = function( data ){ return this.encodeInt( data, 64, true ); }; +BinaryParser.toDWord = function( data ){ return this.decodeInt( data, 32, false ); }; +BinaryParser.fromDWord = function( data ){ return this.encodeInt( data, 32, false ); }; +BinaryParser.toQWord = function( data ){ return this.decodeInt( data, 64, true ); }; +BinaryParser.fromQWord = function( data ){ return this.encodeInt( data, 64, true ); }; +BinaryParser.toFloat = function( data ){ return this.decodeFloat( data, 23, 8 ); }; +BinaryParser.fromFloat = function( data ){ return this.encodeFloat( data, 23, 8 ); }; +BinaryParser.toDouble = function( data ){ return this.decodeFloat( data, 52, 11 ); }; +BinaryParser.fromDouble = function( data ){ return this.encodeFloat( data, 52, 11 ); }; + +// Factor out the encode so it can be shared by add_header and push_int32 +BinaryParser.encode_int32 = function encode_int32 (number, asArray) { + var a, b, c, d, unsigned; + unsigned = (number < 0) ? (number + 0x100000000) : number; + a = Math.floor(unsigned / 0xffffff); + unsigned &= 0xffffff; + b = Math.floor(unsigned / 0xffff); + unsigned &= 0xffff; + c = Math.floor(unsigned / 0xff); + unsigned &= 0xff; + d = Math.floor(unsigned); + return asArray ? [chr(a), chr(b), chr(c), chr(d)] : chr(a) + chr(b) + chr(c) + chr(d); +}; + +BinaryParser.encode_int64 = function encode_int64 (number) { + var a, b, c, d, e, f, g, h, unsigned; + unsigned = (number < 0) ? (number + 0x10000000000000000) : number; + a = Math.floor(unsigned / 0xffffffffffffff); + unsigned &= 0xffffffffffffff; + b = Math.floor(unsigned / 0xffffffffffff); + unsigned &= 0xffffffffffff; + c = Math.floor(unsigned / 0xffffffffff); + unsigned &= 0xffffffffff; + d = Math.floor(unsigned / 0xffffffff); + unsigned &= 0xffffffff; + e = Math.floor(unsigned / 0xffffff); + unsigned &= 0xffffff; + f = Math.floor(unsigned / 0xffff); + unsigned &= 0xffff; + g = Math.floor(unsigned / 0xff); + unsigned &= 0xff; + h = Math.floor(unsigned); + return chr(a) + chr(b) + chr(c) + chr(d) + chr(e) + chr(f) + chr(g) + chr(h); +}; + +/** + * UTF8 methods + */ + +// Take a raw binary string and return a utf8 string +BinaryParser.decode_utf8 = function decode_utf8 (binaryStr) { + var len = binaryStr.length + , decoded = '' + , i = 0 + , c = 0 + , c1 = 0 + , c2 = 0 + , c3; + + while (i < len) { + c = binaryStr.charCodeAt(i); + if (c < 128) { + decoded += String.fromCharCode(c); + i++; + } else if ((c > 191) && (c < 224)) { + c2 = binaryStr.charCodeAt(i+1); + decoded += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); + i += 2; + } else { + c2 = binaryStr.charCodeAt(i+1); + c3 = binaryStr.charCodeAt(i+2); + decoded += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); + i += 3; + } + } + + return decoded; +}; + +// Encode a cstring +BinaryParser.encode_cstring = function encode_cstring (s) { + return unescape(encodeURIComponent(s)) + BinaryParser.fromByte(0); +}; + +// Take a utf8 string and return a binary string +BinaryParser.encode_utf8 = function encode_utf8 (s) { + var a = "" + , c; + + for (var n = 0, len = s.length; n < len; n++) { + c = s.charCodeAt(n); + + if (c < 128) { + a += String.fromCharCode(c); + } else if ((c > 127) && (c < 2048)) { + a += String.fromCharCode((c>>6) | 192) ; + a += String.fromCharCode((c&63) | 128); + } else { + a += String.fromCharCode((c>>12) | 224); + a += String.fromCharCode(((c>>6) & 63) | 128); + a += String.fromCharCode((c&63) | 128); + } + } + + return a; +}; + +BinaryParser.hprint = function hprint (s) { + var number; + + for (var i = 0, len = s.length; i < len; i++) { + if (s.charCodeAt(i) < 32) { + number = s.charCodeAt(i) <= 15 + ? "0" + s.charCodeAt(i).toString(16) + : s.charCodeAt(i).toString(16); + process.stdout.write(number + " ") + } else { + number = s.charCodeAt(i) <= 15 + ? "0" + s.charCodeAt(i).toString(16) + : s.charCodeAt(i).toString(16); + process.stdout.write(number + " ") + } + } + + process.stdout.write("\n\n"); +}; + +BinaryParser.ilprint = function hprint (s) { + var number; + + for (var i = 0, len = s.length; i < len; i++) { + if (s.charCodeAt(i) < 32) { + number = s.charCodeAt(i) <= 15 + ? "0" + s.charCodeAt(i).toString(10) + : s.charCodeAt(i).toString(10); + + require('util').debug(number+' : '); + } else { + number = s.charCodeAt(i) <= 15 + ? "0" + s.charCodeAt(i).toString(10) + : s.charCodeAt(i).toString(10); + require('util').debug(number+' : '+ s.charAt(i)); + } + } +}; + +BinaryParser.hlprint = function hprint (s) { + var number; + + for (var i = 0, len = s.length; i < len; i++) { + if (s.charCodeAt(i) < 32) { + number = s.charCodeAt(i) <= 15 + ? "0" + s.charCodeAt(i).toString(16) + : s.charCodeAt(i).toString(16); + require('util').debug(number+' : '); + } else { + number = s.charCodeAt(i) <= 15 + ? "0" + s.charCodeAt(i).toString(16) + : s.charCodeAt(i).toString(16); + require('util').debug(number+' : '+ s.charAt(i)); + } + } +}; + +/** + * BinaryParser buffer constructor. + */ +function BinaryParserBuffer (bigEndian, buffer) { + this.bigEndian = bigEndian || 0; + this.buffer = []; + this.setBuffer(buffer); +}; + +BinaryParserBuffer.prototype.setBuffer = function setBuffer (data) { + var l, i, b; + + if (data) { + i = l = data.length; + b = this.buffer = new Array(l); + for (; i; b[l - i] = data.charCodeAt(--i)); + this.bigEndian && b.reverse(); + } +}; + +BinaryParserBuffer.prototype.hasNeededBits = function hasNeededBits (neededBits) { + return this.buffer.length >= -(-neededBits >> 3); +}; + +BinaryParserBuffer.prototype.checkBuffer = function checkBuffer (neededBits) { + if (!this.hasNeededBits(neededBits)) { + throw new Error("checkBuffer::missing bytes"); + } +}; + +BinaryParserBuffer.prototype.readBits = function readBits (start, length) { + //shl fix: Henri Torgemane ~1996 (compressed by Jonas Raoni) + + function shl (a, b) { + for (; b--; a = ((a %= 0x7fffffff + 1) & 0x40000000) == 0x40000000 ? a * 2 : (a - 0x40000000) * 2 + 0x7fffffff + 1); + return a; + } + + if (start < 0 || length <= 0) { + return 0; + } + + this.checkBuffer(start + length); + + var offsetLeft + , offsetRight = start % 8 + , curByte = this.buffer.length - ( start >> 3 ) - 1 + , lastByte = this.buffer.length + ( -( start + length ) >> 3 ) + , diff = curByte - lastByte + , sum = ((this.buffer[ curByte ] >> offsetRight) & ((1 << (diff ? 8 - offsetRight : length)) - 1)) + (diff && (offsetLeft = (start + length) % 8) ? (this.buffer[lastByte++] & ((1 << offsetLeft) - 1)) << (diff-- << 3) - offsetRight : 0); + + for(; diff; sum += shl(this.buffer[lastByte++], (diff-- << 3) - offsetRight)); + + return sum; +}; + +/** + * Expose. + */ +BinaryParser.Buffer = BinaryParserBuffer; + +exports.BinaryParser = BinaryParser; diff --git a/node_modules/mongodb/node_modules/bson/lib/bson/bson.js b/node_modules/mongodb/node_modules/bson/lib/bson/bson.js new file mode 100644 index 0000000..e0590e8 --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/lib/bson/bson.js @@ -0,0 +1,1573 @@ +var Long = require('./long').Long + , Double = require('./double').Double + , Timestamp = require('./timestamp').Timestamp + , ObjectID = require('./objectid').ObjectID + , Symbol = require('./symbol').Symbol + , Code = require('./code').Code + , MinKey = require('./min_key').MinKey + , MaxKey = require('./max_key').MaxKey + , DBRef = require('./db_ref').DBRef + , Binary = require('./binary').Binary + , BinaryParser = require('./binary_parser').BinaryParser + , writeIEEE754 = require('./float_parser').writeIEEE754 + , readIEEE754 = require('./float_parser').readIEEE754 + +// To ensure that 0.4 of node works correctly +var isDate = function isDate(d) { + return typeof d === 'object' && Object.prototype.toString.call(d) === '[object Date]'; +} + +/** + * Create a new BSON instance + * + * @class Represents the BSON Parser + * @return {BSON} instance of BSON Parser. + */ +function BSON () {}; + +/** + * @ignore + * @api private + */ +// BSON MAX VALUES +BSON.BSON_INT32_MAX = 0x7FFFFFFF; +BSON.BSON_INT32_MIN = -0x80000000; + +BSON.BSON_INT64_MAX = Math.pow(2, 63) - 1; +BSON.BSON_INT64_MIN = -Math.pow(2, 63); + +// JS MAX PRECISE VALUES +BSON.JS_INT_MAX = 0x20000000000000; // Any integer up to 2^53 can be precisely represented by a double. +BSON.JS_INT_MIN = -0x20000000000000; // Any integer down to -2^53 can be precisely represented by a double. + +// Internal long versions +var JS_INT_MAX_LONG = Long.fromNumber(0x20000000000000); // Any integer up to 2^53 can be precisely represented by a double. +var JS_INT_MIN_LONG = Long.fromNumber(-0x20000000000000); // Any integer down to -2^53 can be precisely represented by a double. + +/** + * Number BSON Type + * + * @classconstant BSON_DATA_NUMBER + **/ +BSON.BSON_DATA_NUMBER = 1; +/** + * String BSON Type + * + * @classconstant BSON_DATA_STRING + **/ +BSON.BSON_DATA_STRING = 2; +/** + * Object BSON Type + * + * @classconstant BSON_DATA_OBJECT + **/ +BSON.BSON_DATA_OBJECT = 3; +/** + * Array BSON Type + * + * @classconstant BSON_DATA_ARRAY + **/ +BSON.BSON_DATA_ARRAY = 4; +/** + * Binary BSON Type + * + * @classconstant BSON_DATA_BINARY + **/ +BSON.BSON_DATA_BINARY = 5; +/** + * Binary BSON Type + * + * @classconstant BSON_DATA_UNDEFINED + **/ +BSON.BSON_DATA_UNDEFINED = 6; +/** + * ObjectID BSON Type + * + * @classconstant BSON_DATA_OID + **/ +BSON.BSON_DATA_OID = 7; +/** + * Boolean BSON Type + * + * @classconstant BSON_DATA_BOOLEAN + **/ +BSON.BSON_DATA_BOOLEAN = 8; +/** + * Date BSON Type + * + * @classconstant BSON_DATA_DATE + **/ +BSON.BSON_DATA_DATE = 9; +/** + * null BSON Type + * + * @classconstant BSON_DATA_NULL + **/ +BSON.BSON_DATA_NULL = 10; +/** + * RegExp BSON Type + * + * @classconstant BSON_DATA_REGEXP + **/ +BSON.BSON_DATA_REGEXP = 11; +/** + * Code BSON Type + * + * @classconstant BSON_DATA_CODE + **/ +BSON.BSON_DATA_CODE = 13; +/** + * Symbol BSON Type + * + * @classconstant BSON_DATA_SYMBOL + **/ +BSON.BSON_DATA_SYMBOL = 14; +/** + * Code with Scope BSON Type + * + * @classconstant BSON_DATA_CODE_W_SCOPE + **/ +BSON.BSON_DATA_CODE_W_SCOPE = 15; +/** + * 32 bit Integer BSON Type + * + * @classconstant BSON_DATA_INT + **/ +BSON.BSON_DATA_INT = 16; +/** + * Timestamp BSON Type + * + * @classconstant BSON_DATA_TIMESTAMP + **/ +BSON.BSON_DATA_TIMESTAMP = 17; +/** + * Long BSON Type + * + * @classconstant BSON_DATA_LONG + **/ +BSON.BSON_DATA_LONG = 18; +/** + * MinKey BSON Type + * + * @classconstant BSON_DATA_MIN_KEY + **/ +BSON.BSON_DATA_MIN_KEY = 0xff; +/** + * MaxKey BSON Type + * + * @classconstant BSON_DATA_MAX_KEY + **/ +BSON.BSON_DATA_MAX_KEY = 0x7f; + +/** + * Binary Default Type + * + * @classconstant BSON_BINARY_SUBTYPE_DEFAULT + **/ +BSON.BSON_BINARY_SUBTYPE_DEFAULT = 0; +/** + * Binary Function Type + * + * @classconstant BSON_BINARY_SUBTYPE_FUNCTION + **/ +BSON.BSON_BINARY_SUBTYPE_FUNCTION = 1; +/** + * Binary Byte Array Type + * + * @classconstant BSON_BINARY_SUBTYPE_BYTE_ARRAY + **/ +BSON.BSON_BINARY_SUBTYPE_BYTE_ARRAY = 2; +/** + * Binary UUID Type + * + * @classconstant BSON_BINARY_SUBTYPE_UUID + **/ +BSON.BSON_BINARY_SUBTYPE_UUID = 3; +/** + * Binary MD5 Type + * + * @classconstant BSON_BINARY_SUBTYPE_MD5 + **/ +BSON.BSON_BINARY_SUBTYPE_MD5 = 4; +/** + * Binary User Defined Type + * + * @classconstant BSON_BINARY_SUBTYPE_USER_DEFINED + **/ +BSON.BSON_BINARY_SUBTYPE_USER_DEFINED = 128; + +/** + * Calculate the bson size for a passed in Javascript object. + * + * @param {Object} object the Javascript object to calculate the BSON byte size for. + * @param {Boolean} [serializeFunctions] serialize all functions in the object **(default:false)**. + * @return {Number} returns the number of bytes the BSON object will take up. + * @api public + */ +BSON.calculateObjectSize = function calculateObjectSize(object, serializeFunctions) { + var totalLength = (4 + 1); + + if(Array.isArray(object)) { + for(var i = 0; i < object.length; i++) { + totalLength += calculateElement(i.toString(), object[i], serializeFunctions) + } + } else { + // If we have toBSON defined, override the current object + if(object.toBSON) { + object = object.toBSON(); + } + + // Calculate size + for(var key in object) { + totalLength += calculateElement(key, object[key], serializeFunctions) + } + } + + return totalLength; +} + +/** + * @ignore + * @api private + */ +function calculateElement(name, value, serializeFunctions) { + var isBuffer = typeof Buffer !== 'undefined'; + + // If we have toBSON defined, override the current object + if(value && value.toBSON){ + value = value.toBSON(); + } + + switch(typeof value) { + case 'string': + return 1 + (!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1 + 4 + (!isBuffer ? numberOfBytes(value) : Buffer.byteLength(value, 'utf8')) + 1; + case 'number': + if(Math.floor(value) === value && value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) { + if(value >= BSON.BSON_INT32_MIN && value <= BSON.BSON_INT32_MAX) { // 32 bit + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (4 + 1); + } else { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (8 + 1); + } + } else { // 64 bit + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (8 + 1); + } + case 'undefined': + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (1); + case 'boolean': + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (1 + 1); + case 'object': + if(value == null || value instanceof MinKey || value instanceof MaxKey || value['_bsontype'] == 'MinKey' || value['_bsontype'] == 'MaxKey') { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (1); + } else if(value instanceof ObjectID || value['_bsontype'] == 'ObjectID') { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (12 + 1); + } else if(value instanceof Date || isDate(value)) { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (8 + 1); + } else if(typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (1 + 4 + 1) + value.length; + } else if(value instanceof Long || value instanceof Double || value instanceof Timestamp + || value['_bsontype'] == 'Long' || value['_bsontype'] == 'Double' || value['_bsontype'] == 'Timestamp') { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (8 + 1); + } else if(value instanceof Code || value['_bsontype'] == 'Code') { + // Calculate size depending on the availability of a scope + if(value.scope != null && Object.keys(value.scope).length > 0) { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + 4 + 4 + (!isBuffer ? numberOfBytes(value.code.toString()) : Buffer.byteLength(value.code.toString(), 'utf8')) + 1 + BSON.calculateObjectSize(value.scope, serializeFunctions); + } else { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + 4 + (!isBuffer ? numberOfBytes(value.code.toString()) : Buffer.byteLength(value.code.toString(), 'utf8')) + 1; + } + } else if(value instanceof Binary || value['_bsontype'] == 'Binary') { + // Check what kind of subtype we have + if(value.sub_type == Binary.SUBTYPE_BYTE_ARRAY) { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (value.position + 1 + 4 + 1 + 4); + } else { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (value.position + 1 + 4 + 1); + } + } else if(value instanceof Symbol || value['_bsontype'] == 'Symbol') { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + ((!isBuffer ? numberOfBytes(value.value) : Buffer.byteLength(value.value, 'utf8')) + 4 + 1 + 1); + } else if(value instanceof DBRef || value['_bsontype'] == 'DBRef') { + // Set up correct object for serialization + var ordered_values = { + '$ref': value.namespace + , '$id' : value.oid + }; + + // Add db reference if it exists + if(null != value.db) { + ordered_values['$db'] = value.db; + } + + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + BSON.calculateObjectSize(ordered_values, serializeFunctions); + } else if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]') { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + (!isBuffer ? numberOfBytes(value.source) : Buffer.byteLength(value.source, 'utf8')) + 1 + + (value.global ? 1 : 0) + (value.ignoreCase ? 1 : 0) + (value.multiline ? 1 : 0) + 1 + } else { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + BSON.calculateObjectSize(value, serializeFunctions) + 1; + } + case 'function': + // WTF for 0.4.X where typeof /someregexp/ === 'function' + if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]' || String.call(value) == '[object RegExp]') { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + (!isBuffer ? numberOfBytes(value.source) : Buffer.byteLength(value.source, 'utf8')) + 1 + + (value.global ? 1 : 0) + (value.ignoreCase ? 1 : 0) + (value.multiline ? 1 : 0) + 1 + } else { + if(serializeFunctions && value.scope != null && Object.keys(value.scope).length > 0) { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + 4 + 4 + (!isBuffer ? numberOfBytes(value.toString()) : Buffer.byteLength(value.toString(), 'utf8')) + 1 + BSON.calculateObjectSize(value.scope, serializeFunctions); + } else if(serializeFunctions) { + return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + 4 + (!isBuffer ? numberOfBytes(value.toString()) : Buffer.byteLength(value.toString(), 'utf8')) + 1; + } + } + } + + return 0; +} + +/** + * Serialize a Javascript object using a predefined Buffer and index into the buffer, useful when pre-allocating the space for serialization. + * + * @param {Object} object the Javascript object to serialize. + * @param {Boolean} checkKeys the serializer will check if keys are valid. + * @param {Buffer} buffer the Buffer you pre-allocated to store the serialized BSON object. + * @param {Number} index the index in the buffer where we wish to start serializing into. + * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**. + * @return {Number} returns the new write index in the Buffer. + * @api public + */ +BSON.serializeWithBufferAndIndex = function serializeWithBufferAndIndex(object, checkKeys, buffer, index, serializeFunctions) { + // Default setting false + serializeFunctions = serializeFunctions == null ? false : serializeFunctions; + // Write end information (length of the object) + var size = buffer.length; + // Write the size of the object + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + return serializeObject(object, checkKeys, buffer, index, serializeFunctions) - 1; +} + +/** + * @ignore + * @api private + */ +var serializeObject = function(object, checkKeys, buffer, index, serializeFunctions) { + if(object.toBSON) { + if(typeof object.toBSON != 'function') throw new Error("toBSON is not a function"); + object = object.toBSON(); + if(object != null && typeof object != 'object') throw new Error("toBSON function did not return an object"); + } + + // Process the object + if(Array.isArray(object)) { + for(var i = 0; i < object.length; i++) { + index = packElement(i.toString(), object[i], checkKeys, buffer, index, serializeFunctions); + } + } else { + // If we have toBSON defined, override the current object + if(object.toBSON) { + object = object.toBSON(); + } + + // Serialize the object + for(var key in object) { + // Check the key and throw error if it's illegal + if (key != '$db' && key != '$ref' && key != '$id') { + // dollars and dots ok + BSON.checkKey(key, !checkKeys); + } + + // Pack the element + index = packElement(key, object[key], checkKeys, buffer, index, serializeFunctions); + } + } + + // Write zero + buffer[index++] = 0; + return index; +} + +var stringToBytes = function(str) { + var ch, st, re = []; + for (var i = 0; i < str.length; i++ ) { + ch = str.charCodeAt(i); // get char + st = []; // set up "stack" + do { + st.push( ch & 0xFF ); // push byte to stack + ch = ch >> 8; // shift value down by 1 byte + } + while ( ch ); + // add stack contents to result + // done because chars have "wrong" endianness + re = re.concat( st.reverse() ); + } + // return an array of bytes + return re; +} + +var numberOfBytes = function(str) { + var ch, st, re = 0; + for (var i = 0; i < str.length; i++ ) { + ch = str.charCodeAt(i); // get char + st = []; // set up "stack" + do { + st.push( ch & 0xFF ); // push byte to stack + ch = ch >> 8; // shift value down by 1 byte + } + while ( ch ); + // add stack contents to result + // done because chars have "wrong" endianness + re = re + st.length; + } + // return an array of bytes + return re; +} + +/** + * @ignore + * @api private + */ +var writeToTypedArray = function(buffer, string, index) { + var bytes = stringToBytes(string); + for(var i = 0; i < bytes.length; i++) { + buffer[index + i] = bytes[i]; + } + return bytes.length; +} + +/** + * @ignore + * @api private + */ +var supportsBuffer = typeof Buffer != 'undefined'; + +/** + * @ignore + * @api private + */ +var packElement = function(name, value, checkKeys, buffer, index, serializeFunctions) { + + // If we have toBSON defined, override the current object + if(value && value.toBSON){ + value = value.toBSON(); + } + + var startIndex = index; + + switch(typeof value) { + case 'string': + // console.log("+++++++++++ index string:: " + index) + // Encode String type + buffer[index++] = BSON.BSON_DATA_STRING; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + + // Calculate size + var size = supportsBuffer ? Buffer.byteLength(value) + 1 : numberOfBytes(value) + 1; + // console.log("====== key :: " + name + " size ::" + size) + // Write the size of the string to buffer + buffer[index + 3] = (size >> 24) & 0xff; + buffer[index + 2] = (size >> 16) & 0xff; + buffer[index + 1] = (size >> 8) & 0xff; + buffer[index] = size & 0xff; + // Ajust the index + index = index + 4; + // Write the string + supportsBuffer ? buffer.write(value, index, 'utf8') : writeToTypedArray(buffer, value, index); + // Update index + index = index + size - 1; + // Write zero + buffer[index++] = 0; + // Return index + return index; + case 'number': + // We have an integer value + if(Math.floor(value) === value && value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) { + // If the value fits in 32 bits encode as int, if it fits in a double + // encode it as a double, otherwise long + if(value >= BSON.BSON_INT32_MIN && value <= BSON.BSON_INT32_MAX) { + // Set int type 32 bits or less + buffer[index++] = BSON.BSON_DATA_INT; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Write the int value + buffer[index++] = value & 0xff; + buffer[index++] = (value >> 8) & 0xff; + buffer[index++] = (value >> 16) & 0xff; + buffer[index++] = (value >> 24) & 0xff; + } else if(value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) { + // Encode as double + buffer[index++] = BSON.BSON_DATA_NUMBER; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Write float + writeIEEE754(buffer, value, index, 'little', 52, 8); + // Ajust index + index = index + 8; + } else { + // Set long type + buffer[index++] = BSON.BSON_DATA_LONG; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + var longVal = Long.fromNumber(value); + var lowBits = longVal.getLowBits(); + var highBits = longVal.getHighBits(); + // Encode low bits + buffer[index++] = lowBits & 0xff; + buffer[index++] = (lowBits >> 8) & 0xff; + buffer[index++] = (lowBits >> 16) & 0xff; + buffer[index++] = (lowBits >> 24) & 0xff; + // Encode high bits + buffer[index++] = highBits & 0xff; + buffer[index++] = (highBits >> 8) & 0xff; + buffer[index++] = (highBits >> 16) & 0xff; + buffer[index++] = (highBits >> 24) & 0xff; + } + } else { + // Encode as double + buffer[index++] = BSON.BSON_DATA_NUMBER; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Write float + writeIEEE754(buffer, value, index, 'little', 52, 8); + // Ajust index + index = index + 8; + } + + return index; + case 'undefined': + // Set long type + buffer[index++] = BSON.BSON_DATA_NULL; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + return index; + case 'boolean': + // Write the type + buffer[index++] = BSON.BSON_DATA_BOOLEAN; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Encode the boolean value + buffer[index++] = value ? 1 : 0; + return index; + case 'object': + if(value === null || value instanceof MinKey || value instanceof MaxKey + || value['_bsontype'] == 'MinKey' || value['_bsontype'] == 'MaxKey') { + // Write the type of either min or max key + if(value === null) { + buffer[index++] = BSON.BSON_DATA_NULL; + } else if(value instanceof MinKey) { + buffer[index++] = BSON.BSON_DATA_MIN_KEY; + } else { + buffer[index++] = BSON.BSON_DATA_MAX_KEY; + } + + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + return index; + } else if(value instanceof ObjectID || value['_bsontype'] == 'ObjectID') { + // console.log("+++++++++++ index OBJECTID:: " + index) + // Write the type + buffer[index++] = BSON.BSON_DATA_OID; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + + // Write objectid + supportsBuffer ? buffer.write(value.id, index, 'binary') : writeToTypedArray(buffer, value.id, index); + // Ajust index + index = index + 12; + return index; + } else if(value instanceof Date || isDate(value)) { + // Write the type + buffer[index++] = BSON.BSON_DATA_DATE; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + + // Write the date + var dateInMilis = Long.fromNumber(value.getTime()); + var lowBits = dateInMilis.getLowBits(); + var highBits = dateInMilis.getHighBits(); + // Encode low bits + buffer[index++] = lowBits & 0xff; + buffer[index++] = (lowBits >> 8) & 0xff; + buffer[index++] = (lowBits >> 16) & 0xff; + buffer[index++] = (lowBits >> 24) & 0xff; + // Encode high bits + buffer[index++] = highBits & 0xff; + buffer[index++] = (highBits >> 8) & 0xff; + buffer[index++] = (highBits >> 16) & 0xff; + buffer[index++] = (highBits >> 24) & 0xff; + return index; + } else if(typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) { + // Write the type + buffer[index++] = BSON.BSON_DATA_BINARY; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Get size of the buffer (current write point) + var size = value.length; + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + // Write the default subtype + buffer[index++] = BSON.BSON_BINARY_SUBTYPE_DEFAULT; + // Copy the content form the binary field to the buffer + value.copy(buffer, index, 0, size); + // Adjust the index + index = index + size; + return index; + } else if(value instanceof Long || value instanceof Timestamp || value['_bsontype'] == 'Long' || value['_bsontype'] == 'Timestamp') { + // Write the type + buffer[index++] = value instanceof Long || value['_bsontype'] == 'Long' ? BSON.BSON_DATA_LONG : BSON.BSON_DATA_TIMESTAMP; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Write the date + var lowBits = value.getLowBits(); + var highBits = value.getHighBits(); + // Encode low bits + buffer[index++] = lowBits & 0xff; + buffer[index++] = (lowBits >> 8) & 0xff; + buffer[index++] = (lowBits >> 16) & 0xff; + buffer[index++] = (lowBits >> 24) & 0xff; + // Encode high bits + buffer[index++] = highBits & 0xff; + buffer[index++] = (highBits >> 8) & 0xff; + buffer[index++] = (highBits >> 16) & 0xff; + buffer[index++] = (highBits >> 24) & 0xff; + return index; + } else if(value instanceof Double || value['_bsontype'] == 'Double') { + // Encode as double + buffer[index++] = BSON.BSON_DATA_NUMBER; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Write float + writeIEEE754(buffer, value, index, 'little', 52, 8); + // Ajust index + index = index + 8; + return index; + } else if(value instanceof Code || value['_bsontype'] == 'Code') { + if(value.scope != null && Object.keys(value.scope).length > 0) { + // Write the type + buffer[index++] = BSON.BSON_DATA_CODE_W_SCOPE; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Calculate the scope size + var scopeSize = BSON.calculateObjectSize(value.scope, serializeFunctions); + // Function string + var functionString = value.code.toString(); + // Function Size + var codeSize = supportsBuffer ? Buffer.byteLength(functionString) + 1 : numberOfBytes(functionString) + 1; + + // Calculate full size of the object + var totalSize = 4 + codeSize + scopeSize + 4; + + // Write the total size of the object + buffer[index++] = totalSize & 0xff; + buffer[index++] = (totalSize >> 8) & 0xff; + buffer[index++] = (totalSize >> 16) & 0xff; + buffer[index++] = (totalSize >> 24) & 0xff; + + // Write the size of the string to buffer + buffer[index++] = codeSize & 0xff; + buffer[index++] = (codeSize >> 8) & 0xff; + buffer[index++] = (codeSize >> 16) & 0xff; + buffer[index++] = (codeSize >> 24) & 0xff; + + // Write the string + supportsBuffer ? buffer.write(functionString, index, 'utf8') : writeToTypedArray(buffer, functionString, index); + // Update index + index = index + codeSize - 1; + // Write zero + buffer[index++] = 0; + // Serialize the scope object + var scopeObjectBuffer = supportsBuffer ? new Buffer(scopeSize) : new Uint8Array(new ArrayBuffer(scopeSize)); + // Execute the serialization into a seperate buffer + serializeObject(value.scope, checkKeys, scopeObjectBuffer, 0, serializeFunctions); + + // Adjusted scope Size (removing the header) + var scopeDocSize = scopeSize; + // Write scope object size + buffer[index++] = scopeDocSize & 0xff; + buffer[index++] = (scopeDocSize >> 8) & 0xff; + buffer[index++] = (scopeDocSize >> 16) & 0xff; + buffer[index++] = (scopeDocSize >> 24) & 0xff; + + // Write the scopeObject into the buffer + supportsBuffer ? scopeObjectBuffer.copy(buffer, index, 0, scopeSize) : buffer.set(scopeObjectBuffer, index); + // Adjust index, removing the empty size of the doc (5 bytes 0000000005) + index = index + scopeDocSize - 5; + // Write trailing zero + buffer[index++] = 0; + return index + } else { + buffer[index++] = BSON.BSON_DATA_CODE; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Function string + var functionString = value.code.toString(); + // Function Size + var size = supportsBuffer ? Buffer.byteLength(functionString) + 1 : numberOfBytes(functionString) + 1; + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + // Write the string + supportsBuffer ? buffer.write(functionString, index, 'utf8') : writeToTypedArray(buffer, functionString, index); + // Update index + index = index + size - 1; + // Write zero + buffer[index++] = 0; + return index; + } + } else if(value instanceof Binary || value['_bsontype'] == 'Binary') { + // Write the type + buffer[index++] = BSON.BSON_DATA_BINARY; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Extract the buffer + var data = value.value(true); + // Calculate size + var size = value.position; + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + // Write the subtype to the buffer + buffer[index++] = value.sub_type; + + // If we have binary type 2 the 4 first bytes are the size + if(value.sub_type == Binary.SUBTYPE_BYTE_ARRAY) { + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + } + + // Write the data to the object + supportsBuffer ? data.copy(buffer, index, 0, value.position) : buffer.set(data, index); + // Ajust index + index = index + value.position; + return index; + } else if(value instanceof Symbol || value['_bsontype'] == 'Symbol') { + // Write the type + buffer[index++] = BSON.BSON_DATA_SYMBOL; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Calculate size + var size = supportsBuffer ? Buffer.byteLength(value.value) + 1 : numberOfBytes(value.value) + 1; + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + // Write the string + buffer.write(value.value, index, 'utf8'); + // Update index + index = index + size - 1; + // Write zero + buffer[index++] = 0x00; + return index; + } else if(value instanceof DBRef || value['_bsontype'] == 'DBRef') { + // Write the type + buffer[index++] = BSON.BSON_DATA_OBJECT; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Set up correct object for serialization + var ordered_values = { + '$ref': value.namespace + , '$id' : value.oid + }; + + // Add db reference if it exists + if(null != value.db) { + ordered_values['$db'] = value.db; + } + + // Message size + var size = BSON.calculateObjectSize(ordered_values, serializeFunctions); + // Serialize the object + var endIndex = BSON.serializeWithBufferAndIndex(ordered_values, checkKeys, buffer, index, serializeFunctions); + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + // Write zero for object + buffer[endIndex++] = 0x00; + // Return the end index + return endIndex; + } else if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]') { + // Write the type + buffer[index++] = BSON.BSON_DATA_REGEXP; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + + // Write the regular expression string + supportsBuffer ? buffer.write(value.source, index, 'utf8') : writeToTypedArray(buffer, value.source, index); + // Adjust the index + index = index + (supportsBuffer ? Buffer.byteLength(value.source) : numberOfBytes(value.source)); + // Write zero + buffer[index++] = 0x00; + // Write the parameters + if(value.global) buffer[index++] = 0x73; // s + if(value.ignoreCase) buffer[index++] = 0x69; // i + if(value.multiline) buffer[index++] = 0x6d; // m + // Add ending zero + buffer[index++] = 0x00; + return index; + } else { + // Write the type + buffer[index++] = Array.isArray(value) ? BSON.BSON_DATA_ARRAY : BSON.BSON_DATA_OBJECT; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Adjust the index + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + var endIndex = serializeObject(value, checkKeys, buffer, index + 4, serializeFunctions); + // Write size + var size = endIndex - index; + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + return endIndex; + } + case 'function': + // WTF for 0.4.X where typeof /someregexp/ === 'function' + if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]' || String.call(value) == '[object RegExp]') { + // Write the type + buffer[index++] = BSON.BSON_DATA_REGEXP; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + + // Write the regular expression string + buffer.write(value.source, index, 'utf8'); + // Adjust the index + index = index + (supportsBuffer ? Buffer.byteLength(value.source) : numberOfBytes(value.source)); + // Write zero + buffer[index++] = 0x00; + // Write the parameters + if(value.global) buffer[index++] = 0x73; // s + if(value.ignoreCase) buffer[index++] = 0x69; // i + if(value.multiline) buffer[index++] = 0x6d; // m + // Add ending zero + buffer[index++] = 0x00; + return index; + } else { + if(serializeFunctions && value.scope != null && Object.keys(value.scope).length > 0) { + // Write the type + buffer[index++] = BSON.BSON_DATA_CODE_W_SCOPE; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Calculate the scope size + var scopeSize = BSON.calculateObjectSize(value.scope, serializeFunctions); + // Function string + var functionString = value.toString(); + // Function Size + var codeSize = supportsBuffer ? Buffer.byteLength(functionString) + 1 : numberOfBytes(functionString) + 1; + + // Calculate full size of the object + var totalSize = 4 + codeSize + scopeSize; + + // Write the total size of the object + buffer[index++] = totalSize & 0xff; + buffer[index++] = (totalSize >> 8) & 0xff; + buffer[index++] = (totalSize >> 16) & 0xff; + buffer[index++] = (totalSize >> 24) & 0xff; + + // Write the size of the string to buffer + buffer[index++] = codeSize & 0xff; + buffer[index++] = (codeSize >> 8) & 0xff; + buffer[index++] = (codeSize >> 16) & 0xff; + buffer[index++] = (codeSize >> 24) & 0xff; + + // Write the string + supportsBuffer ? buffer.write(functionString, index, 'utf8') : writeToTypedArray(buffer, functionString, index); + // Update index + index = index + codeSize - 1; + // Write zero + buffer[index++] = 0; + // Serialize the scope object + var scopeObjectBuffer = new Buffer(scopeSize); + // Execute the serialization into a seperate buffer + serializeObject(value.scope, checkKeys, scopeObjectBuffer, 0, serializeFunctions); + + // Adjusted scope Size (removing the header) + var scopeDocSize = scopeSize - 4; + // Write scope object size + buffer[index++] = scopeDocSize & 0xff; + buffer[index++] = (scopeDocSize >> 8) & 0xff; + buffer[index++] = (scopeDocSize >> 16) & 0xff; + buffer[index++] = (scopeDocSize >> 24) & 0xff; + + // Write the scopeObject into the buffer + scopeObjectBuffer.copy(buffer, index, 0, scopeSize); + + // Adjust index, removing the empty size of the doc (5 bytes 0000000005) + index = index + scopeDocSize - 5; + // Write trailing zero + buffer[index++] = 0; + return index + } else if(serializeFunctions) { + buffer[index++] = BSON.BSON_DATA_CODE; + // Number of written bytes + var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + // Function string + var functionString = value.toString(); + // Function Size + var size = supportsBuffer ? Buffer.byteLength(functionString) + 1 : numberOfBytes(functionString) + 1; + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + // Write the string + supportsBuffer ? buffer.write(functionString, index, 'utf8') : writeToTypedArray(buffer, functionString, index); + // Update index + index = index + size - 1; + // Write zero + buffer[index++] = 0; + return index; + } + } + } + + // If no value to serialize + return index; +} + +/** + * Serialize a Javascript object. + * + * @param {Object} object the Javascript object to serialize. + * @param {Boolean} checkKeys the serializer will check if keys are valid. + * @param {Boolean} asBuffer return the serialized object as a Buffer object **(ignore)**. + * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**. + * @return {Buffer} returns the Buffer object containing the serialized object. + * @api public + */ +BSON.serialize = function(object, checkKeys, asBuffer, serializeFunctions) { + // Throw error if we are trying serialize an illegal type + if(object == null || typeof object != 'object' || Array.isArray(object)) + throw new Error("Only javascript objects supported"); + + // Emoty target buffer + var buffer = null; + // Calculate the size of the object + var size = BSON.calculateObjectSize(object, serializeFunctions); + // Fetch the best available type for storing the binary data + if(buffer = typeof Buffer != 'undefined') { + buffer = new Buffer(size); + asBuffer = true; + } else if(typeof Uint8Array != 'undefined') { + buffer = new Uint8Array(new ArrayBuffer(size)); + } else { + buffer = new Array(size); + } + + // If asBuffer is false use typed arrays + BSON.serializeWithBufferAndIndex(object, checkKeys, buffer, 0, serializeFunctions); + // console.log("++++++++++++++++++++++++++++++++++++ OLDJS :: " + buffer.length) + // console.log(buffer.toString('hex')) + // console.log(buffer.toString('ascii')) + return buffer; +} + +/** + * Contains the function cache if we have that enable to allow for avoiding the eval step on each deserialization, comparison is by md5 + * + * @ignore + * @api private + */ +var functionCache = BSON.functionCache = {}; + +/** + * Crc state variables shared by function + * + * @ignore + * @api private + */ +var table = [0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D]; + +/** + * CRC32 hash method, Fast and enough versitility for our usage + * + * @ignore + * @api private + */ +var crc32 = function(string, start, end) { + var crc = 0 + var x = 0; + var y = 0; + crc = crc ^ (-1); + + for(var i = start, iTop = end; i < iTop;i++) { + y = (crc ^ string[i]) & 0xFF; + x = table[y]; + crc = (crc >>> 8) ^ x; + } + + return crc ^ (-1); +} + +/** + * Deserialize stream data as BSON documents. + * + * Options + * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized. + * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse. + * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function. + * - **promoteLongs** {Boolean, default:true}, when deserializing a Long will fit it into a Number if it's smaller than 53 bits + * + * @param {Buffer} data the buffer containing the serialized set of BSON documents. + * @param {Number} startIndex the start index in the data Buffer where the deserialization is to start. + * @param {Number} numberOfDocuments number of documents to deserialize. + * @param {Array} documents an array where to store the deserialized documents. + * @param {Number} docStartIndex the index in the documents array from where to start inserting documents. + * @param {Object} [options] additional options used for the deserialization. + * @return {Number} returns the next index in the buffer after deserialization **x** numbers of documents. + * @api public + */ +BSON.deserializeStream = function(data, startIndex, numberOfDocuments, documents, docStartIndex, options) { + // if(numberOfDocuments !== documents.length) throw new Error("Number of expected results back is less than the number of documents"); + options = options != null ? options : {}; + var index = startIndex; + // Loop over all documents + for(var i = 0; i < numberOfDocuments; i++) { + // Find size of the document + var size = data[index] | data[index + 1] << 8 | data[index + 2] << 16 | data[index + 3] << 24; + // Update options with index + options['index'] = index; + // Parse the document at this point + documents[docStartIndex + i] = BSON.deserialize(data, options); + // Adjust index by the document size + index = index + size; + } + + // Return object containing end index of parsing and list of documents + return index; +} + +/** + * Ensure eval is isolated. + * + * @ignore + * @api private + */ +var isolateEvalWithHash = function(functionCache, hash, functionString, object) { + // Contains the value we are going to set + var value = null; + + // Check for cache hit, eval if missing and return cached function + if(functionCache[hash] == null) { + eval("value = " + functionString); + functionCache[hash] = value; + } + // Set the object + return functionCache[hash].bind(object); +} + +/** + * Ensure eval is isolated. + * + * @ignore + * @api private + */ +var isolateEval = function(functionString) { + // Contains the value we are going to set + var value = null; + // Eval the function + eval("value = " + functionString); + return value; +} + +/** + * Convert Uint8Array to String + * + * @ignore + * @api private + */ +var convertUint8ArrayToUtf8String = function(byteArray, startIndex, endIndex) { + return BinaryParser.decode_utf8(convertArraytoUtf8BinaryString(byteArray, startIndex, endIndex)); +} + +var convertArraytoUtf8BinaryString = function(byteArray, startIndex, endIndex) { + var result = ""; + for(var i = startIndex; i < endIndex; i++) { + result = result + String.fromCharCode(byteArray[i]); + } + + return result; +}; + +/** + * Deserialize data as BSON. + * + * Options + * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized. + * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse. + * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function. + * - **promoteLongs** {Boolean, default:true}, when deserializing a Long will fit it into a Number if it's smaller than 53 bits + * + * @param {Buffer} buffer the buffer containing the serialized set of BSON documents. + * @param {Object} [options] additional options used for the deserialization. + * @param {Boolean} [isArray] ignore used for recursive parsing. + * @return {Object} returns the deserialized Javascript Object. + * @api public + */ +BSON.deserialize = function(buffer, options, isArray) { + // Options + options = options == null ? {} : options; + var evalFunctions = options['evalFunctions'] == null ? false : options['evalFunctions']; + var cacheFunctions = options['cacheFunctions'] == null ? false : options['cacheFunctions']; + var cacheFunctionsCrc32 = options['cacheFunctionsCrc32'] == null ? false : options['cacheFunctionsCrc32']; + var promoteLongs = options['promoteLongs'] == null ? true : options['promoteLongs']; + + // Validate that we have at least 4 bytes of buffer + if(buffer.length < 5) throw new Error("corrupt bson message < 5 bytes long"); + + // Set up index + var index = typeof options['index'] == 'number' ? options['index'] : 0; + // Reads in a C style string + var readCStyleString = function() { + // Get the start search index + var i = index; + // Locate the end of the c string + while(buffer[i] !== 0x00 && i < buffer.length) { + i++ + } + // If are at the end of the buffer there is a problem with the document + if(i >= buffer.length) throw new Error("Bad BSON Document: illegal CString") + // Grab utf8 encoded string + var string = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('utf8', index, i) : convertUint8ArrayToUtf8String(buffer, index, i); + // Update index position + index = i + 1; + // Return string + return string; + } + + // Create holding object + var object = isArray ? [] : {}; + + // Read the document size + var size = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + + // Ensure buffer is valid size + if(size < 5 || size > buffer.length) throw new Error("corrupt bson message"); + + // While we have more left data left keep parsing + while(true) { + // Read the type + var elementType = buffer[index++]; + // If we get a zero it's the last byte, exit + if(elementType == 0) break; + // Read the name of the field + var name = readCStyleString(); + // Switch on the type + switch(elementType) { + case BSON.BSON_DATA_OID: + var string = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('binary', index, index + 12) : convertArraytoUtf8BinaryString(buffer, index, index + 12); + // Decode the oid + object[name] = new ObjectID(string); + // Update index + index = index + 12; + break; + case BSON.BSON_DATA_STRING: + // Read the content of the field + var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Add string to object + object[name] = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('utf8', index, index + stringSize - 1) : convertUint8ArrayToUtf8String(buffer, index, index + stringSize - 1); + // Update parse index position + index = index + stringSize; + break; + case BSON.BSON_DATA_INT: + // Decode the 32bit value + object[name] = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + break; + case BSON.BSON_DATA_NUMBER: + // Decode the double value + object[name] = readIEEE754(buffer, index, 'little', 52, 8); + // Update the index + index = index + 8; + break; + case BSON.BSON_DATA_DATE: + // Unpack the low and high bits + var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Set date object + object[name] = new Date(new Long(lowBits, highBits).toNumber()); + break; + case BSON.BSON_DATA_BOOLEAN: + // Parse the boolean value + object[name] = buffer[index++] == 1; + break; + case BSON.BSON_DATA_UNDEFINED: + case BSON.BSON_DATA_NULL: + // Parse the boolean value + object[name] = null; + break; + case BSON.BSON_DATA_BINARY: + // Decode the size of the binary blob + var binarySize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Decode the subtype + var subType = buffer[index++]; + // Decode as raw Buffer object if options specifies it + if(buffer['slice'] != null) { + // If we have subtype 2 skip the 4 bytes for the size + if(subType == Binary.SUBTYPE_BYTE_ARRAY) { + binarySize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + } + // Slice the data + object[name] = new Binary(buffer.slice(index, index + binarySize), subType); + } else { + var _buffer = typeof Uint8Array != 'undefined' ? new Uint8Array(new ArrayBuffer(binarySize)) : new Array(binarySize); + // If we have subtype 2 skip the 4 bytes for the size + if(subType == Binary.SUBTYPE_BYTE_ARRAY) { + binarySize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + } + // Copy the data + for(var i = 0; i < binarySize; i++) { + _buffer[i] = buffer[index + i]; + } + // Create the binary object + object[name] = new Binary(_buffer, subType); + } + // Update the index + index = index + binarySize; + break; + case BSON.BSON_DATA_ARRAY: + options['index'] = index; + // Decode the size of the array document + var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24; + // Set the array to the object + object[name] = BSON.deserialize(buffer, options, true); + // Adjust the index + index = index + objectSize; + break; + case BSON.BSON_DATA_OBJECT: + options['index'] = index; + // Decode the size of the object document + var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24; + // Set the array to the object + object[name] = BSON.deserialize(buffer, options, false); + // Adjust the index + index = index + objectSize; + break; + case BSON.BSON_DATA_REGEXP: + // Create the regexp + var source = readCStyleString(); + var regExpOptions = readCStyleString(); + // For each option add the corresponding one for javascript + var optionsArray = new Array(regExpOptions.length); + + // Parse options + for(var i = 0; i < regExpOptions.length; i++) { + switch(regExpOptions[i]) { + case 'm': + optionsArray[i] = 'm'; + break; + case 's': + optionsArray[i] = 'g'; + break; + case 'i': + optionsArray[i] = 'i'; + break; + } + } + + object[name] = new RegExp(source, optionsArray.join('')); + break; + case BSON.BSON_DATA_LONG: + // Unpack the low and high bits + var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Create long object + var long = new Long(lowBits, highBits); + // Promote the long if possible + if(promoteLongs) { + object[name] = long.lessThanOrEqual(JS_INT_MAX_LONG) && long.greaterThanOrEqual(JS_INT_MIN_LONG) ? long.toNumber() : long; + } else { + object[name] = long; + } + break; + case BSON.BSON_DATA_SYMBOL: + // Read the content of the field + var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Add string to object + object[name] = new Symbol(buffer.toString('utf8', index, index + stringSize - 1)); + // Update parse index position + index = index + stringSize; + break; + case BSON.BSON_DATA_TIMESTAMP: + // Unpack the low and high bits + var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Set the object + object[name] = new Timestamp(lowBits, highBits); + break; + case BSON.BSON_DATA_MIN_KEY: + // Parse the object + object[name] = new MinKey(); + break; + case BSON.BSON_DATA_MAX_KEY: + // Parse the object + object[name] = new MaxKey(); + break; + case BSON.BSON_DATA_CODE: + // Read the content of the field + var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Function string + var functionString = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('utf8', index, index + stringSize - 1) : convertUint8ArrayToUtf8String(buffer, index, index + stringSize - 1); + + // If we are evaluating the functions + if(evalFunctions) { + // Contains the value we are going to set + var value = null; + // If we have cache enabled let's look for the md5 of the function in the cache + if(cacheFunctions) { + var hash = cacheFunctionsCrc32 ? crc32(functionString) : functionString; + // Got to do this to avoid V8 deoptimizing the call due to finding eval + object[name] = isolateEvalWithHash(functionCache, hash, functionString, object); + } else { + // Set directly + object[name] = isolateEval(functionString); + } + } else { + object[name] = new Code(functionString, {}); + } + + // Update parse index position + index = index + stringSize; + break; + case BSON.BSON_DATA_CODE_W_SCOPE: + // Read the content of the field + var totalSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Javascript function + var functionString = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('utf8', index, index + stringSize - 1) : convertUint8ArrayToUtf8String(buffer, index, index + stringSize - 1); + // Update parse index position + index = index + stringSize; + // Parse the element + options['index'] = index; + // Decode the size of the object document + var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24; + // Decode the scope object + var scopeObject = BSON.deserialize(buffer, options, false); + // Adjust the index + index = index + objectSize; + + // If we are evaluating the functions + if(evalFunctions) { + // Contains the value we are going to set + var value = null; + // If we have cache enabled let's look for the md5 of the function in the cache + if(cacheFunctions) { + var hash = cacheFunctionsCrc32 ? crc32(functionString) : functionString; + // Got to do this to avoid V8 deoptimizing the call due to finding eval + object[name] = isolateEvalWithHash(functionCache, hash, functionString, object); + } else { + // Set directly + object[name] = isolateEval(functionString); + } + + // Set the scope on the object + object[name].scope = scopeObject; + } else { + object[name] = new Code(functionString, scopeObject); + } + + // Add string to object + break; + } + } + + // Check if we have a db ref object + if(object['$id'] != null) object = new DBRef(object['$ref'], object['$id'], object['$db']); + + // Return the final objects + return object; +} + +/** + * Check if key name is valid. + * + * @ignore + * @api private + */ +BSON.checkKey = function checkKey (key, dollarsAndDotsOk) { + if (!key.length) return; + // Check if we have a legal key for the object + if (!!~key.indexOf("\x00")) { + // The BSON spec doesn't allow keys with null bytes because keys are + // null-terminated. + throw Error("key " + key + " must not contain null bytes"); + } + if (!dollarsAndDotsOk) { + if('$' == key[0]) { + throw Error("key " + key + " must not start with '$'"); + } else if (!!~key.indexOf('.')) { + throw Error("key " + key + " must not contain '.'"); + } + } +}; + +/** + * Deserialize data as BSON. + * + * Options + * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized. + * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse. + * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function. + * + * @param {Buffer} buffer the buffer containing the serialized set of BSON documents. + * @param {Object} [options] additional options used for the deserialization. + * @param {Boolean} [isArray] ignore used for recursive parsing. + * @return {Object} returns the deserialized Javascript Object. + * @api public + */ +BSON.prototype.deserialize = function(data, options) { + return BSON.deserialize(data, options); +} + +/** + * Deserialize stream data as BSON documents. + * + * Options + * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized. + * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse. + * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function. + * + * @param {Buffer} data the buffer containing the serialized set of BSON documents. + * @param {Number} startIndex the start index in the data Buffer where the deserialization is to start. + * @param {Number} numberOfDocuments number of documents to deserialize. + * @param {Array} documents an array where to store the deserialized documents. + * @param {Number} docStartIndex the index in the documents array from where to start inserting documents. + * @param {Object} [options] additional options used for the deserialization. + * @return {Number} returns the next index in the buffer after deserialization **x** numbers of documents. + * @api public + */ +BSON.prototype.deserializeStream = function(data, startIndex, numberOfDocuments, documents, docStartIndex, options) { + return BSON.deserializeStream(data, startIndex, numberOfDocuments, documents, docStartIndex, options); +} + +/** + * Serialize a Javascript object. + * + * @param {Object} object the Javascript object to serialize. + * @param {Boolean} checkKeys the serializer will check if keys are valid. + * @param {Boolean} asBuffer return the serialized object as a Buffer object **(ignore)**. + * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**. + * @return {Buffer} returns the Buffer object containing the serialized object. + * @api public + */ +BSON.prototype.serialize = function(object, checkKeys, asBuffer, serializeFunctions) { + return BSON.serialize(object, checkKeys, asBuffer, serializeFunctions); +} + +/** + * Calculate the bson size for a passed in Javascript object. + * + * @param {Object} object the Javascript object to calculate the BSON byte size for. + * @param {Boolean} [serializeFunctions] serialize all functions in the object **(default:false)**. + * @return {Number} returns the number of bytes the BSON object will take up. + * @api public + */ +BSON.prototype.calculateObjectSize = function(object, serializeFunctions) { + return BSON.calculateObjectSize(object, serializeFunctions); +} + +/** + * Serialize a Javascript object using a predefined Buffer and index into the buffer, useful when pre-allocating the space for serialization. + * + * @param {Object} object the Javascript object to serialize. + * @param {Boolean} checkKeys the serializer will check if keys are valid. + * @param {Buffer} buffer the Buffer you pre-allocated to store the serialized BSON object. + * @param {Number} index the index in the buffer where we wish to start serializing into. + * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**. + * @return {Number} returns the new write index in the Buffer. + * @api public + */ +BSON.prototype.serializeWithBufferAndIndex = function(object, checkKeys, buffer, startIndex, serializeFunctions) { + return BSON.serializeWithBufferAndIndex(object, checkKeys, buffer, startIndex, serializeFunctions); +} + +/** + * @ignore + * @api private + */ +exports.Code = Code; +exports.Symbol = Symbol; +exports.BSON = BSON; +exports.DBRef = DBRef; +exports.Binary = Binary; +exports.ObjectID = ObjectID; +exports.Long = Long; +exports.Timestamp = Timestamp; +exports.Double = Double; +exports.MinKey = MinKey; +exports.MaxKey = MaxKey; diff --git a/node_modules/mongodb/node_modules/bson/lib/bson/bson_new.js b/node_modules/mongodb/node_modules/bson/lib/bson/bson_new.js new file mode 100644 index 0000000..0b1b38d --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/lib/bson/bson_new.js @@ -0,0 +1,776 @@ +var writeIEEE754 = require('./float_parser').writeIEEE754 + , Long = require('./long').Long + , Double = require('./double').Double + , Timestamp = require('./timestamp').Timestamp + , ObjectID = require('./objectid').ObjectID + , Symbol = require('./symbol').Symbol + , Code = require('./code').Code + , MinKey = require('./min_key').MinKey + , MaxKey = require('./max_key').MaxKey + , DBRef = require('./db_ref').DBRef + , Binary = require('./binary').Binary + , BinaryParser = require('./binary_parser').BinaryParser; + +// Max Document Buffer size +var buffer = new Buffer(1024 * 1024 * 16); + +var checkKey = function checkKey (key, dollarsAndDotsOk) { + if (!key.length) return; + // Check if we have a legal key for the object + if (!!~key.indexOf("\x00")) { + // The BSON spec doesn't allow keys with null bytes because keys are + // null-terminated. + throw Error("key " + key + " must not contain null bytes"); + } + if (!dollarsAndDotsOk) { + if('$' == key[0]) { + throw Error("key " + key + " must not start with '$'"); + } else if (!!~key.indexOf('.')) { + throw Error("key " + key + " must not contain '.'"); + } + } +}; + +var serializeString = function(key, value, index) { + // Encode String type + buffer[index++] = BSON.BSON_DATA_STRING; + // Number of written bytes + var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); + // Encode the name + index = index + numberOfWrittenBytes + 1; + buffer[index - 1] = 0; + + // Calculate size + var size = Buffer.byteLength(value) + 1; + // Write the size of the string to buffer + buffer[index + 3] = (size >> 24) & 0xff; + buffer[index + 2] = (size >> 16) & 0xff; + buffer[index + 1] = (size >> 8) & 0xff; + buffer[index] = size & 0xff; + // Ajust the index + index = index + 4; + // Write the string + buffer.write(value, index, 'utf8'); + // Update index + index = index + size - 1; + // Write zero + buffer[index++] = 0; + return index; +} + +var serializeNumber = function(key, value, index) { + // We have an integer value + if(Math.floor(value) === value && value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) { + // If the value fits in 32 bits encode as int, if it fits in a double + // encode it as a double, otherwise long + if(value >= BSON.BSON_INT32_MIN && value <= BSON.BSON_INT32_MAX) { + // Set int type 32 bits or less + buffer[index++] = BSON.BSON_DATA_INT; + // Number of written bytes + var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); + // Encode the name + index = index + numberOfWrittenBytes; + buffer[index++] = 0; + // Write the int value + buffer[index++] = value & 0xff; + buffer[index++] = (value >> 8) & 0xff; + buffer[index++] = (value >> 16) & 0xff; + buffer[index++] = (value >> 24) & 0xff; + } else if(value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) { + // Encode as double + buffer[index++] = BSON.BSON_DATA_NUMBER; + // Number of written bytes + var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); + // Encode the name + index = index + numberOfWrittenBytes; + buffer[index++] = 0; + // Write float + writeIEEE754(buffer, value, index, 'little', 52, 8); + // Ajust index + index = index + 8; + } else { + // Set long type + buffer[index++] = BSON.BSON_DATA_LONG; + // Number of written bytes + var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); + // Encode the name + index = index + numberOfWrittenBytes; + buffer[index++] = 0; + var longVal = Long.fromNumber(value); + var lowBits = longVal.getLowBits(); + var highBits = longVal.getHighBits(); + // Encode low bits + buffer[index++] = lowBits & 0xff; + buffer[index++] = (lowBits >> 8) & 0xff; + buffer[index++] = (lowBits >> 16) & 0xff; + buffer[index++] = (lowBits >> 24) & 0xff; + // Encode high bits + buffer[index++] = highBits & 0xff; + buffer[index++] = (highBits >> 8) & 0xff; + buffer[index++] = (highBits >> 16) & 0xff; + buffer[index++] = (highBits >> 24) & 0xff; + } + } else { + // Encode as double + buffer[index++] = BSON.BSON_DATA_NUMBER; + // Number of written bytes + var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); + // Encode the name + index = index + numberOfWrittenBytes; + buffer[index++] = 0; + // Write float + writeIEEE754(buffer, value, index, 'little', 52, 8); + // Ajust index + index = index + 8; + } + + return index; +} + +var serializeUndefined = function(key, value, index) { + // Set long type + buffer[index++] = BSON.BSON_DATA_NULL; + // Number of written bytes + var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); + // Encode the name + index = index + numberOfWrittenBytes; + buffer[index++] = 0; + return index; +} + +var serializeBoolean = function(key, value, index) { + // Write the type + buffer[index++] = BSON.BSON_DATA_BOOLEAN; + // Number of written bytes + var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); + // Encode the name + index = index + numberOfWrittenBytes; + buffer[index++] = 0; + // Encode the boolean value + buffer[index++] = value ? 1 : 0; + return index; +} + +var serializeDate = function(key, value, index) { + // Write the type + buffer[index++] = BSON.BSON_DATA_DATE; + // Number of written bytes + var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); + // Encode the name + index = index + numberOfWrittenBytes; + buffer[index++] = 0; + + // Write the date + var dateInMilis = Long.fromNumber(value.getTime()); + var lowBits = dateInMilis.getLowBits(); + var highBits = dateInMilis.getHighBits(); + // Encode low bits + buffer[index++] = lowBits & 0xff; + buffer[index++] = (lowBits >> 8) & 0xff; + buffer[index++] = (lowBits >> 16) & 0xff; + buffer[index++] = (lowBits >> 24) & 0xff; + // Encode high bits + buffer[index++] = highBits & 0xff; + buffer[index++] = (highBits >> 8) & 0xff; + buffer[index++] = (highBits >> 16) & 0xff; + buffer[index++] = (highBits >> 24) & 0xff; + return index; +} + +var serializeRegExp = function(key, value, index) { + // Write the type + buffer[index++] = BSON.BSON_DATA_REGEXP; + // Number of written bytes + var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); + // Encode the name + index = index + numberOfWrittenBytes; + buffer[index++] = 0; + + // Write the regular expression string + buffer.write(value.source, index, 'utf8'); + // Adjust the index + index = index + Buffer.byteLength(value.source); + // Write zero + buffer[index++] = 0x00; + // Write the parameters + if(value.global) buffer[index++] = 0x73; // s + if(value.ignoreCase) buffer[index++] = 0x69; // i + if(value.multiline) buffer[index++] = 0x6d; // m + // Add ending zero + buffer[index++] = 0x00; + return index; +} + +var serializeMinMax = function(key, value, index) { + // Write the type of either min or max key + if(value === null) { + buffer[index++] = BSON.BSON_DATA_NULL; + } else if(value instanceof MinKey) { + buffer[index++] = BSON.BSON_DATA_MIN_KEY; + } else { + buffer[index++] = BSON.BSON_DATA_MAX_KEY; + } + + // Number of written bytes + var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); + // Encode the name + index = index + numberOfWrittenBytes; + buffer[index++] = 0; + return index; +} + +var serializeObjectId = function(key, value, index) { + // Write the type + buffer[index++] = BSON.BSON_DATA_OID; + // Number of written bytes + var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); + // Encode the name + index = index + numberOfWrittenBytes; + buffer[index++] = 0; + + for(var j = 0; j < 12; j++) { + buffer[index + j] = value.binId[j]; + } + + // Ajust index + index = index + 12; + return index; +} + +var serializeBuffer = function(key, value, index) { + // Write the type + buffer[index++] = BSON.BSON_DATA_BINARY; + // Number of written bytes + var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); + // Encode the name + index = index + numberOfWrittenBytes; + buffer[index++] = 0; + // Get size of the buffer (current write point) + var size = value.length; + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + // Write the default subtype + buffer[index++] = BSON.BSON_BINARY_SUBTYPE_DEFAULT; + // Copy the content form the binary field to the buffer + value.copy(buffer, index, 0, size); + // Adjust the index + index = index + size; + return index; +} + +var serializeObject = function(key, value, index, checkKeys, depth) { + // Write the type + buffer[index++] = Array.isArray(value) ? BSON.BSON_DATA_ARRAY : BSON.BSON_DATA_OBJECT; + // Number of written bytes + var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); + // Encode the name + index = index + numberOfWrittenBytes; + buffer[index++] = 0; + var endIndex = serializeInto(value, checkKeys, index, depth + 1); + // Write size + var size = endIndex - index; + return endIndex; +} + +var serializeLong = function(key, value, index) { + // Write the type + buffer[index++] = value instanceof Long ? BSON.BSON_DATA_LONG : BSON.BSON_DATA_TIMESTAMP; + // Number of written bytes + var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); + // Encode the name + index = index + numberOfWrittenBytes; + buffer[index++] = 0; + // Write the date + var lowBits = value.getLowBits(); + var highBits = value.getHighBits(); + // Encode low bits + buffer[index++] = lowBits & 0xff; + buffer[index++] = (lowBits >> 8) & 0xff; + buffer[index++] = (lowBits >> 16) & 0xff; + buffer[index++] = (lowBits >> 24) & 0xff; + // Encode high bits + buffer[index++] = highBits & 0xff; + buffer[index++] = (highBits >> 8) & 0xff; + buffer[index++] = (highBits >> 16) & 0xff; + buffer[index++] = (highBits >> 24) & 0xff; + return index; +} + +var serializeDouble = function(key, value, index) { + // Encode as double + buffer[index++] = BSON.BSON_DATA_NUMBER; + // Number of written bytes + var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); + // Encode the name + index = index + numberOfWrittenBytes; + buffer[index++] = 0; + // Write float + writeIEEE754(buffer, value, index, 'little', 52, 8); + // Ajust index + index = index + 8; + return index; +} + +var serializeCode = function(key, value, index, checkKeys, depth) { + if(value.scope != null && Object.keys(value.scope).length > 0) { + // Write the type + buffer[index++] = BSON.BSON_DATA_CODE_W_SCOPE; + // Number of written bytes + var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); + // Encode the name + index = index + numberOfWrittenBytes; + buffer[index++] = 0; + + // Starting index + var startIndex = index; + + // Serialize the function + // Get the function string + var functionString = typeof value.code == 'string' ? value.code : value.code.toString(); + var codeSize = Buffer.byteLength(functionString) + 1; + // Index adjustment + index = index + 4; + // Write the size of the string to buffer + buffer[index] = codeSize & 0xff; + buffer[index + 1] = (codeSize >> 8) & 0xff; + buffer[index + 2] = (codeSize >> 16) & 0xff; + buffer[index + 3] = (codeSize >> 24) & 0xff; + // Write string into buffer + buffer.write(functionString, index + 4, 'utf8'); + // Write end 0 + buffer[index + 4 + codeSize - 1] = 0; + // Write the + index = index + codeSize + 4; + + // + // Serialize the scope value + var endIndex = serializeInto(value.scope, checkKeys, index, depth + 1) + index = endIndex - 1; + + // Writ the total + var totalSize = endIndex - startIndex; + + // Write the total size of the object + buffer[startIndex++] = totalSize & 0xff; + buffer[startIndex++] = (totalSize >> 8) & 0xff; + buffer[startIndex++] = (totalSize >> 16) & 0xff; + buffer[startIndex++] = (totalSize >> 24) & 0xff; + // Write trailing zero + buffer[index++] = 0; + } else { + buffer[index++] = BSON.BSON_DATA_CODE; + // Number of written bytes + var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); + // Encode the name + index = index + numberOfWrittenBytes; + buffer[index++] = 0; + // Function string + var functionString = value.code.toString(); + // Function Size + var size = Buffer.byteLength(functionString) + 1; + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + // Write the string + buffer.write(functionString, index, 'utf8'); + // Update index + index = index + size - 1; + // Write zero + buffer[index++] = 0; + } + + return index; +} + +var serializeBinary = function(key, value, index) { + // Write the type + buffer[index++] = BSON.BSON_DATA_BINARY; + // Number of written bytes + var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); + // Encode the name + index = index + numberOfWrittenBytes; + buffer[index++] = 0; + // Extract the buffer + var data = value.value(true); + // Calculate size + var size = value.position; + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + // Write the subtype to the buffer + buffer[index++] = value.sub_type; + + // If we have binary type 2 the 4 first bytes are the size + if(value.sub_type == Binary.SUBTYPE_BYTE_ARRAY) { + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + } + + // Write the data to the object + data.copy(buffer, index, 0, value.position); + // Adjust the index + index = index + value.position; + return index; +} + +var serializeSymbol = function(key, value, index) { + // Write the type + buffer[index++] = BSON.BSON_DATA_SYMBOL; + // Number of written bytes + var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); + // Encode the name + index = index + numberOfWrittenBytes; + buffer[index++] = 0; + // Calculate size + var size = Buffer.byteLength(value.value) + 1; + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + // Write the string + buffer.write(value.value, index, 'utf8'); + // Update index + index = index + size - 1; + // Write zero + buffer[index++] = 0x00; + return index; +} + +var serializeDBRef = function(key, value, index, depth) { + // Write the type + buffer[index++] = BSON.BSON_DATA_OBJECT; + // Number of written bytes + var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); + + // Encode the name + index = index + numberOfWrittenBytes; + buffer[index++] = 0; + + var startIndex = index; + var endIndex; + + // Serialize object + if(null != value.db) { + endIndex = serializeInto({ + '$ref': value.namespace + , '$id' : value.oid + , '$db' : value.db + }, false, index, depth + 1); + } else { + endIndex = serializeInto({ + '$ref': value.namespace + , '$id' : value.oid + }, false, index, depth + 1); + } + + // Calculate object size + var size = endIndex - startIndex; + // Write the size + buffer[startIndex++] = size & 0xff; + buffer[startIndex++] = (size >> 8) & 0xff; + buffer[startIndex++] = (size >> 16) & 0xff; + buffer[startIndex++] = (size >> 24) & 0xff; + // Set index + return endIndex; +} + +var BSON = function() { + this.buffer = buffer; +} + +BSON.prototype.serialize = function serialize(object, checkKeys, index) { + var finishedBuffer = new Buffer(serializeInto(object, checkKeys, index || 0, 0)); + this.buffer.copy(finishedBuffer, 0, 0, finishedBuffer.length); + return finishedBuffer; +} + +var serializeInto = function serializeInto(object, checkKeys, startingIndex, depth) { + startingIndex = startingIndex || 0; + + // Start place to serialize into + var index = startingIndex + 4; + var self = this; + + // Special case isArray + if(Array.isArray(object)) { + // Get object keys + for(var i = 0; i < object.length; i++) { + var key = "" + i; + var type = typeof object[i]; + + // Check the key and throw error if it's illegal + if(key != '$db' && key != '$ref' && key != '$id') { + checkKey(key, !checkKeys); + } + + if(type == 'string') { + index = serializeString(key, object[i], index); + } else if(type == 'number') { + index = serializeNumber(key, object[i], index); + } else if(type == 'undefined') { + index = serializeUndefined(key, object[i], index); + } else if(type == 'boolean') { + index = serializeBoolean(key, object[i], index); + } else if(object[i] instanceof Date) { + index = serializeDate(key, object[i], index); + } else if(object[i] instanceof RegExp || Object.prototype.toString.call(object[i]) === '[object RegExp]') { + index = serializeRegExp(key, object[i], index); + } else if(object[i]['_bsontype'] == 'MinKey' || object[i]['_bsontype'] == 'MaxKey') { + index = serializeMinMax(key, object[i], index); + } else if(object[i]['_bsontype'] == 'ObjectID') { + index = serializeObjectId(key, object[i], index); + } else if(Buffer.isBuffer(object[i])) { + index = serializeBuffer(key, object[i], index); + } else if(type == 'object' && object[i]['_bsontype'] == null) { + index = serializeObject(key, object[i], index, checkKeys, depth); + } else if(object[i]['_bsontype'] == 'Long' || object[i]['_bsontype'] == 'Timestamp') { + index = serializeLong(key, object[i], index); + } else if(object[i]['_bsontype'] == 'Double') { + index = serializeDouble(key, object[i], index); + } else if(object[i]['_bsontype'] == 'Code') { + index = serializeCode(key, object[i], index, checkKeys, depth); + } else if(object[i]['_bsontype'] == 'Binary') { + index = serializeBinary(key, object[i], index); + } else if(object[i]['_bsontype'] == 'Symbol') { + index = serializeSymbol(key, object[i], index); + } else if(object[i]['_bsontype'] == 'DBRef') { + index = serializeDBRef(key, object[i], index, depth); + } + } + } else { + var keys = Object.keys(object); + for(var i = 0; i < keys.length; i++) { + var key = keys[i]; + var type = typeof object[key]; + + // Check the key and throw error if it's illegal + if(key != '$db' && key != '$ref' && key != '$id') { + checkKey(key, !checkKeys); + } + + if(type == 'string') { + index = serializeString(key, object[key], index); + } else if(type == 'number') { + index = serializeNumber(key, object[key], index); + } else if(type == 'undefined') { + index = serializeUndefined(key, object[key], index); + } else if(type == 'boolean') { + index = serializeBoolean(key, object[key], index); + } else if(object[key] instanceof Date) { + index = serializeDate(key, object[key], index); + } else if(object[key] instanceof RegExp || Object.prototype.toString.call(object[key]) === '[object RegExp]') { + index = serializeRegExp(key, object[key], index); + } else if(object[key]['_bsontype'] == 'MinKey' || object[key]['_bsontype'] == 'MaxKey') { + index = serializeMinMax(key, object[key], index); + } else if(object[key]['_bsontype'] == 'ObjectID') { + index = serializeObjectId(key, object[key], index); + } else if(Buffer.isBuffer(object[key])) { + index = serializeBuffer(key, object[key], index); + } else if(type == 'object' && object[key]['_bsontype'] == null) { + index = serializeObject(key, object[key], index, checkKeys, depth); + } else if(object[key]['_bsontype'] == 'Long' || object[key]['_bsontype'] == 'Timestamp') { + index = serializeLong(key, object[key], index); + } else if(object[key]['_bsontype'] == 'Double') { + index = serializeDouble(key, object[key], index); + } else if(object[key]['_bsontype'] == 'Code') { + index = serializeCode(key, object[key], index, checkKeys, depth); + } else if(object[key]['_bsontype'] == 'Binary') { + index = serializeBinary(key, object[key], index); + } else if(object[key]['_bsontype'] == 'Symbol') { + index = serializeSymbol(key, object[key], index); + } else if(object[key]['_bsontype'] == 'DBRef') { + index = serializeDBRef(key, object[key], index, depth); + } + } + } + + // Final padding byte for object + buffer[index++] = 0x00; + + // Final size + var size = index - startingIndex; + // Write the size of the object + buffer[startingIndex++] = size & 0xff; + buffer[startingIndex++] = (size >> 8) & 0xff; + buffer[startingIndex++] = (size >> 16) & 0xff; + buffer[startingIndex++] = (size >> 24) & 0xff; + return index; +} + +/** + * @ignore + * @api private + */ +// BSON MAX VALUES +BSON.BSON_INT32_MAX = 0x7FFFFFFF; +BSON.BSON_INT32_MIN = -0x80000000; + +BSON.BSON_INT64_MAX = Math.pow(2, 63) - 1; +BSON.BSON_INT64_MIN = -Math.pow(2, 63); + +// JS MAX PRECISE VALUES +BSON.JS_INT_MAX = 0x20000000000000; // Any integer up to 2^53 can be precisely represented by a double. +BSON.JS_INT_MIN = -0x20000000000000; // Any integer down to -2^53 can be precisely represented by a double. + +// Internal long versions +var JS_INT_MAX_LONG = Long.fromNumber(0x20000000000000); // Any integer up to 2^53 can be precisely represented by a double. +var JS_INT_MIN_LONG = Long.fromNumber(-0x20000000000000); // Any integer down to -2^53 can be precisely represented by a double. + +/** + * Number BSON Type + * + * @classconstant BSON_DATA_NUMBER + **/ +BSON.BSON_DATA_NUMBER = 1; +/** + * String BSON Type + * + * @classconstant BSON_DATA_STRING + **/ +BSON.BSON_DATA_STRING = 2; +/** + * Object BSON Type + * + * @classconstant BSON_DATA_OBJECT + **/ +BSON.BSON_DATA_OBJECT = 3; +/** + * Array BSON Type + * + * @classconstant BSON_DATA_ARRAY + **/ +BSON.BSON_DATA_ARRAY = 4; +/** + * Binary BSON Type + * + * @classconstant BSON_DATA_BINARY + **/ +BSON.BSON_DATA_BINARY = 5; +/** + * ObjectID BSON Type + * + * @classconstant BSON_DATA_OID + **/ +BSON.BSON_DATA_OID = 7; +/** + * Boolean BSON Type + * + * @classconstant BSON_DATA_BOOLEAN + **/ +BSON.BSON_DATA_BOOLEAN = 8; +/** + * Date BSON Type + * + * @classconstant BSON_DATA_DATE + **/ +BSON.BSON_DATA_DATE = 9; +/** + * null BSON Type + * + * @classconstant BSON_DATA_NULL + **/ +BSON.BSON_DATA_NULL = 10; +/** + * RegExp BSON Type + * + * @classconstant BSON_DATA_REGEXP + **/ +BSON.BSON_DATA_REGEXP = 11; +/** + * Code BSON Type + * + * @classconstant BSON_DATA_CODE + **/ +BSON.BSON_DATA_CODE = 13; +/** + * Symbol BSON Type + * + * @classconstant BSON_DATA_SYMBOL + **/ +BSON.BSON_DATA_SYMBOL = 14; +/** + * Code with Scope BSON Type + * + * @classconstant BSON_DATA_CODE_W_SCOPE + **/ +BSON.BSON_DATA_CODE_W_SCOPE = 15; +/** + * 32 bit Integer BSON Type + * + * @classconstant BSON_DATA_INT + **/ +BSON.BSON_DATA_INT = 16; +/** + * Timestamp BSON Type + * + * @classconstant BSON_DATA_TIMESTAMP + **/ +BSON.BSON_DATA_TIMESTAMP = 17; +/** + * Long BSON Type + * + * @classconstant BSON_DATA_LONG + **/ +BSON.BSON_DATA_LONG = 18; +/** + * MinKey BSON Type + * + * @classconstant BSON_DATA_MIN_KEY + **/ +BSON.BSON_DATA_MIN_KEY = 0xff; +/** + * MaxKey BSON Type + * + * @classconstant BSON_DATA_MAX_KEY + **/ +BSON.BSON_DATA_MAX_KEY = 0x7f; + +/** + * Binary Default Type + * + * @classconstant BSON_BINARY_SUBTYPE_DEFAULT + **/ +BSON.BSON_BINARY_SUBTYPE_DEFAULT = 0; +/** + * Binary Function Type + * + * @classconstant BSON_BINARY_SUBTYPE_FUNCTION + **/ +BSON.BSON_BINARY_SUBTYPE_FUNCTION = 1; +/** + * Binary Byte Array Type + * + * @classconstant BSON_BINARY_SUBTYPE_BYTE_ARRAY + **/ +BSON.BSON_BINARY_SUBTYPE_BYTE_ARRAY = 2; +/** + * Binary UUID Type + * + * @classconstant BSON_BINARY_SUBTYPE_UUID + **/ +BSON.BSON_BINARY_SUBTYPE_UUID = 3; +/** + * Binary MD5 Type + * + * @classconstant BSON_BINARY_SUBTYPE_MD5 + **/ +BSON.BSON_BINARY_SUBTYPE_MD5 = 4; +/** + * Binary User Defined Type + * + * @classconstant BSON_BINARY_SUBTYPE_USER_DEFINED + **/ +BSON.BSON_BINARY_SUBTYPE_USER_DEFINED = 128; + +// Return BSON +exports.BSON = BSON; \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/bson/lib/bson/code.js b/node_modules/mongodb/node_modules/bson/lib/bson/code.js new file mode 100644 index 0000000..c534103 --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/lib/bson/code.js @@ -0,0 +1,24 @@ +/** + * A class representation of the BSON Code type. + * + * @class Represents the BSON Code type. + * @param {String|Function} code a string or function. + * @param {Object} [scope] an optional scope for the function. + * @return {Code} + */ +var Code = function Code(code, scope) { + if(!(this instanceof Code)) return new Code(code, scope); + this._bsontype = 'Code'; + this.code = code; + this.scope = scope == null ? {} : scope; +}; + +/** + * @ignore + * @api private + */ +Code.prototype.toJSON = function() { + return {scope:this.scope, code:this.code}; +} + +exports.Code = Code; \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/bson/lib/bson/db_ref.js b/node_modules/mongodb/node_modules/bson/lib/bson/db_ref.js new file mode 100644 index 0000000..56b6510 --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/lib/bson/db_ref.js @@ -0,0 +1,31 @@ +/** + * A class representation of the BSON DBRef type. + * + * @class Represents the BSON DBRef type. + * @param {String} namespace the collection name. + * @param {ObjectID} oid the reference ObjectID. + * @param {String} [db] optional db name, if omitted the reference is local to the current db. + * @return {DBRef} + */ +function DBRef(namespace, oid, db) { + if(!(this instanceof DBRef)) return new DBRef(namespace, oid, db); + + this._bsontype = 'DBRef'; + this.namespace = namespace; + this.oid = oid; + this.db = db; +}; + +/** + * @ignore + * @api private + */ +DBRef.prototype.toJSON = function() { + return { + '$ref':this.namespace, + '$id':this.oid, + '$db':this.db == null ? '' : this.db + }; +} + +exports.DBRef = DBRef; \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/bson/lib/bson/double.js b/node_modules/mongodb/node_modules/bson/lib/bson/double.js new file mode 100644 index 0000000..ae51463 --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/lib/bson/double.js @@ -0,0 +1,33 @@ +/** + * A class representation of the BSON Double type. + * + * @class Represents the BSON Double type. + * @param {Number} value the number we want to represent as a double. + * @return {Double} + */ +function Double(value) { + if(!(this instanceof Double)) return new Double(value); + + this._bsontype = 'Double'; + this.value = value; +} + +/** + * Access the number value. + * + * @return {Number} returns the wrapped double number. + * @api public + */ +Double.prototype.valueOf = function() { + return this.value; +}; + +/** + * @ignore + * @api private + */ +Double.prototype.toJSON = function() { + return this.value; +} + +exports.Double = Double; \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/bson/lib/bson/float_parser.js b/node_modules/mongodb/node_modules/bson/lib/bson/float_parser.js new file mode 100644 index 0000000..6fca392 --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/lib/bson/float_parser.js @@ -0,0 +1,121 @@ +// Copyright (c) 2008, Fair Oaks Labs, Inc. +// All rights reserved. +// +// 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. +// +// * Neither the name of Fair Oaks Labs, Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 OWNER OR CONTRIBUTORS 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. +// +// +// Modifications to writeIEEE754 to support negative zeroes made by Brian White + +var readIEEE754 = function(buffer, offset, endian, mLen, nBytes) { + var e, m, + bBE = (endian === 'big'), + eLen = nBytes * 8 - mLen - 1, + eMax = (1 << eLen) - 1, + eBias = eMax >> 1, + nBits = -7, + i = bBE ? 0 : (nBytes - 1), + d = bBE ? 1 : -1, + s = buffer[offset + i]; + + i += d; + + e = s & ((1 << (-nBits)) - 1); + s >>= (-nBits); + nBits += eLen; + for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8); + + m = e & ((1 << (-nBits)) - 1); + e >>= (-nBits); + nBits += mLen; + for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8); + + if (e === 0) { + e = 1 - eBias; + } else if (e === eMax) { + return m ? NaN : ((s ? -1 : 1) * Infinity); + } else { + m = m + Math.pow(2, mLen); + e = e - eBias; + } + return (s ? -1 : 1) * m * Math.pow(2, e - mLen); +}; + +var writeIEEE754 = function(buffer, value, offset, endian, mLen, nBytes) { + var e, m, c, + bBE = (endian === 'big'), + eLen = nBytes * 8 - mLen - 1, + eMax = (1 << eLen) - 1, + eBias = eMax >> 1, + rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0), + i = bBE ? (nBytes-1) : 0, + d = bBE ? -1 : 1, + s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0; + + value = Math.abs(value); + + if (isNaN(value) || value === Infinity) { + m = isNaN(value) ? 1 : 0; + e = eMax; + } else { + e = Math.floor(Math.log(value) / Math.LN2); + if (value * (c = Math.pow(2, -e)) < 1) { + e--; + c *= 2; + } + if (e+eBias >= 1) { + value += rt / c; + } else { + value += rt * Math.pow(2, 1 - eBias); + } + if (value * c >= 2) { + e++; + c /= 2; + } + + if (e + eBias >= eMax) { + m = 0; + e = eMax; + } else if (e + eBias >= 1) { + m = (value * c - 1) * Math.pow(2, mLen); + e = e + eBias; + } else { + m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen); + e = 0; + } + } + + for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8); + + e = (e << mLen) | m; + eLen += mLen; + for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8); + + buffer[offset + i - d] |= s * 128; +}; + +exports.readIEEE754 = readIEEE754; +exports.writeIEEE754 = writeIEEE754; \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/bson/lib/bson/index.js b/node_modules/mongodb/node_modules/bson/lib/bson/index.js new file mode 100644 index 0000000..950fcad --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/lib/bson/index.js @@ -0,0 +1,74 @@ +try { + exports.BSONPure = require('./bson'); + exports.BSONNative = require('../../ext'); +} catch(err) { + // do nothing +} + +[ './binary_parser' + , './binary' + , './code' + , './db_ref' + , './double' + , './max_key' + , './min_key' + , './objectid' + , './symbol' + , './timestamp' + , './long'].forEach(function (path) { + var module = require('./' + path); + for (var i in module) { + exports[i] = module[i]; + } +}); + +// Exports all the classes for the NATIVE JS BSON Parser +exports.native = function() { + var classes = {}; + // Map all the classes + [ './binary_parser' + , './binary' + , './code' + , './db_ref' + , './double' + , './max_key' + , './min_key' + , './objectid' + , './symbol' + , './timestamp' + , './long' + , '../../ext' +].forEach(function (path) { + var module = require('./' + path); + for (var i in module) { + classes[i] = module[i]; + } + }); + // Return classes list + return classes; +} + +// Exports all the classes for the PURE JS BSON Parser +exports.pure = function() { + var classes = {}; + // Map all the classes + [ './binary_parser' + , './binary' + , './code' + , './db_ref' + , './double' + , './max_key' + , './min_key' + , './objectid' + , './symbol' + , './timestamp' + , './long' + , '././bson'].forEach(function (path) { + var module = require('./' + path); + for (var i in module) { + classes[i] = module[i]; + } + }); + // Return classes list + return classes; +} diff --git a/node_modules/mongodb/node_modules/bson/lib/bson/long.js b/node_modules/mongodb/node_modules/bson/lib/bson/long.js new file mode 100644 index 0000000..f8f37a6 --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/lib/bson/long.js @@ -0,0 +1,854 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Copyright 2009 Google Inc. All Rights Reserved + +/** + * Defines a Long class for representing a 64-bit two's-complement + * integer value, which faithfully simulates the behavior of a Java "Long". This + * implementation is derived from LongLib in GWT. + * + * Constructs a 64-bit two's-complement integer, given its low and high 32-bit + * values as *signed* integers. See the from* functions below for more + * convenient ways of constructing Longs. + * + * The internal representation of a Long is the two given signed, 32-bit values. + * We use 32-bit pieces because these are the size of integers on which + * Javascript performs bit-operations. For operations like addition and + * multiplication, we split each number into 16-bit pieces, which can easily be + * multiplied within Javascript's floating-point representation without overflow + * or change in sign. + * + * In the algorithms below, we frequently reduce the negative case to the + * positive case by negating the input(s) and then post-processing the result. + * Note that we must ALWAYS check specially whether those values are MIN_VALUE + * (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as + * a positive number, it overflows back into a negative). Not handling this + * case would often result in infinite recursion. + * + * @class Represents the BSON Long type. + * @param {Number} low the low (signed) 32 bits of the Long. + * @param {Number} high the high (signed) 32 bits of the Long. + */ +function Long(low, high) { + if(!(this instanceof Long)) return new Long(low, high); + + this._bsontype = 'Long'; + /** + * @type {number} + * @api private + */ + this.low_ = low | 0; // force into 32 signed bits. + + /** + * @type {number} + * @api private + */ + this.high_ = high | 0; // force into 32 signed bits. +}; + +/** + * Return the int value. + * + * @return {Number} the value, assuming it is a 32-bit integer. + * @api public + */ +Long.prototype.toInt = function() { + return this.low_; +}; + +/** + * Return the Number value. + * + * @return {Number} the closest floating-point representation to this value. + * @api public + */ +Long.prototype.toNumber = function() { + return this.high_ * Long.TWO_PWR_32_DBL_ + + this.getLowBitsUnsigned(); +}; + +/** + * Return the JSON value. + * + * @return {String} the JSON representation. + * @api public + */ +Long.prototype.toJSON = function() { + return this.toString(); +} + +/** + * Return the String value. + * + * @param {Number} [opt_radix] the radix in which the text should be written. + * @return {String} the textual representation of this value. + * @api public + */ +Long.prototype.toString = function(opt_radix) { + var radix = opt_radix || 10; + if (radix < 2 || 36 < radix) { + throw Error('radix out of range: ' + radix); + } + + if (this.isZero()) { + return '0'; + } + + if (this.isNegative()) { + if (this.equals(Long.MIN_VALUE)) { + // We need to change the Long value before it can be negated, so we remove + // the bottom-most digit in this base and then recurse to do the rest. + var radixLong = Long.fromNumber(radix); + var div = this.div(radixLong); + var rem = div.multiply(radixLong).subtract(this); + return div.toString(radix) + rem.toInt().toString(radix); + } else { + return '-' + this.negate().toString(radix); + } + } + + // Do several (6) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = Long.fromNumber(Math.pow(radix, 6)); + + var rem = this; + var result = ''; + while (true) { + var remDiv = rem.div(radixToPower); + var intval = rem.subtract(remDiv.multiply(radixToPower)).toInt(); + var digits = intval.toString(radix); + + rem = remDiv; + if (rem.isZero()) { + return digits + result; + } else { + while (digits.length < 6) { + digits = '0' + digits; + } + result = '' + digits + result; + } + } +}; + +/** + * Return the high 32-bits value. + * + * @return {Number} the high 32-bits as a signed value. + * @api public + */ +Long.prototype.getHighBits = function() { + return this.high_; +}; + +/** + * Return the low 32-bits value. + * + * @return {Number} the low 32-bits as a signed value. + * @api public + */ +Long.prototype.getLowBits = function() { + return this.low_; +}; + +/** + * Return the low unsigned 32-bits value. + * + * @return {Number} the low 32-bits as an unsigned value. + * @api public + */ +Long.prototype.getLowBitsUnsigned = function() { + return (this.low_ >= 0) ? + this.low_ : Long.TWO_PWR_32_DBL_ + this.low_; +}; + +/** + * Returns the number of bits needed to represent the absolute value of this Long. + * + * @return {Number} Returns the number of bits needed to represent the absolute value of this Long. + * @api public + */ +Long.prototype.getNumBitsAbs = function() { + if (this.isNegative()) { + if (this.equals(Long.MIN_VALUE)) { + return 64; + } else { + return this.negate().getNumBitsAbs(); + } + } else { + var val = this.high_ != 0 ? this.high_ : this.low_; + for (var bit = 31; bit > 0; bit--) { + if ((val & (1 << bit)) != 0) { + break; + } + } + return this.high_ != 0 ? bit + 33 : bit + 1; + } +}; + +/** + * Return whether this value is zero. + * + * @return {Boolean} whether this value is zero. + * @api public + */ +Long.prototype.isZero = function() { + return this.high_ == 0 && this.low_ == 0; +}; + +/** + * Return whether this value is negative. + * + * @return {Boolean} whether this value is negative. + * @api public + */ +Long.prototype.isNegative = function() { + return this.high_ < 0; +}; + +/** + * Return whether this value is odd. + * + * @return {Boolean} whether this value is odd. + * @api public + */ +Long.prototype.isOdd = function() { + return (this.low_ & 1) == 1; +}; + +/** + * Return whether this Long equals the other + * + * @param {Long} other Long to compare against. + * @return {Boolean} whether this Long equals the other + * @api public + */ +Long.prototype.equals = function(other) { + return (this.high_ == other.high_) && (this.low_ == other.low_); +}; + +/** + * Return whether this Long does not equal the other. + * + * @param {Long} other Long to compare against. + * @return {Boolean} whether this Long does not equal the other. + * @api public + */ +Long.prototype.notEquals = function(other) { + return (this.high_ != other.high_) || (this.low_ != other.low_); +}; + +/** + * Return whether this Long is less than the other. + * + * @param {Long} other Long to compare against. + * @return {Boolean} whether this Long is less than the other. + * @api public + */ +Long.prototype.lessThan = function(other) { + return this.compare(other) < 0; +}; + +/** + * Return whether this Long is less than or equal to the other. + * + * @param {Long} other Long to compare against. + * @return {Boolean} whether this Long is less than or equal to the other. + * @api public + */ +Long.prototype.lessThanOrEqual = function(other) { + return this.compare(other) <= 0; +}; + +/** + * Return whether this Long is greater than the other. + * + * @param {Long} other Long to compare against. + * @return {Boolean} whether this Long is greater than the other. + * @api public + */ +Long.prototype.greaterThan = function(other) { + return this.compare(other) > 0; +}; + +/** + * Return whether this Long is greater than or equal to the other. + * + * @param {Long} other Long to compare against. + * @return {Boolean} whether this Long is greater than or equal to the other. + * @api public + */ +Long.prototype.greaterThanOrEqual = function(other) { + return this.compare(other) >= 0; +}; + +/** + * Compares this Long with the given one. + * + * @param {Long} other Long to compare against. + * @return {Boolean} 0 if they are the same, 1 if the this is greater, and -1 if the given one is greater. + * @api public + */ +Long.prototype.compare = function(other) { + if (this.equals(other)) { + return 0; + } + + var thisNeg = this.isNegative(); + var otherNeg = other.isNegative(); + if (thisNeg && !otherNeg) { + return -1; + } + if (!thisNeg && otherNeg) { + return 1; + } + + // at this point, the signs are the same, so subtraction will not overflow + if (this.subtract(other).isNegative()) { + return -1; + } else { + return 1; + } +}; + +/** + * The negation of this value. + * + * @return {Long} the negation of this value. + * @api public + */ +Long.prototype.negate = function() { + if (this.equals(Long.MIN_VALUE)) { + return Long.MIN_VALUE; + } else { + return this.not().add(Long.ONE); + } +}; + +/** + * Returns the sum of this and the given Long. + * + * @param {Long} other Long to add to this one. + * @return {Long} the sum of this and the given Long. + * @api public + */ +Long.prototype.add = function(other) { + // Divide each number into 4 chunks of 16 bits, and then sum the chunks. + + var a48 = this.high_ >>> 16; + var a32 = this.high_ & 0xFFFF; + var a16 = this.low_ >>> 16; + var a00 = this.low_ & 0xFFFF; + + var b48 = other.high_ >>> 16; + var b32 = other.high_ & 0xFFFF; + var b16 = other.low_ >>> 16; + var b00 = other.low_ & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 + b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 + b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 + b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 + b48; + c48 &= 0xFFFF; + return Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32); +}; + +/** + * Returns the difference of this and the given Long. + * + * @param {Long} other Long to subtract from this. + * @return {Long} the difference of this and the given Long. + * @api public + */ +Long.prototype.subtract = function(other) { + return this.add(other.negate()); +}; + +/** + * Returns the product of this and the given Long. + * + * @param {Long} other Long to multiply with this. + * @return {Long} the product of this and the other. + * @api public + */ +Long.prototype.multiply = function(other) { + if (this.isZero()) { + return Long.ZERO; + } else if (other.isZero()) { + return Long.ZERO; + } + + if (this.equals(Long.MIN_VALUE)) { + return other.isOdd() ? Long.MIN_VALUE : Long.ZERO; + } else if (other.equals(Long.MIN_VALUE)) { + return this.isOdd() ? Long.MIN_VALUE : Long.ZERO; + } + + if (this.isNegative()) { + if (other.isNegative()) { + return this.negate().multiply(other.negate()); + } else { + return this.negate().multiply(other).negate(); + } + } else if (other.isNegative()) { + return this.multiply(other.negate()).negate(); + } + + // If both Longs are small, use float multiplication + if (this.lessThan(Long.TWO_PWR_24_) && + other.lessThan(Long.TWO_PWR_24_)) { + return Long.fromNumber(this.toNumber() * other.toNumber()); + } + + // Divide each Long into 4 chunks of 16 bits, and then add up 4x4 products. + // We can skip products that would overflow. + + var a48 = this.high_ >>> 16; + var a32 = this.high_ & 0xFFFF; + var a16 = this.low_ >>> 16; + var a00 = this.low_ & 0xFFFF; + + var b48 = other.high_ >>> 16; + var b32 = other.high_ & 0xFFFF; + var b16 = other.low_ >>> 16; + var b00 = other.low_ & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 * b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 * b00; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c16 += a00 * b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 * b00; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a16 * b16; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a00 * b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48; + c48 &= 0xFFFF; + return Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32); +}; + +/** + * Returns this Long divided by the given one. + * + * @param {Long} other Long by which to divide. + * @return {Long} this Long divided by the given one. + * @api public + */ +Long.prototype.div = function(other) { + if (other.isZero()) { + throw Error('division by zero'); + } else if (this.isZero()) { + return Long.ZERO; + } + + if (this.equals(Long.MIN_VALUE)) { + if (other.equals(Long.ONE) || + other.equals(Long.NEG_ONE)) { + return Long.MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE + } else if (other.equals(Long.MIN_VALUE)) { + return Long.ONE; + } else { + // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|. + var halfThis = this.shiftRight(1); + var approx = halfThis.div(other).shiftLeft(1); + if (approx.equals(Long.ZERO)) { + return other.isNegative() ? Long.ONE : Long.NEG_ONE; + } else { + var rem = this.subtract(other.multiply(approx)); + var result = approx.add(rem.div(other)); + return result; + } + } + } else if (other.equals(Long.MIN_VALUE)) { + return Long.ZERO; + } + + if (this.isNegative()) { + if (other.isNegative()) { + return this.negate().div(other.negate()); + } else { + return this.negate().div(other).negate(); + } + } else if (other.isNegative()) { + return this.div(other.negate()).negate(); + } + + // Repeat the following until the remainder is less than other: find a + // floating-point that approximates remainder / other *from below*, add this + // into the result, and subtract it from the remainder. It is critical that + // the approximate value is less than or equal to the real value so that the + // remainder never becomes negative. + var res = Long.ZERO; + var rem = this; + while (rem.greaterThanOrEqual(other)) { + // Approximate the result of division. This may be a little greater or + // smaller than the actual value. + var approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber())); + + // We will tweak the approximate result by changing it in the 48-th digit or + // the smallest non-fractional digit, whichever is larger. + var log2 = Math.ceil(Math.log(approx) / Math.LN2); + var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48); + + // Decrease the approximation until it is smaller than the remainder. Note + // that if it is too large, the product overflows and is negative. + var approxRes = Long.fromNumber(approx); + var approxRem = approxRes.multiply(other); + while (approxRem.isNegative() || approxRem.greaterThan(rem)) { + approx -= delta; + approxRes = Long.fromNumber(approx); + approxRem = approxRes.multiply(other); + } + + // We know the answer can't be zero... and actually, zero would cause + // infinite recursion since we would make no progress. + if (approxRes.isZero()) { + approxRes = Long.ONE; + } + + res = res.add(approxRes); + rem = rem.subtract(approxRem); + } + return res; +}; + +/** + * Returns this Long modulo the given one. + * + * @param {Long} other Long by which to mod. + * @return {Long} this Long modulo the given one. + * @api public + */ +Long.prototype.modulo = function(other) { + return this.subtract(this.div(other).multiply(other)); +}; + +/** + * The bitwise-NOT of this value. + * + * @return {Long} the bitwise-NOT of this value. + * @api public + */ +Long.prototype.not = function() { + return Long.fromBits(~this.low_, ~this.high_); +}; + +/** + * Returns the bitwise-AND of this Long and the given one. + * + * @param {Long} other the Long with which to AND. + * @return {Long} the bitwise-AND of this and the other. + * @api public + */ +Long.prototype.and = function(other) { + return Long.fromBits(this.low_ & other.low_, this.high_ & other.high_); +}; + +/** + * Returns the bitwise-OR of this Long and the given one. + * + * @param {Long} other the Long with which to OR. + * @return {Long} the bitwise-OR of this and the other. + * @api public + */ +Long.prototype.or = function(other) { + return Long.fromBits(this.low_ | other.low_, this.high_ | other.high_); +}; + +/** + * Returns the bitwise-XOR of this Long and the given one. + * + * @param {Long} other the Long with which to XOR. + * @return {Long} the bitwise-XOR of this and the other. + * @api public + */ +Long.prototype.xor = function(other) { + return Long.fromBits(this.low_ ^ other.low_, this.high_ ^ other.high_); +}; + +/** + * Returns this Long with bits shifted to the left by the given amount. + * + * @param {Number} numBits the number of bits by which to shift. + * @return {Long} this shifted to the left by the given amount. + * @api public + */ +Long.prototype.shiftLeft = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var low = this.low_; + if (numBits < 32) { + var high = this.high_; + return Long.fromBits( + low << numBits, + (high << numBits) | (low >>> (32 - numBits))); + } else { + return Long.fromBits(0, low << (numBits - 32)); + } + } +}; + +/** + * Returns this Long with bits shifted to the right by the given amount. + * + * @param {Number} numBits the number of bits by which to shift. + * @return {Long} this shifted to the right by the given amount. + * @api public + */ +Long.prototype.shiftRight = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var high = this.high_; + if (numBits < 32) { + var low = this.low_; + return Long.fromBits( + (low >>> numBits) | (high << (32 - numBits)), + high >> numBits); + } else { + return Long.fromBits( + high >> (numBits - 32), + high >= 0 ? 0 : -1); + } + } +}; + +/** + * Returns this Long with bits shifted to the right by the given amount, with the new top bits matching the current sign bit. + * + * @param {Number} numBits the number of bits by which to shift. + * @return {Long} this shifted to the right by the given amount, with zeros placed into the new leading bits. + * @api public + */ +Long.prototype.shiftRightUnsigned = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var high = this.high_; + if (numBits < 32) { + var low = this.low_; + return Long.fromBits( + (low >>> numBits) | (high << (32 - numBits)), + high >>> numBits); + } else if (numBits == 32) { + return Long.fromBits(high, 0); + } else { + return Long.fromBits(high >>> (numBits - 32), 0); + } + } +}; + +/** + * Returns a Long representing the given (32-bit) integer value. + * + * @param {Number} value the 32-bit integer in question. + * @return {Long} the corresponding Long value. + * @api public + */ +Long.fromInt = function(value) { + if (-128 <= value && value < 128) { + var cachedObj = Long.INT_CACHE_[value]; + if (cachedObj) { + return cachedObj; + } + } + + var obj = new Long(value | 0, value < 0 ? -1 : 0); + if (-128 <= value && value < 128) { + Long.INT_CACHE_[value] = obj; + } + return obj; +}; + +/** + * Returns a Long representing the given value, provided that it is a finite number. Otherwise, zero is returned. + * + * @param {Number} value the number in question. + * @return {Long} the corresponding Long value. + * @api public + */ +Long.fromNumber = function(value) { + if (isNaN(value) || !isFinite(value)) { + return Long.ZERO; + } else if (value <= -Long.TWO_PWR_63_DBL_) { + return Long.MIN_VALUE; + } else if (value + 1 >= Long.TWO_PWR_63_DBL_) { + return Long.MAX_VALUE; + } else if (value < 0) { + return Long.fromNumber(-value).negate(); + } else { + return new Long( + (value % Long.TWO_PWR_32_DBL_) | 0, + (value / Long.TWO_PWR_32_DBL_) | 0); + } +}; + +/** + * Returns a Long representing the 64-bit integer that comes by concatenating the given high and low bits. Each is assumed to use 32 bits. + * + * @param {Number} lowBits the low 32-bits. + * @param {Number} highBits the high 32-bits. + * @return {Long} the corresponding Long value. + * @api public + */ +Long.fromBits = function(lowBits, highBits) { + return new Long(lowBits, highBits); +}; + +/** + * Returns a Long representation of the given string, written using the given radix. + * + * @param {String} str the textual representation of the Long. + * @param {Number} opt_radix the radix in which the text is written. + * @return {Long} the corresponding Long value. + * @api public + */ +Long.fromString = function(str, opt_radix) { + if (str.length == 0) { + throw Error('number format error: empty string'); + } + + var radix = opt_radix || 10; + if (radix < 2 || 36 < radix) { + throw Error('radix out of range: ' + radix); + } + + if (str.charAt(0) == '-') { + return Long.fromString(str.substring(1), radix).negate(); + } else if (str.indexOf('-') >= 0) { + throw Error('number format error: interior "-" character: ' + str); + } + + // Do several (8) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = Long.fromNumber(Math.pow(radix, 8)); + + var result = Long.ZERO; + for (var i = 0; i < str.length; i += 8) { + var size = Math.min(8, str.length - i); + var value = parseInt(str.substring(i, i + size), radix); + if (size < 8) { + var power = Long.fromNumber(Math.pow(radix, size)); + result = result.multiply(power).add(Long.fromNumber(value)); + } else { + result = result.multiply(radixToPower); + result = result.add(Long.fromNumber(value)); + } + } + return result; +}; + +// NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the +// from* methods on which they depend. + + +/** + * A cache of the Long representations of small integer values. + * @type {Object} + * @api private + */ +Long.INT_CACHE_ = {}; + +// NOTE: the compiler should inline these constant values below and then remove +// these variables, so there should be no runtime penalty for these. + +/** + * Number used repeated below in calculations. This must appear before the + * first call to any from* function below. + * @type {number} + * @api private + */ +Long.TWO_PWR_16_DBL_ = 1 << 16; + +/** + * @type {number} + * @api private + */ +Long.TWO_PWR_24_DBL_ = 1 << 24; + +/** + * @type {number} + * @api private + */ +Long.TWO_PWR_32_DBL_ = Long.TWO_PWR_16_DBL_ * Long.TWO_PWR_16_DBL_; + +/** + * @type {number} + * @api private + */ +Long.TWO_PWR_31_DBL_ = Long.TWO_PWR_32_DBL_ / 2; + +/** + * @type {number} + * @api private + */ +Long.TWO_PWR_48_DBL_ = Long.TWO_PWR_32_DBL_ * Long.TWO_PWR_16_DBL_; + +/** + * @type {number} + * @api private + */ +Long.TWO_PWR_64_DBL_ = Long.TWO_PWR_32_DBL_ * Long.TWO_PWR_32_DBL_; + +/** + * @type {number} + * @api private + */ +Long.TWO_PWR_63_DBL_ = Long.TWO_PWR_64_DBL_ / 2; + +/** @type {Long} */ +Long.ZERO = Long.fromInt(0); + +/** @type {Long} */ +Long.ONE = Long.fromInt(1); + +/** @type {Long} */ +Long.NEG_ONE = Long.fromInt(-1); + +/** @type {Long} */ +Long.MAX_VALUE = + Long.fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0); + +/** @type {Long} */ +Long.MIN_VALUE = Long.fromBits(0, 0x80000000 | 0); + +/** + * @type {Long} + * @api private + */ +Long.TWO_PWR_24_ = Long.fromInt(1 << 24); + +/** + * Expose. + */ +exports.Long = Long; \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/bson/lib/bson/max_key.js b/node_modules/mongodb/node_modules/bson/lib/bson/max_key.js new file mode 100644 index 0000000..0825408 --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/lib/bson/max_key.js @@ -0,0 +1,13 @@ +/** + * A class representation of the BSON MaxKey type. + * + * @class Represents the BSON MaxKey type. + * @return {MaxKey} + */ +function MaxKey() { + if(!(this instanceof MaxKey)) return new MaxKey(); + + this._bsontype = 'MaxKey'; +} + +exports.MaxKey = MaxKey; \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/bson/lib/bson/min_key.js b/node_modules/mongodb/node_modules/bson/lib/bson/min_key.js new file mode 100644 index 0000000..230c2e6 --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/lib/bson/min_key.js @@ -0,0 +1,13 @@ +/** + * A class representation of the BSON MinKey type. + * + * @class Represents the BSON MinKey type. + * @return {MinKey} + */ +function MinKey() { + if(!(this instanceof MinKey)) return new MinKey(); + + this._bsontype = 'MinKey'; +} + +exports.MinKey = MinKey; \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/bson/lib/bson/objectid.js b/node_modules/mongodb/node_modules/bson/lib/bson/objectid.js new file mode 100644 index 0000000..52e7197 --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/lib/bson/objectid.js @@ -0,0 +1,266 @@ +/** + * Module dependencies. + */ +var BinaryParser = require('./binary_parser').BinaryParser; + +/** + * Machine id. + * + * Create a random 3-byte value (i.e. unique for this + * process). Other drivers use a md5 of the machine id here, but + * that would mean an asyc call to gethostname, so we don't bother. + */ +var MACHINE_ID = parseInt(Math.random() * 0xFFFFFF, 10); + +// Regular expression that checks for hex value +var checkForHexRegExp = new RegExp("^[0-9a-fA-F]{24}$"); + +/** +* Create a new ObjectID instance +* +* @class Represents the BSON ObjectID type +* @param {String|Number} id Can be a 24 byte hex string, 12 byte binary string or a Number. +* @return {Object} instance of ObjectID. +*/ +var ObjectID = function ObjectID(id) { + if(!(this instanceof ObjectID)) return new ObjectID(id); + if((id instanceof ObjectID)) return id; + + this._bsontype = 'ObjectID'; + var __id = null; + var valid = ObjectID.isValid(id); + + // Throw an error if it's not a valid setup + if(!valid && id != null){ + throw new Error("Argument passed in must be a single String of 12 bytes or a string of 24 hex characters"); + } else if(valid && typeof id == 'string' && id.length == 24) { + return ObjectID.createFromHexString(id); + } else if(id == null || typeof id == 'number') { + // convert to 12 byte binary string + this.id = this.generate(id); + } else if(id != null && id.length === 12) { + // assume 12 byte string + this.id = id; + } + + if(ObjectID.cacheHexString) this.__id = this.toHexString(); +}; + +// Allow usage of ObjectId as well as ObjectID +var ObjectId = ObjectID; + +// Precomputed hex table enables speedy hex string conversion +var hexTable = []; +for (var i = 0; i < 256; i++) { + hexTable[i] = (i <= 15 ? '0' : '') + i.toString(16); +} + +/** +* Return the ObjectID id as a 24 byte hex string representation +* +* @return {String} return the 24 byte hex string representation. +* @api public +*/ +ObjectID.prototype.toHexString = function() { + if(ObjectID.cacheHexString && this.__id) return this.__id; + + var hexString = ''; + + for (var i = 0; i < this.id.length; i++) { + hexString += hexTable[this.id.charCodeAt(i)]; + } + + if(ObjectID.cacheHexString) this.__id = hexString; + return hexString; +}; + +/** +* Update the ObjectID index used in generating new ObjectID's on the driver +* +* @return {Number} returns next index value. +* @api private +*/ +ObjectID.prototype.get_inc = function() { + return ObjectID.index = (ObjectID.index + 1) % 0xFFFFFF; +}; + +/** +* Update the ObjectID index used in generating new ObjectID's on the driver +* +* @return {Number} returns next index value. +* @api private +*/ +ObjectID.prototype.getInc = function() { + return this.get_inc(); +}; + +/** +* Generate a 12 byte id string used in ObjectID's +* +* @param {Number} [time] optional parameter allowing to pass in a second based timestamp. +* @return {String} return the 12 byte id binary string. +* @api private +*/ +ObjectID.prototype.generate = function(time) { + if ('number' != typeof time) { + time = parseInt(Date.now()/1000,10); + } + + var time4Bytes = BinaryParser.encodeInt(time, 32, true, true); + /* for time-based ObjectID the bytes following the time will be zeroed */ + var machine3Bytes = BinaryParser.encodeInt(MACHINE_ID, 24, false); + var pid2Bytes = BinaryParser.fromShort(typeof process === 'undefined' ? Math.floor(Math.random() * 100000) : process.pid); + var index3Bytes = BinaryParser.encodeInt(this.get_inc(), 24, false, true); + + return time4Bytes + machine3Bytes + pid2Bytes + index3Bytes; +}; + +/** +* Converts the id into a 24 byte hex string for printing +* +* @return {String} return the 24 byte hex string representation. +* @api private +*/ +ObjectID.prototype.toString = function() { + return this.toHexString(); +}; + +/** +* Converts to a string representation of this Id. +* +* @return {String} return the 24 byte hex string representation. +* @api private +*/ +ObjectID.prototype.inspect = ObjectID.prototype.toString; + +/** +* Converts to its JSON representation. +* +* @return {String} return the 24 byte hex string representation. +* @api private +*/ +ObjectID.prototype.toJSON = function() { + return this.toHexString(); +}; + +/** +* Compares the equality of this ObjectID with `otherID`. +* +* @param {Object} otherID ObjectID instance to compare against. +* @return {Bool} the result of comparing two ObjectID's +* @api public +*/ +ObjectID.prototype.equals = function equals (otherID) { + if(otherID == null) return false; + var id = (otherID instanceof ObjectID || otherID.toHexString) + ? otherID.id + : ObjectID.createFromHexString(otherID).id; + + return this.id === id; +} + +/** +* Returns the generation date (accurate up to the second) that this ID was generated. +* +* @return {Date} the generation date +* @api public +*/ +ObjectID.prototype.getTimestamp = function() { + var timestamp = new Date(); + timestamp.setTime(Math.floor(BinaryParser.decodeInt(this.id.substring(0,4), 32, true, true)) * 1000); + return timestamp; +} + +/** +* @ignore +* @api private +*/ +ObjectID.index = parseInt(Math.random() * 0xFFFFFF, 10); + +ObjectID.createPk = function createPk () { + return new ObjectID(); +}; + +/** +* Creates an ObjectID from a second based number, with the rest of the ObjectID zeroed out. Used for comparisons or sorting the ObjectID. +* +* @param {Number} time an integer number representing a number of seconds. +* @return {ObjectID} return the created ObjectID +* @api public +*/ +ObjectID.createFromTime = function createFromTime (time) { + var id = BinaryParser.encodeInt(time, 32, true, true) + + BinaryParser.encodeInt(0, 64, true, true); + return new ObjectID(id); +}; + +/** +* Creates an ObjectID from a hex string representation of an ObjectID. +* +* @param {String} hexString create a ObjectID from a passed in 24 byte hexstring. +* @return {ObjectID} return the created ObjectID +* @api public +*/ +ObjectID.createFromHexString = function createFromHexString (hexString) { + // Throw an error if it's not a valid setup + if(typeof hexString === 'undefined' || hexString != null && hexString.length != 24) + throw new Error("Argument passed in must be a single String of 12 bytes or a string of 24 hex characters"); + + var len = hexString.length; + + if(len > 12*2) { + throw new Error('Id cannot be longer than 12 bytes'); + } + + var result = '' + , string + , number; + + for (var index = 0; index < len; index += 2) { + string = hexString.substr(index, 2); + number = parseInt(string, 16); + result += BinaryParser.fromByte(number); + } + + return new ObjectID(result, hexString); +}; + +/** +* Checks if a value is a valid bson ObjectId +* +* @return {Boolean} return true if the value is a valid bson ObjectId, return false otherwise. +* @api public +*/ +ObjectID.isValid = function isValid(id) { + if(id == null) return false; + + if(id != null && 'number' != typeof id && (id.length != 12 && id.length != 24)) { + return false; + } else { + // Check specifically for hex correctness + if(typeof id == 'string' && id.length == 24) return checkForHexRegExp.test(id); + return true; + } +}; + +/** +* @ignore +*/ +Object.defineProperty(ObjectID.prototype, "generationTime", { + enumerable: true + , get: function () { + return Math.floor(BinaryParser.decodeInt(this.id.substring(0,4), 32, true, true)); + } + , set: function (value) { + var value = BinaryParser.encodeInt(value, 32, true, true); + this.id = value + this.id.substr(4); + // delete this.__id; + this.toHexString(); + } +}); + +/** + * Expose. + */ +exports.ObjectID = ObjectID; +exports.ObjectId = ObjectID; diff --git a/node_modules/mongodb/node_modules/bson/lib/bson/symbol.js b/node_modules/mongodb/node_modules/bson/lib/bson/symbol.js new file mode 100644 index 0000000..8e2838d --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/lib/bson/symbol.js @@ -0,0 +1,48 @@ +/** + * A class representation of the BSON Symbol type. + * + * @class Represents the BSON Symbol type. + * @param {String} value the string representing the symbol. + * @return {Symbol} + */ +function Symbol(value) { + if(!(this instanceof Symbol)) return new Symbol(value); + this._bsontype = 'Symbol'; + this.value = value; +} + +/** + * Access the wrapped string value. + * + * @return {String} returns the wrapped string. + * @api public + */ +Symbol.prototype.valueOf = function() { + return this.value; +}; + +/** + * @ignore + * @api private + */ +Symbol.prototype.toString = function() { + return this.value; +} + +/** + * @ignore + * @api private + */ +Symbol.prototype.inspect = function() { + return this.value; +} + +/** + * @ignore + * @api private + */ +Symbol.prototype.toJSON = function() { + return this.value; +} + +exports.Symbol = Symbol; \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/bson/lib/bson/timestamp.js b/node_modules/mongodb/node_modules/bson/lib/bson/timestamp.js new file mode 100644 index 0000000..c650d15 --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/lib/bson/timestamp.js @@ -0,0 +1,853 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Copyright 2009 Google Inc. All Rights Reserved + +/** + * Defines a Timestamp class for representing a 64-bit two's-complement + * integer value, which faithfully simulates the behavior of a Java "Timestamp". This + * implementation is derived from TimestampLib in GWT. + * + * Constructs a 64-bit two's-complement integer, given its low and high 32-bit + * values as *signed* integers. See the from* functions below for more + * convenient ways of constructing Timestamps. + * + * The internal representation of a Timestamp is the two given signed, 32-bit values. + * We use 32-bit pieces because these are the size of integers on which + * Javascript performs bit-operations. For operations like addition and + * multiplication, we split each number into 16-bit pieces, which can easily be + * multiplied within Javascript's floating-point representation without overflow + * or change in sign. + * + * In the algorithms below, we frequently reduce the negative case to the + * positive case by negating the input(s) and then post-processing the result. + * Note that we must ALWAYS check specially whether those values are MIN_VALUE + * (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as + * a positive number, it overflows back into a negative). Not handling this + * case would often result in infinite recursion. + * + * @class Represents the BSON Timestamp type. + * @param {Number} low the low (signed) 32 bits of the Timestamp. + * @param {Number} high the high (signed) 32 bits of the Timestamp. + */ +function Timestamp(low, high) { + if(!(this instanceof Timestamp)) return new Timestamp(low, high); + this._bsontype = 'Timestamp'; + /** + * @type {number} + * @api private + */ + this.low_ = low | 0; // force into 32 signed bits. + + /** + * @type {number} + * @api private + */ + this.high_ = high | 0; // force into 32 signed bits. +}; + +/** + * Return the int value. + * + * @return {Number} the value, assuming it is a 32-bit integer. + * @api public + */ +Timestamp.prototype.toInt = function() { + return this.low_; +}; + +/** + * Return the Number value. + * + * @return {Number} the closest floating-point representation to this value. + * @api public + */ +Timestamp.prototype.toNumber = function() { + return this.high_ * Timestamp.TWO_PWR_32_DBL_ + + this.getLowBitsUnsigned(); +}; + +/** + * Return the JSON value. + * + * @return {String} the JSON representation. + * @api public + */ +Timestamp.prototype.toJSON = function() { + return this.toString(); +} + +/** + * Return the String value. + * + * @param {Number} [opt_radix] the radix in which the text should be written. + * @return {String} the textual representation of this value. + * @api public + */ +Timestamp.prototype.toString = function(opt_radix) { + var radix = opt_radix || 10; + if (radix < 2 || 36 < radix) { + throw Error('radix out of range: ' + radix); + } + + if (this.isZero()) { + return '0'; + } + + if (this.isNegative()) { + if (this.equals(Timestamp.MIN_VALUE)) { + // We need to change the Timestamp value before it can be negated, so we remove + // the bottom-most digit in this base and then recurse to do the rest. + var radixTimestamp = Timestamp.fromNumber(radix); + var div = this.div(radixTimestamp); + var rem = div.multiply(radixTimestamp).subtract(this); + return div.toString(radix) + rem.toInt().toString(radix); + } else { + return '-' + this.negate().toString(radix); + } + } + + // Do several (6) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = Timestamp.fromNumber(Math.pow(radix, 6)); + + var rem = this; + var result = ''; + while (true) { + var remDiv = rem.div(radixToPower); + var intval = rem.subtract(remDiv.multiply(radixToPower)).toInt(); + var digits = intval.toString(radix); + + rem = remDiv; + if (rem.isZero()) { + return digits + result; + } else { + while (digits.length < 6) { + digits = '0' + digits; + } + result = '' + digits + result; + } + } +}; + +/** + * Return the high 32-bits value. + * + * @return {Number} the high 32-bits as a signed value. + * @api public + */ +Timestamp.prototype.getHighBits = function() { + return this.high_; +}; + +/** + * Return the low 32-bits value. + * + * @return {Number} the low 32-bits as a signed value. + * @api public + */ +Timestamp.prototype.getLowBits = function() { + return this.low_; +}; + +/** + * Return the low unsigned 32-bits value. + * + * @return {Number} the low 32-bits as an unsigned value. + * @api public + */ +Timestamp.prototype.getLowBitsUnsigned = function() { + return (this.low_ >= 0) ? + this.low_ : Timestamp.TWO_PWR_32_DBL_ + this.low_; +}; + +/** + * Returns the number of bits needed to represent the absolute value of this Timestamp. + * + * @return {Number} Returns the number of bits needed to represent the absolute value of this Timestamp. + * @api public + */ +Timestamp.prototype.getNumBitsAbs = function() { + if (this.isNegative()) { + if (this.equals(Timestamp.MIN_VALUE)) { + return 64; + } else { + return this.negate().getNumBitsAbs(); + } + } else { + var val = this.high_ != 0 ? this.high_ : this.low_; + for (var bit = 31; bit > 0; bit--) { + if ((val & (1 << bit)) != 0) { + break; + } + } + return this.high_ != 0 ? bit + 33 : bit + 1; + } +}; + +/** + * Return whether this value is zero. + * + * @return {Boolean} whether this value is zero. + * @api public + */ +Timestamp.prototype.isZero = function() { + return this.high_ == 0 && this.low_ == 0; +}; + +/** + * Return whether this value is negative. + * + * @return {Boolean} whether this value is negative. + * @api public + */ +Timestamp.prototype.isNegative = function() { + return this.high_ < 0; +}; + +/** + * Return whether this value is odd. + * + * @return {Boolean} whether this value is odd. + * @api public + */ +Timestamp.prototype.isOdd = function() { + return (this.low_ & 1) == 1; +}; + +/** + * Return whether this Timestamp equals the other + * + * @param {Timestamp} other Timestamp to compare against. + * @return {Boolean} whether this Timestamp equals the other + * @api public + */ +Timestamp.prototype.equals = function(other) { + return (this.high_ == other.high_) && (this.low_ == other.low_); +}; + +/** + * Return whether this Timestamp does not equal the other. + * + * @param {Timestamp} other Timestamp to compare against. + * @return {Boolean} whether this Timestamp does not equal the other. + * @api public + */ +Timestamp.prototype.notEquals = function(other) { + return (this.high_ != other.high_) || (this.low_ != other.low_); +}; + +/** + * Return whether this Timestamp is less than the other. + * + * @param {Timestamp} other Timestamp to compare against. + * @return {Boolean} whether this Timestamp is less than the other. + * @api public + */ +Timestamp.prototype.lessThan = function(other) { + return this.compare(other) < 0; +}; + +/** + * Return whether this Timestamp is less than or equal to the other. + * + * @param {Timestamp} other Timestamp to compare against. + * @return {Boolean} whether this Timestamp is less than or equal to the other. + * @api public + */ +Timestamp.prototype.lessThanOrEqual = function(other) { + return this.compare(other) <= 0; +}; + +/** + * Return whether this Timestamp is greater than the other. + * + * @param {Timestamp} other Timestamp to compare against. + * @return {Boolean} whether this Timestamp is greater than the other. + * @api public + */ +Timestamp.prototype.greaterThan = function(other) { + return this.compare(other) > 0; +}; + +/** + * Return whether this Timestamp is greater than or equal to the other. + * + * @param {Timestamp} other Timestamp to compare against. + * @return {Boolean} whether this Timestamp is greater than or equal to the other. + * @api public + */ +Timestamp.prototype.greaterThanOrEqual = function(other) { + return this.compare(other) >= 0; +}; + +/** + * Compares this Timestamp with the given one. + * + * @param {Timestamp} other Timestamp to compare against. + * @return {Boolean} 0 if they are the same, 1 if the this is greater, and -1 if the given one is greater. + * @api public + */ +Timestamp.prototype.compare = function(other) { + if (this.equals(other)) { + return 0; + } + + var thisNeg = this.isNegative(); + var otherNeg = other.isNegative(); + if (thisNeg && !otherNeg) { + return -1; + } + if (!thisNeg && otherNeg) { + return 1; + } + + // at this point, the signs are the same, so subtraction will not overflow + if (this.subtract(other).isNegative()) { + return -1; + } else { + return 1; + } +}; + +/** + * The negation of this value. + * + * @return {Timestamp} the negation of this value. + * @api public + */ +Timestamp.prototype.negate = function() { + if (this.equals(Timestamp.MIN_VALUE)) { + return Timestamp.MIN_VALUE; + } else { + return this.not().add(Timestamp.ONE); + } +}; + +/** + * Returns the sum of this and the given Timestamp. + * + * @param {Timestamp} other Timestamp to add to this one. + * @return {Timestamp} the sum of this and the given Timestamp. + * @api public + */ +Timestamp.prototype.add = function(other) { + // Divide each number into 4 chunks of 16 bits, and then sum the chunks. + + var a48 = this.high_ >>> 16; + var a32 = this.high_ & 0xFFFF; + var a16 = this.low_ >>> 16; + var a00 = this.low_ & 0xFFFF; + + var b48 = other.high_ >>> 16; + var b32 = other.high_ & 0xFFFF; + var b16 = other.low_ >>> 16; + var b00 = other.low_ & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 + b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 + b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 + b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 + b48; + c48 &= 0xFFFF; + return Timestamp.fromBits((c16 << 16) | c00, (c48 << 16) | c32); +}; + +/** + * Returns the difference of this and the given Timestamp. + * + * @param {Timestamp} other Timestamp to subtract from this. + * @return {Timestamp} the difference of this and the given Timestamp. + * @api public + */ +Timestamp.prototype.subtract = function(other) { + return this.add(other.negate()); +}; + +/** + * Returns the product of this and the given Timestamp. + * + * @param {Timestamp} other Timestamp to multiply with this. + * @return {Timestamp} the product of this and the other. + * @api public + */ +Timestamp.prototype.multiply = function(other) { + if (this.isZero()) { + return Timestamp.ZERO; + } else if (other.isZero()) { + return Timestamp.ZERO; + } + + if (this.equals(Timestamp.MIN_VALUE)) { + return other.isOdd() ? Timestamp.MIN_VALUE : Timestamp.ZERO; + } else if (other.equals(Timestamp.MIN_VALUE)) { + return this.isOdd() ? Timestamp.MIN_VALUE : Timestamp.ZERO; + } + + if (this.isNegative()) { + if (other.isNegative()) { + return this.negate().multiply(other.negate()); + } else { + return this.negate().multiply(other).negate(); + } + } else if (other.isNegative()) { + return this.multiply(other.negate()).negate(); + } + + // If both Timestamps are small, use float multiplication + if (this.lessThan(Timestamp.TWO_PWR_24_) && + other.lessThan(Timestamp.TWO_PWR_24_)) { + return Timestamp.fromNumber(this.toNumber() * other.toNumber()); + } + + // Divide each Timestamp into 4 chunks of 16 bits, and then add up 4x4 products. + // We can skip products that would overflow. + + var a48 = this.high_ >>> 16; + var a32 = this.high_ & 0xFFFF; + var a16 = this.low_ >>> 16; + var a00 = this.low_ & 0xFFFF; + + var b48 = other.high_ >>> 16; + var b32 = other.high_ & 0xFFFF; + var b16 = other.low_ >>> 16; + var b00 = other.low_ & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 * b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 * b00; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c16 += a00 * b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 * b00; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a16 * b16; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a00 * b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48; + c48 &= 0xFFFF; + return Timestamp.fromBits((c16 << 16) | c00, (c48 << 16) | c32); +}; + +/** + * Returns this Timestamp divided by the given one. + * + * @param {Timestamp} other Timestamp by which to divide. + * @return {Timestamp} this Timestamp divided by the given one. + * @api public + */ +Timestamp.prototype.div = function(other) { + if (other.isZero()) { + throw Error('division by zero'); + } else if (this.isZero()) { + return Timestamp.ZERO; + } + + if (this.equals(Timestamp.MIN_VALUE)) { + if (other.equals(Timestamp.ONE) || + other.equals(Timestamp.NEG_ONE)) { + return Timestamp.MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE + } else if (other.equals(Timestamp.MIN_VALUE)) { + return Timestamp.ONE; + } else { + // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|. + var halfThis = this.shiftRight(1); + var approx = halfThis.div(other).shiftLeft(1); + if (approx.equals(Timestamp.ZERO)) { + return other.isNegative() ? Timestamp.ONE : Timestamp.NEG_ONE; + } else { + var rem = this.subtract(other.multiply(approx)); + var result = approx.add(rem.div(other)); + return result; + } + } + } else if (other.equals(Timestamp.MIN_VALUE)) { + return Timestamp.ZERO; + } + + if (this.isNegative()) { + if (other.isNegative()) { + return this.negate().div(other.negate()); + } else { + return this.negate().div(other).negate(); + } + } else if (other.isNegative()) { + return this.div(other.negate()).negate(); + } + + // Repeat the following until the remainder is less than other: find a + // floating-point that approximates remainder / other *from below*, add this + // into the result, and subtract it from the remainder. It is critical that + // the approximate value is less than or equal to the real value so that the + // remainder never becomes negative. + var res = Timestamp.ZERO; + var rem = this; + while (rem.greaterThanOrEqual(other)) { + // Approximate the result of division. This may be a little greater or + // smaller than the actual value. + var approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber())); + + // We will tweak the approximate result by changing it in the 48-th digit or + // the smallest non-fractional digit, whichever is larger. + var log2 = Math.ceil(Math.log(approx) / Math.LN2); + var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48); + + // Decrease the approximation until it is smaller than the remainder. Note + // that if it is too large, the product overflows and is negative. + var approxRes = Timestamp.fromNumber(approx); + var approxRem = approxRes.multiply(other); + while (approxRem.isNegative() || approxRem.greaterThan(rem)) { + approx -= delta; + approxRes = Timestamp.fromNumber(approx); + approxRem = approxRes.multiply(other); + } + + // We know the answer can't be zero... and actually, zero would cause + // infinite recursion since we would make no progress. + if (approxRes.isZero()) { + approxRes = Timestamp.ONE; + } + + res = res.add(approxRes); + rem = rem.subtract(approxRem); + } + return res; +}; + +/** + * Returns this Timestamp modulo the given one. + * + * @param {Timestamp} other Timestamp by which to mod. + * @return {Timestamp} this Timestamp modulo the given one. + * @api public + */ +Timestamp.prototype.modulo = function(other) { + return this.subtract(this.div(other).multiply(other)); +}; + +/** + * The bitwise-NOT of this value. + * + * @return {Timestamp} the bitwise-NOT of this value. + * @api public + */ +Timestamp.prototype.not = function() { + return Timestamp.fromBits(~this.low_, ~this.high_); +}; + +/** + * Returns the bitwise-AND of this Timestamp and the given one. + * + * @param {Timestamp} other the Timestamp with which to AND. + * @return {Timestamp} the bitwise-AND of this and the other. + * @api public + */ +Timestamp.prototype.and = function(other) { + return Timestamp.fromBits(this.low_ & other.low_, this.high_ & other.high_); +}; + +/** + * Returns the bitwise-OR of this Timestamp and the given one. + * + * @param {Timestamp} other the Timestamp with which to OR. + * @return {Timestamp} the bitwise-OR of this and the other. + * @api public + */ +Timestamp.prototype.or = function(other) { + return Timestamp.fromBits(this.low_ | other.low_, this.high_ | other.high_); +}; + +/** + * Returns the bitwise-XOR of this Timestamp and the given one. + * + * @param {Timestamp} other the Timestamp with which to XOR. + * @return {Timestamp} the bitwise-XOR of this and the other. + * @api public + */ +Timestamp.prototype.xor = function(other) { + return Timestamp.fromBits(this.low_ ^ other.low_, this.high_ ^ other.high_); +}; + +/** + * Returns this Timestamp with bits shifted to the left by the given amount. + * + * @param {Number} numBits the number of bits by which to shift. + * @return {Timestamp} this shifted to the left by the given amount. + * @api public + */ +Timestamp.prototype.shiftLeft = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var low = this.low_; + if (numBits < 32) { + var high = this.high_; + return Timestamp.fromBits( + low << numBits, + (high << numBits) | (low >>> (32 - numBits))); + } else { + return Timestamp.fromBits(0, low << (numBits - 32)); + } + } +}; + +/** + * Returns this Timestamp with bits shifted to the right by the given amount. + * + * @param {Number} numBits the number of bits by which to shift. + * @return {Timestamp} this shifted to the right by the given amount. + * @api public + */ +Timestamp.prototype.shiftRight = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var high = this.high_; + if (numBits < 32) { + var low = this.low_; + return Timestamp.fromBits( + (low >>> numBits) | (high << (32 - numBits)), + high >> numBits); + } else { + return Timestamp.fromBits( + high >> (numBits - 32), + high >= 0 ? 0 : -1); + } + } +}; + +/** + * Returns this Timestamp with bits shifted to the right by the given amount, with the new top bits matching the current sign bit. + * + * @param {Number} numBits the number of bits by which to shift. + * @return {Timestamp} this shifted to the right by the given amount, with zeros placed into the new leading bits. + * @api public + */ +Timestamp.prototype.shiftRightUnsigned = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var high = this.high_; + if (numBits < 32) { + var low = this.low_; + return Timestamp.fromBits( + (low >>> numBits) | (high << (32 - numBits)), + high >>> numBits); + } else if (numBits == 32) { + return Timestamp.fromBits(high, 0); + } else { + return Timestamp.fromBits(high >>> (numBits - 32), 0); + } + } +}; + +/** + * Returns a Timestamp representing the given (32-bit) integer value. + * + * @param {Number} value the 32-bit integer in question. + * @return {Timestamp} the corresponding Timestamp value. + * @api public + */ +Timestamp.fromInt = function(value) { + if (-128 <= value && value < 128) { + var cachedObj = Timestamp.INT_CACHE_[value]; + if (cachedObj) { + return cachedObj; + } + } + + var obj = new Timestamp(value | 0, value < 0 ? -1 : 0); + if (-128 <= value && value < 128) { + Timestamp.INT_CACHE_[value] = obj; + } + return obj; +}; + +/** + * Returns a Timestamp representing the given value, provided that it is a finite number. Otherwise, zero is returned. + * + * @param {Number} value the number in question. + * @return {Timestamp} the corresponding Timestamp value. + * @api public + */ +Timestamp.fromNumber = function(value) { + if (isNaN(value) || !isFinite(value)) { + return Timestamp.ZERO; + } else if (value <= -Timestamp.TWO_PWR_63_DBL_) { + return Timestamp.MIN_VALUE; + } else if (value + 1 >= Timestamp.TWO_PWR_63_DBL_) { + return Timestamp.MAX_VALUE; + } else if (value < 0) { + return Timestamp.fromNumber(-value).negate(); + } else { + return new Timestamp( + (value % Timestamp.TWO_PWR_32_DBL_) | 0, + (value / Timestamp.TWO_PWR_32_DBL_) | 0); + } +}; + +/** + * Returns a Timestamp representing the 64-bit integer that comes by concatenating the given high and low bits. Each is assumed to use 32 bits. + * + * @param {Number} lowBits the low 32-bits. + * @param {Number} highBits the high 32-bits. + * @return {Timestamp} the corresponding Timestamp value. + * @api public + */ +Timestamp.fromBits = function(lowBits, highBits) { + return new Timestamp(lowBits, highBits); +}; + +/** + * Returns a Timestamp representation of the given string, written using the given radix. + * + * @param {String} str the textual representation of the Timestamp. + * @param {Number} opt_radix the radix in which the text is written. + * @return {Timestamp} the corresponding Timestamp value. + * @api public + */ +Timestamp.fromString = function(str, opt_radix) { + if (str.length == 0) { + throw Error('number format error: empty string'); + } + + var radix = opt_radix || 10; + if (radix < 2 || 36 < radix) { + throw Error('radix out of range: ' + radix); + } + + if (str.charAt(0) == '-') { + return Timestamp.fromString(str.substring(1), radix).negate(); + } else if (str.indexOf('-') >= 0) { + throw Error('number format error: interior "-" character: ' + str); + } + + // Do several (8) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = Timestamp.fromNumber(Math.pow(radix, 8)); + + var result = Timestamp.ZERO; + for (var i = 0; i < str.length; i += 8) { + var size = Math.min(8, str.length - i); + var value = parseInt(str.substring(i, i + size), radix); + if (size < 8) { + var power = Timestamp.fromNumber(Math.pow(radix, size)); + result = result.multiply(power).add(Timestamp.fromNumber(value)); + } else { + result = result.multiply(radixToPower); + result = result.add(Timestamp.fromNumber(value)); + } + } + return result; +}; + +// NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the +// from* methods on which they depend. + + +/** + * A cache of the Timestamp representations of small integer values. + * @type {Object} + * @api private + */ +Timestamp.INT_CACHE_ = {}; + +// NOTE: the compiler should inline these constant values below and then remove +// these variables, so there should be no runtime penalty for these. + +/** + * Number used repeated below in calculations. This must appear before the + * first call to any from* function below. + * @type {number} + * @api private + */ +Timestamp.TWO_PWR_16_DBL_ = 1 << 16; + +/** + * @type {number} + * @api private + */ +Timestamp.TWO_PWR_24_DBL_ = 1 << 24; + +/** + * @type {number} + * @api private + */ +Timestamp.TWO_PWR_32_DBL_ = Timestamp.TWO_PWR_16_DBL_ * Timestamp.TWO_PWR_16_DBL_; + +/** + * @type {number} + * @api private + */ +Timestamp.TWO_PWR_31_DBL_ = Timestamp.TWO_PWR_32_DBL_ / 2; + +/** + * @type {number} + * @api private + */ +Timestamp.TWO_PWR_48_DBL_ = Timestamp.TWO_PWR_32_DBL_ * Timestamp.TWO_PWR_16_DBL_; + +/** + * @type {number} + * @api private + */ +Timestamp.TWO_PWR_64_DBL_ = Timestamp.TWO_PWR_32_DBL_ * Timestamp.TWO_PWR_32_DBL_; + +/** + * @type {number} + * @api private + */ +Timestamp.TWO_PWR_63_DBL_ = Timestamp.TWO_PWR_64_DBL_ / 2; + +/** @type {Timestamp} */ +Timestamp.ZERO = Timestamp.fromInt(0); + +/** @type {Timestamp} */ +Timestamp.ONE = Timestamp.fromInt(1); + +/** @type {Timestamp} */ +Timestamp.NEG_ONE = Timestamp.fromInt(-1); + +/** @type {Timestamp} */ +Timestamp.MAX_VALUE = + Timestamp.fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0); + +/** @type {Timestamp} */ +Timestamp.MIN_VALUE = Timestamp.fromBits(0, 0x80000000 | 0); + +/** + * @type {Timestamp} + * @api private + */ +Timestamp.TWO_PWR_24_ = Timestamp.fromInt(1 << 24); + +/** + * Expose. + */ +exports.Timestamp = Timestamp; \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/bson/node_modules/nan/.dntrc b/node_modules/mongodb/node_modules/bson/node_modules/nan/.dntrc new file mode 100644 index 0000000..47971da --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/node_modules/nan/.dntrc @@ -0,0 +1,30 @@ +## DNT config file +## see https://github.com/rvagg/dnt + +NODE_VERSIONS="\ + master \ + v0.11.13 \ + v0.10.30 \ + v0.10.29 \ + v0.10.28 \ + v0.10.26 \ + v0.10.25 \ + v0.10.24 \ + v0.10.23 \ + v0.10.22 \ + v0.10.21 \ + v0.10.20 \ + v0.10.19 \ + v0.8.28 \ + v0.8.27 \ + v0.8.26 \ + v0.8.24 \ +" +OUTPUT_PREFIX="nan-" +TEST_CMD=" \ + cd /dnt/ && \ + npm install && \ + node_modules/.bin/node-gyp --nodedir /usr/src/node/ rebuild --directory test && \ + node_modules/.bin/tap --gc test/js/*-test.js \ +" + diff --git a/node_modules/mongodb/node_modules/bson/node_modules/nan/CHANGELOG.md b/node_modules/mongodb/node_modules/bson/node_modules/nan/CHANGELOG.md new file mode 100644 index 0000000..146cbb5 --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/node_modules/nan/CHANGELOG.md @@ -0,0 +1,200 @@ +# NAN ChangeLog + +### Version 1.3.0: current Node unstable: 0.11.13, Node stable: 0.10.30 + + +**1.3.0 Aug 2 2014** + + - Added NanNew(std::string) + - Added NanNew(std::string&) + - Added NanAsciiString helper class + - Added NanUtf8String helper class + - Added NanUcs2String helper class + - Deprecated NanRawString() + - Deprecated NanCString() + - Added NanGetIsolateData(v8::Isolate *isolate) + - Added NanMakeCallback(v8::Handle target, v8::Handle func, int argc, v8::Handle* argv) + - Added NanMakeCallback(v8::Handle target, v8::Handle symbol, int argc, v8::Handle* argv) + - Added NanMakeCallback(v8::Handle target, const char* method, int argc, v8::Handle* argv) + - Added NanSetTemplate(v8::Handle templ, v8::Handle name , v8::Handle value, v8::PropertyAttribute attributes) + - Added NanSetPrototypeTemplate(v8::Local templ, v8::Handle name, v8::Handle value, v8::PropertyAttribute attributes) + - Added NanSetInstanceTemplate(v8::Local templ, const char *name, v8::Handle value) + - Added NanSetInstanceTemplate(v8::Local templ, v8::Handle name, v8::Handle value, v8::PropertyAttribute attributes) + +**1.2.0 Jun 5 2014** + + - Add NanSetPrototypeTemplate + - Changed NAN_WEAK_CALLBACK internals, switched _NanWeakCallbackData to class, + introduced _NanWeakCallbackDispatcher + - Removed -Wno-unused-local-typedefs from test builds + - Made test builds Windows compatible ('Sleep()') + +**1.1.2 May 28 2014** + + - Release to fix more stuff-ups in 1.1.1 + +**1.1.1 May 28 2014** + + - Release to fix version mismatch in nan.h and lack of changelog entry for 1.1.0 + +**1.1.0 May 25 2014** + + - Remove nan_isolate, use v8::Isolate::GetCurrent() internally instead + - Additional explicit overloads for NanNew(): (char*,int), (uint8_t*[,int]), + (uint16_t*[,int), double, int, unsigned int, bool, v8::String::ExternalStringResource*, + v8::String::ExternalAsciiStringResource* + - Deprecate NanSymbol() + - Added SetErrorMessage() and ErrorMessage() to NanAsyncWorker + +**1.0.0 May 4 2014** + + - Heavy API changes for V8 3.25 / Node 0.11.13 + - Use cpplint.py + - Removed NanInitPersistent + - Removed NanPersistentToLocal + - Removed NanFromV8String + - Removed NanMakeWeak + - Removed NanNewLocal + - Removed NAN_WEAK_CALLBACK_OBJECT + - Removed NAN_WEAK_CALLBACK_DATA + - Introduce NanNew, replaces NanNewLocal, NanPersistentToLocal, adds many overloaded typed versions + - Introduce NanUndefined, NanNull, NanTrue and NanFalse + - Introduce NanEscapableScope and NanEscapeScope + - Introduce NanMakeWeakPersistent (requires a special callback to work on both old and new node) + - Introduce NanMakeCallback for node::MakeCallback + - Introduce NanSetTemplate + - Introduce NanGetCurrentContext + - Introduce NanCompileScript and NanRunScript + - Introduce NanAdjustExternalMemory + - Introduce NanAddGCEpilogueCallback, NanAddGCPrologueCallback, NanRemoveGCEpilogueCallback, NanRemoveGCPrologueCallback + - Introduce NanGetHeapStatistics + - Rename NanAsyncWorker#SavePersistent() to SaveToPersistent() + +**0.8.0 Jan 9 2014** + + - NanDispose -> NanDisposePersistent, deprecate NanDispose + - Extract _NAN_*_RETURN_TYPE, pull up NAN_*() + +**0.7.1 Jan 9 2014** + + - Fixes to work against debug builds of Node + - Safer NanPersistentToLocal (avoid reinterpret_cast) + - Speed up common NanRawString case by only extracting flattened string when necessary + +**0.7.0 Dec 17 2013** + + - New no-arg form of NanCallback() constructor. + - NanCallback#Call takes Handle rather than Local + - Removed deprecated NanCallback#Run method, use NanCallback#Call instead + - Split off _NAN_*_ARGS_TYPE from _NAN_*_ARGS + - Restore (unofficial) Node 0.6 compatibility at NanCallback#Call() + - Introduce NanRawString() for char* (or appropriate void*) from v8::String + (replacement for NanFromV8String) + - Introduce NanCString() for null-terminated char* from v8::String + +**0.6.0 Nov 21 2013** + + - Introduce NanNewLocal(v8::Handle value) for use in place of + v8::Local::New(...) since v8 started requiring isolate in Node 0.11.9 + +**0.5.2 Nov 16 2013** + + - Convert SavePersistent and GetFromPersistent in NanAsyncWorker from protected and public + +**0.5.1 Nov 12 2013** + + - Use node::MakeCallback() instead of direct v8::Function::Call() + +**0.5.0 Nov 11 2013** + + - Added @TooTallNate as collaborator + - New, much simpler, "include_dirs" for binding.gyp + - Added full range of NAN_INDEX_* macros to match NAN_PROPERTY_* macros + +**0.4.4 Nov 2 2013** + + - Isolate argument from v8::Persistent::MakeWeak removed for 0.11.8+ + +**0.4.3 Nov 2 2013** + + - Include node_object_wrap.h, removed from node.h for Node 0.11.8. + +**0.4.2 Nov 2 2013** + + - Handle deprecation of v8::Persistent::Dispose(v8::Isolate* isolate)) for + Node 0.11.8 release. + +**0.4.1 Sep 16 2013** + + - Added explicit `#include ` as it was removed from node.h for v0.11.8 + +**0.4.0 Sep 2 2013** + + - Added NAN_INLINE and NAN_DEPRECATED and made use of them + - Added NanError, NanTypeError and NanRangeError + - Cleaned up code + +**0.3.2 Aug 30 2013** + + - Fix missing scope declaration in GetFromPersistent() and SaveToPersistent + in NanAsyncWorker + +**0.3.1 Aug 20 2013** + + - fix "not all control paths return a value" compile warning on some platforms + +**0.3.0 Aug 19 2013** + + - Made NAN work with NPM + - Lots of fixes to NanFromV8String, pulling in features from new Node core + - Changed node::encoding to Nan::Encoding in NanFromV8String to unify the API + - Added optional error number argument for NanThrowError() + - Added NanInitPersistent() + - Added NanReturnNull() and NanReturnEmptyString() + - Added NanLocker and NanUnlocker + - Added missing scopes + - Made sure to clear disposed Persistent handles + - Changed NanAsyncWorker to allocate error messages on the heap + - Changed NanThrowError(Local) to NanThrowError(Handle) + - Fixed leak in NanAsyncWorker when errmsg is used + +**0.2.2 Aug 5 2013** + + - Fixed usage of undefined variable with node::BASE64 in NanFromV8String() + +**0.2.1 Aug 5 2013** + + - Fixed 0.8 breakage, node::BUFFER encoding type not available in 0.8 for + NanFromV8String() + +**0.2.0 Aug 5 2013** + + - Added NAN_PROPERTY_GETTER, NAN_PROPERTY_SETTER, NAN_PROPERTY_ENUMERATOR, + NAN_PROPERTY_DELETER, NAN_PROPERTY_QUERY + - Extracted _NAN_METHOD_ARGS, _NAN_GETTER_ARGS, _NAN_SETTER_ARGS, + _NAN_PROPERTY_GETTER_ARGS, _NAN_PROPERTY_SETTER_ARGS, + _NAN_PROPERTY_ENUMERATOR_ARGS, _NAN_PROPERTY_DELETER_ARGS, + _NAN_PROPERTY_QUERY_ARGS + - Added NanGetInternalFieldPointer, NanSetInternalFieldPointer + - Added NAN_WEAK_CALLBACK, NAN_WEAK_CALLBACK_OBJECT, + NAN_WEAK_CALLBACK_DATA, NanMakeWeak + - Renamed THROW_ERROR to _NAN_THROW_ERROR + - Added NanNewBufferHandle(char*, size_t, node::smalloc::FreeCallback, void*) + - Added NanBufferUse(char*, uint32_t) + - Added NanNewContextHandle(v8::ExtensionConfiguration*, + v8::Handle, v8::Handle) + - Fixed broken NanCallback#GetFunction() + - Added optional encoding and size arguments to NanFromV8String() + - Added NanGetPointerSafe() and NanSetPointerSafe() + - Added initial test suite (to be expanded) + - Allow NanUInt32OptionValue to convert any Number object + +**0.1.0 Jul 21 2013** + + - Added `NAN_GETTER`, `NAN_SETTER` + - Added `NanThrowError` with single Local argument + - Added `NanNewBufferHandle` with single uint32_t argument + - Added `NanHasInstance(Persistent&, Handle)` + - Added `Local NanCallback#GetFunction()` + - Added `NanCallback#Call(int, Local[])` + - Deprecated `NanCallback#Run(int, Local[])` in favour of Call diff --git a/node_modules/mongodb/node_modules/bson/node_modules/nan/LICENSE b/node_modules/mongodb/node_modules/bson/node_modules/nan/LICENSE new file mode 100644 index 0000000..d502e18 --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/node_modules/nan/LICENSE @@ -0,0 +1,46 @@ +Copyright 2013, NAN contributors: + - Rod Vagg + - Benjamin Byholm + - Trevor Norris + - Nathan Rajlich + - Brett Lawson + - Ben Noordhuis +(the "Original Author") +All rights reserved. + +MIT +no-false-attribs 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. + +Distributions of all or part of the Software intended to be used +by the recipients as they would use the unmodified Software, +containing modifications that substantially alter, remove, or +disable functionality of the Software, outside of the documented +configuration mechanisms provided by the Software, shall be +modified such that the Original Author's bug reporting email +addresses and urls are either replaced with the contact information +of the parties responsible for the changes, or removed entirely. + +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. + + +Except where noted, this license applies to any and all software +programs and associated documentation files created by the +Original Author, when distributed with the Software. diff --git a/node_modules/mongodb/node_modules/bson/node_modules/nan/README.md b/node_modules/mongodb/node_modules/bson/node_modules/nan/README.md new file mode 100644 index 0000000..2904a38 --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/node_modules/nan/README.md @@ -0,0 +1,1054 @@ +Native Abstractions for Node.js +=============================== + +**A header file filled with macro and utility goodness for making add-on development for Node.js easier across versions 0.8, 0.10 and 0.11, and eventually 0.12.** + +***Current version: 1.3.0*** + +*(See [nan.h](https://github.com/rvagg/nan/blob/master/CHANGELOG.md) for complete ChangeLog)* + +[![NPM](https://nodei.co/npm/nan.png?downloads=true)](https://nodei.co/npm/nan/) [![NPM](https://nodei.co/npm-dl/nan.png?months=6)](https://nodei.co/npm/nan/) + +[![Build Status](https://secure.travis-ci.org/rvagg/nan.png)](http://travis-ci.org/rvagg/nan) +[![Build status](https://ci.appveyor.com/api/projects/status/kh73pbm9dsju7fgh)](https://ci.appveyor.com/project/RodVagg/nan) + +Thanks to the crazy changes in V8 (and some in Node core), keeping native addons compiling happily across versions, particularly 0.10 to 0.11/0.12, is a minor nightmare. The goal of this project is to store all logic necessary to develop native Node.js addons without having to inspect `NODE_MODULE_VERSION` and get yourself into a macro-tangle. + +This project also contains some helper utilities that make addon development a bit more pleasant. + + * **[News & Updates](#news)** + * **[Usage](#usage)** + * **[Example](#example)** + * **[API](#api)** + + +## News & Updates + +### Aug-2014: 1.3.0 release + +* `NanCString()` and `NanRawString()` have been deprecated in favour of new NanAsciiString, NanUtf8String and NanUcs2String. These classes manage the underlying memory for you in a safer way than just handing off an allocated array. You should now `*NanAsciiString(handle)` to access the raw `char` data, you can also allocate on the heap if you need to keep a reference. +* Two more NanMakeCallback overloads have been added to for parity with Node core. +* You can now `NanNew(std::string)` (use `NanNew(std::string&)` to pass by reference) +* NanSetTemplate, NanSetPrototypeTemplate and NanSetInstanceTemplate have been added. + +### May-2014: 1.1.0 release + +* We've deprecated `NanSymbol()`, you should just use `NanNew()` now. +* `NanNull()`, `NanUndefined()`, `NanTrue()`, `NanFalse()` all return `Local`s now. +* `nan_isolate` is gone, it was intended to be internal-only but if you were using it then you should switch to `v8::Isolate::GetCurrent()`. +* `NanNew()` has received some additional overload-love so you should be able to give it many kinds of values without specifying the ``. +* Lots of small fixes and additions to expand the V8 API coverage, *use the source, Luke*. + + +### May-2014: Major changes for V8 3.25 / Node 0.11.13 + +Node 0.11.11 and 0.11.12 were both broken releases for native add-ons, you simply can't properly compile against either of them for different reasons. But we now have a 0.11.13 release that jumps a couple of versions of V8 ahead and includes some more, major (traumatic) API changes. + +Because we are now nearing Node 0.12 and estimate that the version of V8 we are using in Node 0.11.13 will be close to the API we get for 0.12, we have taken the opportunity to not only *fix* NAN for 0.11.13 but make some major changes to improve the NAN API. + +We have **removed support for Node 0.11 versions prior to 0.11.13**. As usual, our tests are run against (and pass) the last 5 versions of Node 0.8 and Node 0.10. We also include Node 0.11.13 obviously. + +The major change is something that [Benjamin Byholm](kkoopa) has put many hours in to. We now have a fantastic new `NanNew(args)` interface for creating new `Local`s, this replaces `NanNewLocal()` and much more. If you look in [./nan.h](nan.h) you'll see a large number of overloaded versions of this method. In general you should be able to `NanNew(arguments)` for any type you want to make a `Local` from. This includes `Persistent` types, so we now have a `Local NanNew(const Persistent arg)` to replace `NanPersistentToLocal()`. + +We also now have `NanUndefined()`, `NanNull()`, `NanTrue()` and `NanFalse()`. Mainly because of the new requirement for an `Isolate` argument for each of the native V8 versions of this. + +V8 has now introduced an `EscapableHandleScope` from which you `scope.Escape(Local value)` to *return* a value from a one scope to another. This replaces the standard `HandleScope` and `scope.Close(Local value)`, although `HandleScope` still exists for when you don't need to return a handle to the caller. For NAN we are exposing it as `NanEscapableScope()` and `NanEscapeScope()`, while `NanScope()` is still how you create a new scope that doesn't need to return handles. For older versions of Node/V8, it'll still map to the older `HandleScope` functionality. + +`NanFromV8String()` was deprecated and has now been removed. You should use `NanCString()` or `NanRawString()` instead. + +Because `node::MakeCallback()` now takes an `Isolate`, and because it doesn't exist in older versions of Node, we've introduced `NanMakeCallback()`. You should *always* use this when calling a JavaScript function from C++. + +There's lots more, check out the Changelog in nan.h or look through [#86](https://github.com/rvagg/nan/pull/86) for all the gory details. + +### Dec-2013: NanCString and NanRawString + +Two new functions have been introduced to replace the functionality that's been provided by `NanFromV8String` until now. NanCString has sensible defaults so it's super easy to fetch a null-terminated c-style string out of a `v8::String`. `NanFromV8String` is still around and has defaults that allow you to pass a single handle to fetch a `char*` while `NanRawString` requires a little more attention to arguments. + +### Nov-2013: Node 0.11.9+ breaking V8 change + +The version of V8 that's shipping with Node 0.11.9+ has changed the signature for new `Local`s to: `v8::Local::New(isolate, value)`, i.e. introducing the `isolate` argument and therefore breaking all new `Local` declarations for previous versions. NAN 0.6+ now includes a `NanNewLocal(value)` that can be used in place to work around this incompatibility and maintain compatibility with 0.8->0.11.9+ (minus a few early 0.11 releases). + +For example, if you wanted to return a `null` on a callback you will have to change the argument from `v8::Local::New(v8::Null())` to `NanNewLocal(v8::Null())`. + +### Nov-2013: Change to binding.gyp `"include_dirs"` for NAN + +Inclusion of NAN in a project's binding.gyp is now greatly simplified. You can now just use `" +## Usage + +Simply add **NAN** as a dependency in the *package.json* of your Node addon: + +``` bash +$ npm install --save nan +``` + +Pull in the path to **NAN** in your *binding.gyp* so that you can use `#include ` in your *.cpp* files: + +``` python +"include_dirs" : [ + "` when compiling your addon. + + +## Example + +See **[LevelDOWN](https://github.com/rvagg/node-leveldown/pull/48)** for a full example of **NAN** in use. + +For a simpler example, see the **[async pi estimation example](https://github.com/rvagg/nan/tree/master/examples/async_pi_estimate)** in the examples directory for full code and an explanation of what this Monte Carlo Pi estimation example does. Below are just some parts of the full example that illustrate the use of **NAN**. + +Compare to the current 0.10 version of this example, found in the [node-addon-examples](https://github.com/rvagg/node-addon-examples/tree/master/9_async_work) repository and also a 0.11 version of the same found [here](https://github.com/kkoopa/node-addon-examples/tree/5c01f58fc993377a567812597e54a83af69686d7/9_async_work). + +Note that there is no embedded version sniffing going on here and also the async work is made much simpler, see below for details on the `NanAsyncWorker` class. + +```c++ +// addon.cc +#include +#include +// ... + +using v8::FunctionTemplate; +using v8::Handle; +using v8::Object; +using v8::String; + +void InitAll(Handle exports) { + exports->Set(NanNew("calculateSync"), + NanNew(CalculateSync)->GetFunction()); + + exports->Set(NanNew("calculateAsync"), + NanNew(CalculateAsync)->GetFunction()); +} + +NODE_MODULE(addon, InitAll) +``` + +```c++ +// sync.h +#include +#include + +NAN_METHOD(CalculateSync); +``` + +```c++ +// sync.cc +#include +#include +#include "./sync.h" +// ... + +using v8::Number; + +// Simple synchronous access to the `Estimate()` function +NAN_METHOD(CalculateSync) { + NanScope(); + + // expect a number as the first argument + int points = args[0]->Uint32Value(); + double est = Estimate(points); + + NanReturnValue(NanNew(est)); +} +``` + +```c++ +// async.h +#include +#include + +NAN_METHOD(CalculateAsync); +``` + +```c++ +// async.cc +#include +#include +#include "./async.h" + +// ... + +using v8::Function; +using v8::Local; +using v8::Null; +using v8::Number; +using v8::Value; + +class PiWorker : public NanAsyncWorker { + public: + PiWorker(NanCallback *callback, int points) + : NanAsyncWorker(callback), points(points) {} + ~PiWorker() {} + + // Executed inside the worker-thread. + // It is not safe to access V8, or V8 data structures + // here, so everything we need for input and output + // should go on `this`. + void Execute () { + estimate = Estimate(points); + } + + // Executed when the async work is complete + // this function will be run inside the main event loop + // so it is safe to use V8 again + void HandleOKCallback () { + NanScope(); + + Local argv[] = { + NanNull() + , NanNew(estimate) + }; + + callback->Call(2, argv); + }; + + private: + int points; + double estimate; +}; + +// Asynchronous access to the `Estimate()` function +NAN_METHOD(CalculateAsync) { + NanScope(); + + int points = args[0]->Uint32Value(); + NanCallback *callback = new NanCallback(args[1].As()); + + NanAsyncQueueWorker(new PiWorker(callback, points)); + NanReturnUndefined(); +} +``` + + +## API + + * NAN_METHOD + * NAN_GETTER + * NAN_SETTER + * NAN_PROPERTY_GETTER + * NAN_PROPERTY_SETTER + * NAN_PROPERTY_ENUMERATOR + * NAN_PROPERTY_DELETER + * NAN_PROPERTY_QUERY + * NAN_INDEX_GETTER + * NAN_INDEX_SETTER + * NAN_INDEX_ENUMERATOR + * NAN_INDEX_DELETER + * NAN_INDEX_QUERY + * NAN_WEAK_CALLBACK + * NAN_DEPRECATED + * NAN_INLINE + * NanNew + * NanUndefined + * NanNull + * NanTrue + * NanFalse + * NanReturnValue + * NanReturnUndefined + * NanReturnNull + * NanReturnEmptyString + * NanScope + * NanEscapableScope + * NanEscapeScope + * NanLocker + * NanUnlocker + * NanGetInternalFieldPointer + * NanSetInternalFieldPointer + * NanObjectWrapHandle + * NanSymbol + * NanGetPointerSafe + * NanSetPointerSafe + * NanRawString + * NanCString + * NanAsciiString + * NanUtf8String + * NanUcs2String + * NanBooleanOptionValue + * NanUInt32OptionValue + * NanError, NanTypeError, NanRangeError + * NanThrowError, NanThrowTypeError, NanThrowRangeError, NanThrowError(Handle), NanThrowError(Handle, int) + * NanNewBufferHandle(char *, size_t, FreeCallback, void *), NanNewBufferHandle(char *, uint32_t), NanNewBufferHandle(uint32_t) + * NanBufferUse(char *, uint32_t) + * NanNewContextHandle + * NanGetCurrentContext + * NanHasInstance + * NanDisposePersistent + * NanAssignPersistent + * NanMakeWeakPersistent + * NanSetTemplate + * NanSetPrototypeTemplate + * NanSetInstanceTemplate + * NanMakeCallback + * NanCompileScript + * NanRunScript + * NanAdjustExternalMemory + * NanAddGCEpilogueCallback + * NanAddGCPrologueCallback + * NanRemoveGCEpilogueCallback + * NanRemoveGCPrologueCallback + * NanGetHeapStatistics + * NanCallback + * NanAsyncWorker + * NanAsyncQueueWorker + + +### NAN_METHOD(methodname) + +Use `NAN_METHOD` to define your V8 accessible methods: + +```c++ +// .h: +class Foo : public node::ObjectWrap { + ... + + static NAN_METHOD(Bar); + static NAN_METHOD(Baz); +} + + +// .cc: +NAN_METHOD(Foo::Bar) { + ... +} + +NAN_METHOD(Foo::Baz) { + ... +} +``` + +The reason for this macro is because of the method signature change in 0.11: + +```c++ +// 0.10 and below: +Handle name(const Arguments& args) + +// 0.11 and above +void name(const FunctionCallbackInfo& args) +``` + +The introduction of `FunctionCallbackInfo` brings additional complications: + + +### NAN_GETTER(methodname) + +Use `NAN_GETTER` to declare your V8 accessible getters. You get a `Local` `property` and an appropriately typed `args` object that can act like the `args` argument to a `NAN_METHOD` call. + +You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_GETTER`. + + +### NAN_SETTER(methodname) + +Use `NAN_SETTER` to declare your V8 accessible setters. Same as `NAN_GETTER` but you also get a `Local` `value` object to work with. + + +### NAN_PROPERTY_GETTER(cbname) +Use `NAN_PROPERTY_GETTER` to declare your V8 accessible property getters. You get a `Local` `property` and an appropriately typed `args` object that can act similar to the `args` argument to a `NAN_METHOD` call. + +You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_PROPERTY_GETTER`. + + +### NAN_PROPERTY_SETTER(cbname) +Use `NAN_PROPERTY_SETTER` to declare your V8 accessible property setters. Same as `NAN_PROPERTY_GETTER` but you also get a `Local` `value` object to work with. + + +### NAN_PROPERTY_ENUMERATOR(cbname) +Use `NAN_PROPERTY_ENUMERATOR` to declare your V8 accessible property enumerators. You get an appropriately typed `args` object like the `args` argument to a `NAN_PROPERTY_GETTER` call. + +You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_PROPERTY_ENUMERATOR`. + + +### NAN_PROPERTY_DELETER(cbname) +Use `NAN_PROPERTY_DELETER` to declare your V8 accessible property deleters. Same as `NAN_PROPERTY_GETTER`. + +You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_PROPERTY_DELETER`. + + +### NAN_PROPERTY_QUERY(cbname) +Use `NAN_PROPERTY_QUERY` to declare your V8 accessible property queries. Same as `NAN_PROPERTY_GETTER`. + +You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_PROPERTY_QUERY`. + + +### NAN_INDEX_GETTER(cbname) +Use `NAN_INDEX_GETTER` to declare your V8 accessible index getters. You get a `uint32_t` `index` and an appropriately typed `args` object that can act similar to the `args` argument to a `NAN_METHOD` call. + +You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_INDEX_GETTER`. + + +### NAN_INDEX_SETTER(cbname) +Use `NAN_INDEX_SETTER` to declare your V8 accessible index setters. Same as `NAN_INDEX_GETTER` but you also get a `Local` `value` object to work with. + + +### NAN_INDEX_ENUMERATOR(cbname) +Use `NAN_INDEX_ENUMERATOR` to declare your V8 accessible index enumerators. You get an appropriately typed `args` object like the `args` argument to a `NAN_INDEX_GETTER` call. + +You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_INDEX_ENUMERATOR`. + + +### NAN_INDEX_DELETER(cbname) +Use `NAN_INDEX_DELETER` to declare your V8 accessible index deleters. Same as `NAN_INDEX_GETTER`. + +You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_INDEX_DELETER`. + + +### NAN_INDEX_QUERY(cbname) +Use `NAN_INDEX_QUERY` to declare your V8 accessible index queries. Same as `NAN_INDEX_GETTER`. + +You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_INDEX_QUERY`. + + +### NAN_WEAK_CALLBACK(cbname) + +Use `NAN_WEAK_CALLBACK` to define your V8 WeakReference callbacks. There is an argument object `const _NanWeakCallbackData &data` allowing access to the weak object and the supplied parameter through its `GetValue` and `GetParameter` methods. You can even access the weak callback info object through the `GetCallbackInfo()`method, but you probably should not. `Revive()` keeps the weak object alive until the next GC round. + +```c++ +NAN_WEAK_CALLBACK(weakCallback) { + int *parameter = data.GetParameter(); + NanMakeCallback(NanGetCurrentContext()->Global(), data.GetValue(), 0, NULL); + if ((*parameter)++ == 0) { + data.Revive(); + } else { + delete parameter; + } +} +``` + + +### NAN_DEPRECATED +Declares a function as deprecated. + +```c++ +static NAN_DEPRECATED NAN_METHOD(foo) { + ... +} +``` + + +### NAN_INLINE +Inlines a function. + +```c++ +NAN_INLINE int foo(int bar) { + ... +} +``` + + +### Local<T> NanNew<T>( ... ) + +Use `NanNew` to construct almost all v8 objects and make new local handles. + +Note: Using NanNew with an std::string is possible, however, you should ensure +to use the overload version (`NanNew(stdString)`) rather than the template +version (`NanNew(stdString)`) as there is an unnecessary +performance penalty to using the template version because of the inability for +compilers to appropriately deduce to reference types on template specialization. + +```c++ +Local s = NanNew("value"); + +... + +Persistent o; + +... + +Local lo = NanNew(o); + +``` + + +### Local<Primitive> NanUndefined() + +Use instead of `Undefined()` + + +### Local<Primitive> NanNull() + +Use instead of `Null()` + + +### Local<Boolean> NanTrue() + +Use instead of `True()` + + +### Local<Boolean> NanFalse() + +Use instead of `False()` + + +### NanReturnValue(Handle<Value>) + +Use `NanReturnValue` when you want to return a value from your V8 accessible method: + +```c++ +NAN_METHOD(Foo::Bar) { + ... + + NanReturnValue(NanNew("FooBar!")); +} +``` + +No `return` statement required. + + +### NanReturnUndefined() + +Use `NanReturnUndefined` when you don't want to return anything from your V8 accessible method: + +```c++ +NAN_METHOD(Foo::Baz) { + ... + + NanReturnUndefined(); +} +``` + + +### NanReturnNull() + +Use `NanReturnNull` when you want to return `Null` from your V8 accessible method: + +```c++ +NAN_METHOD(Foo::Baz) { + ... + + NanReturnNull(); +} +``` + + +### NanReturnEmptyString() + +Use `NanReturnEmptyString` when you want to return an empty `String` from your V8 accessible method: + +```c++ +NAN_METHOD(Foo::Baz) { + ... + + NanReturnEmptyString(); +} +``` + + +### NanScope() + +The introduction of `isolate` references for many V8 calls in Node 0.11 makes `NanScope()` necessary, use it in place of `HandleScope scope` when you do not wish to return handles (`Handle` or `Local`) to the surrounding scope (or in functions directly exposed to V8, as they do not return values in the normal sense): + +```c++ +NAN_METHOD(Foo::Bar) { + NanScope(); + + NanReturnValue(NanNew("FooBar!")); +} +``` + +This method is not directly exposed to V8, nor does it return a handle, so it uses an unescapable scope: + +```c++ +bool Foo::Bar() { + NanScope(); + + Local val = NanFalse(); + ... + return val->Value(); +} +``` + + +### NanEscapableScope() + +The separation of handle scopes into escapable and inescapable scopes makes `NanEscapableScope()` necessary, use it in place of `HandleScope scope` when you later wish to return a handle (`Handle` or `Local`) from the scope, this is for internal functions not directly exposed to V8: + +```c++ +Handle Foo::Bar() { + NanEscapableScope(); + + return NanEscapeScope(NanNew("FooBar!")); +} +``` + + +### Local<T> NanEscapeScope(Handle<T> value); +Use together with `NanEscapableScope` to escape the scope. Corresponds to `HandleScope::Close` or `EscapableHandleScope::Escape`. + + +### NanLocker() + +The introduction of `isolate` references for many V8 calls in Node 0.11 makes `NanLocker()` necessary, use it in place of `Locker locker`: + +```c++ +NAN_METHOD(Foo::Bar) { + NanLocker(); + ... + NanUnlocker(); +} +``` + + +### NanUnlocker() + +The introduction of `isolate` references for many V8 calls in Node 0.11 makes `NanUnlocker()` necessary, use it in place of `Unlocker unlocker`: + +```c++ +NAN_METHOD(Foo::Bar) { + NanLocker(); + ... + NanUnlocker(); +} +``` + + +### void * NanGetInternalFieldPointer(Handle<Object>, int) + +Gets a pointer to the internal field with at `index` from a V8 `Object` handle. + +```c++ +Local obj; +... +NanGetInternalFieldPointer(obj, 0); +``` + +### void NanSetInternalFieldPointer(Handle<Object>, int, void *) + +Sets the value of the internal field at `index` on a V8 `Object` handle. + +```c++ +static Persistent dataWrapperCtor; +... +Local wrapper = NanNew(dataWrapperCtor)->NewInstance(); +NanSetInternalFieldPointer(wrapper, 0, this); +``` + + +### Local<Object> NanObjectWrapHandle(Object) + +When you want to fetch the V8 object handle from a native object you've wrapped with Node's `ObjectWrap`, you should use `NanObjectWrapHandle`: + +```c++ +NanObjectWrapHandle(iterator)->Get(NanNew("end")) +``` + + +### Local<String> NanSymbol(const char *) + +Deprecated. Use `NanNew` instead. +Use to create string symbol objects (i.e. `v8::String::NewSymbol(x)`), for getting and setting object properties, or names of objects. + +```c++ +bool foo = false; +if (obj->Has(NanNew("foo"))) + foo = optionsObj->Get(NanNew("foo"))->BooleanValue() +``` + + +### Type NanGetPointerSafe(Type *[, Type]) + +A helper for getting values from optional pointers. If the pointer is `NULL`, the function returns the optional default value, which defaults to `0`. Otherwise, the function returns the value the pointer points to. + +```c++ +char *plugh(uint32_t *optional) { + char res[] = "xyzzy"; + uint32_t param = NanGetPointerSafe(optional, 0x1337); + switch (param) { + ... + } + NanSetPointerSafe(optional, 0xDEADBEEF); +} +``` + + +### bool NanSetPointerSafe(Type *, Type) + +A helper for setting optional argument pointers. If the pointer is `NULL`, the function simply returns `false`. Otherwise, the value is assigned to the variable the pointer points to. + +```c++ +const char *plugh(size_t *outputsize) { + char res[] = "xyzzy"; + if !(NanSetPointerSafe(outputsize, strlen(res) + 1)) { + ... + } + + ... +} +``` + + +### void* NanRawString(Handle<Value>, enum Nan::Encoding, size_t *, void *, size_t, int) + +Deprecated. Use something else. + +When you want to convert a V8 `String` to a `char*` buffer, use `NanRawString`. You have to supply an encoding as well as a pointer to a variable that will be assigned the number of bytes in the returned string. It is also possible to supply a buffer and its length to the function in order not to have a new buffer allocated. The final argument allows setting `String::WriteOptions`. +Just remember that you'll end up with an object that you'll need to `delete[]` at some point unless you supply your own buffer: + +```c++ +size_t count; +void* decoded = NanRawString(args[1], Nan::BASE64, &count, NULL, 0, String::HINT_MANY_WRITES_EXPECTED); +... +delete[] reinterpret_cast(decoded); +``` + + +### char* NanCString(Handle<Value>, size_t *[, char *, size_t, int]) + +Deprecated. Use `NanUtf8String` instead. + +When you want to convert a V8 `String` to a null-terminated C `char*` use `NanCString`. The resulting `char*` will be UTF-8-encoded, and you need to supply a pointer to a variable that will be assigned the number of bytes in the returned string. It is also possible to supply a buffer and its length to the function in order not to have a new buffer allocated. The final argument allows optionally setting `String::WriteOptions`, which default to `v8::String::NO_OPTIONS`. +Just remember that you'll end up with an object that you'll need to `delete[]` at some point unless you supply your own buffer: + +```c++ +size_t count; +char* name = NanCString(args[0], &count); +... +delete[] name; +``` + + +### NanAsciiString + +Convert a `String` to zero-terminated, Ascii-encoded `char *`. + +```c++ +NAN_METHOD(foo) { + NanScope(); + NanReturnValue(NanNew(*NanAsciiString(arg[0]))); +} +``` + + +### NanUtf8String + +Convert a `String` to zero-terminated, Utf8-encoded `char *`. + +```c++ +NAN_METHOD(foo) { + NanScope(); + NanReturnValue(NanNew(*NanUtf8String(arg[0]))); +} +``` + + +### NanUcs2String + +Convert a `String` to zero-terminated, Ucs2-encoded `uint16_t *`. + +```c++ +NAN_METHOD(foo) { + NanScope(); + NanReturnValue(NanNew(*NanUcs2String(arg[0]))); +} +``` + + +### bool NanBooleanOptionValue(Handle<Value>, Handle<String>[, bool]) + +When you have an "options" object that you need to fetch properties from, boolean options can be fetched with this pair. They check first if the object exists (`IsEmpty`), then if the object has the given property (`Has`) then they get and convert/coerce the property to a `bool`. + +The optional last parameter is the *default* value, which is `false` if left off: + +```c++ +// `foo` is false unless the user supplies a truthy value for it +bool foo = NanBooleanOptionValue(optionsObj, NanNew("foo")); +// `bar` is true unless the user supplies a falsy value for it +bool bar = NanBooleanOptionValueDefTrue(optionsObj, NanNew("bar"), true); +``` + + +### uint32_t NanUInt32OptionValue(Handle<Value>, Handle<String>, uint32_t) + +Similar to `NanBooleanOptionValue`, use `NanUInt32OptionValue` to fetch an integer option from your options object. Can be any kind of JavaScript `Number` and it will be coerced to an unsigned 32-bit integer. + +Requires all 3 arguments as a default is not optional: + +```c++ +uint32_t count = NanUInt32OptionValue(optionsObj, NanNew("count"), 1024); +``` + + +### NanError(message), NanTypeError(message), NanRangeError(message) + +For making `Error`, `TypeError` and `RangeError` objects. + +```c++ +Local res = NanError("you must supply a callback argument"); +``` + + +### NanThrowError(message), NanThrowTypeError(message), NanThrowRangeError(message), NanThrowError(Local<Value>), NanThrowError(Local<Value>, int) + +For throwing `Error`, `TypeError` and `RangeError` objects. + +```c++ +NanThrowError("you must supply a callback argument"); +``` + +Can also handle any custom object you may want to throw. If used with the error code argument, it will add the supplied error code to the error object as a property called `code`. + + +### Local<Object> NanNewBufferHandle(char *, uint32_t), Local<Object> NanNewBufferHandle(uint32_t) + +The `Buffer` API has changed a little in Node 0.11, this helper provides consistent access to `Buffer` creation: + +```c++ +NanNewBufferHandle((char*)value.data(), value.size()); +``` + +Can also be used to initialize a `Buffer` with just a `size` argument. + +Can also be supplied with a `NanFreeCallback` and a hint for the garbage collector. + + +### Local<Object> NanBufferUse(char*, uint32_t) + +`Buffer::New(char*, uint32_t)` prior to 0.11 would make a copy of the data. +While it was possible to get around this, it required a shim by passing a +callback. So the new API `Buffer::Use(char*, uint32_t)` was introduced to remove +needing to use this shim. + +`NanBufferUse` uses the `char*` passed as the backing data, and will free the +memory automatically when the weak callback is called. Keep this in mind, as +careless use can lead to "double free or corruption" and other cryptic failures. + + +### bool NanHasInstance(Persistent<FunctionTemplate>&, Handle<Value>) + +Can be used to check the type of an object to determine it is of a particular class you have already defined and have a `Persistent` handle for. + + +### Local<Context> NanNewContextHandle([ExtensionConfiguration*, Handle<ObjectTemplate>, Handle<Value>]) +Creates a new `Local` handle. + +```c++ +Local ftmpl = NanNew(); +Local otmpl = ftmpl->InstanceTemplate(); +Local ctx = NanNewContextHandle(NULL, otmpl); +``` + + +### Local<Context> NanGetCurrentContext() + +Gets the current context. + +```c++ +Local ctx = NanGetCurrentContext(); +``` + + +### void NanDisposePersistent(Persistent<T> &) + +Use `NanDisposePersistent` to dispose a `Persistent` handle. + +```c++ +NanDisposePersistent(persistentHandle); +``` + + +### NanAssignPersistent(handle, object) + +Use `NanAssignPersistent` to assign a non-`Persistent` handle to a `Persistent` one. You can no longer just declare a `Persistent` handle and assign directly to it later, you have to `Reset` it in Node 0.11, so this makes it easier. + +In general it is now better to place anything you want to protect from V8's garbage collector as properties of a generic `Object` and then assign that to a `Persistent`. This works in older versions of Node also if you use `NanAssignPersistent`: + +```c++ +Persistent persistentHandle; + +... + +Local obj = NanNew(); +obj->Set(NanNew("key"), keyHandle); // where keyHandle might be a Local +NanAssignPersistent(persistentHandle, obj) +``` + + +### _NanWeakCallbackInfo<T, P>* NanMakeWeakPersistent(Handle<T>, P*, _NanWeakCallbackInfo<T, P>::Callback) + +Creates a weak persistent handle with the supplied parameter and `NAN_WEAK_CALLBACK`. + +```c++ +NAN_WEAK_CALLBACK(weakCallback) { + +... + +} + +Local func; + +... + +int *parameter = new int(0); +NanMakeWeakPersistent(func, parameter, &weakCallback); +``` + + +### NanSetTemplate(templ, name, value [, attributes]) + +Use to add properties on object and function templates. + + +### NanSetPrototypeTemplate(templ, name, value [, attributes]) + +Use to add prototype properties on function templates. + + +### NanSetInstanceTemplate(templ, name, value [, attributes]) + +Use to add instance properties on function templates. + + +### NanMakeCallback(target, func, argc, argv) + +Use instead of `node::MakeCallback` to call javascript functions. This is the only proper way of calling functions. + + +### NanCompileScript(Handle s [, const ScriptOrigin& origin]) + +Use to create new scripts bound to the current context. + + +### NanRunScript(script) + +Use to run both bound and unbound scripts. + + +### NanAdjustExternalMemory(int change_in_bytes) + +Simply does `AdjustAmountOfExternalAllocatedMemory`, note that the argument and returned value have type `int`. + + +### NanAddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type_filter=kGCTypeAll) + +Simply does `AddGCEpilogueCallback` + + +### NanAddGCPrologueCallback(GCPrologueCallback callback, GCType gc_type_filter=kGCTypeAll) + +Simply does `AddGCPrologueCallback` + + +### NanRemoveGCEpilogueCallback(GCEpilogueCallback callback) + +Simply does `RemoveGCEpilogueCallback` + + +### NanRemoveGCPrologueCallback(GCPrologueCallback callback) + +Simply does `RemoveGCPrologueCallback` + + +### NanGetHeapStatistics(HeapStatistics *heap_statistics) + +Simply does `GetHeapStatistics` + + +### NanCallback + +Because of the difficulties imposed by the changes to `Persistent` handles in V8 in Node 0.11, creating `Persistent` versions of your `Handle` is annoyingly tricky. `NanCallback` makes it easier by taking your handle, making it persistent until the `NanCallback` is deleted and even providing a handy `Call()` method to fetch and execute the callback `Function`. + +```c++ +Local callbackHandle = args[0].As(); +NanCallback *callback = new NanCallback(callbackHandle); +// pass `callback` around and it's safe from GC until you: +delete callback; +``` + +You can execute the callback like so: + +```c++ +// no arguments: +callback->Call(0, NULL); + +// an error argument: +Handle argv[] = { + NanError(NanNew("fail!")) +}; +callback->Call(1, argv); + +// a success argument: +Handle argv[] = { + NanNull(), + NanNew("w00t!") +}; +callback->Call(2, argv); +``` + +`NanCallback` also has a `Local GetCallback()` method that you can use +to fetch a local handle to the underlying callback function, as well as a +`void SetFunction(Handle)` for setting the callback on the +`NanCallback`. You can check if a `NanCallback` is empty with the `bool IsEmpty()` method. Additionally a generic constructor is available for using +`NanCallback` without performing heap allocations. + + +### NanAsyncWorker + +`NanAsyncWorker` is an abstract class that you can subclass to have much of the annoying async queuing and handling taken care of for you. It can even store arbitrary V8 objects for you and have them persist while the async work is in progress. + +See a rough outline of the implementation: + +```c++ +class NanAsyncWorker { +public: + NanAsyncWorker (NanCallback *callback); + + // Clean up persistent handles and delete the *callback + virtual ~NanAsyncWorker (); + + // Check the `ErrorMessage()` and call HandleOKCallback() + // or HandleErrorCallback depending on whether it has been set or not + virtual void WorkComplete (); + + // You must implement this to do some async work. If there is an + // error then use `SetErrorMessage()` to set an error message and the callback will + // be passed that string in an Error object + virtual void Execute (); + + // Save a V8 object in a Persistent handle to protect it from GC + void SaveToPersistent(const char *key, Local &obj); + + // Fetch a stored V8 object (don't call from within `Execute()`) + Local GetFromPersistent(const char *key); + + // Get the error message (or NULL) + const char *ErrorMessage(); + + // Set an error message + void SetErrorMessage(const char *msg); + +protected: + // Default implementation calls the callback function with no arguments. + // Override this to return meaningful data + virtual void HandleOKCallback (); + + // Default implementation calls the callback function with an Error object + // wrapping the `errmsg` string + virtual void HandleErrorCallback (); +}; +``` + + +### NanAsyncQueueWorker(NanAsyncWorker *) + +`NanAsyncQueueWorker` will run a `NanAsyncWorker` asynchronously via libuv. Both the *execute* and *after_work* steps are taken care of for you—most of the logic for this is embedded in `NanAsyncWorker`. + +### Contributors + +NAN is only possible due to the excellent work of the following contributors: + + + + + + + + +
Rod VaggGitHub/rvaggTwitter/@rvagg
Benjamin ByholmGitHub/kkoopa-
Trevor NorrisGitHub/trevnorrisTwitter/@trevnorris
Nathan RajlichGitHub/TooTallNateTwitter/@TooTallNate
Brett LawsonGitHub/brett19Twitter/@brett19x
Ben NoordhuisGitHub/bnoordhuisTwitter/@bnoordhuis
+ +Licence & copyright +----------------------- + +Copyright (c) 2014 NAN contributors (listed above). + +Native Abstractions for Node.js is licensed under an MIT +no-false-attribs license. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE file for more details. diff --git a/node_modules/mongodb/node_modules/bson/node_modules/nan/appveyor.yml b/node_modules/mongodb/node_modules/bson/node_modules/nan/appveyor.yml new file mode 100644 index 0000000..657eed6 --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/node_modules/nan/appveyor.yml @@ -0,0 +1,32 @@ +# http://www.appveyor.com/docs/appveyor-yml + +# Test against these versions of Node.js. +environment: + matrix: + - nodejs_version: "0.8" + - nodejs_version: "0.10" + - nodejs_version: "0.11" + +# Install scripts. (runs after repo cloning) +install: + # Get the latest stable version of Node 0.STABLE.latest + - npm install npm + - move node_modules npm + - ps: Update-NodeJsInstallation (Get-NodeJsLatestBuild $env:nodejs_version) + # Typical npm stuff. + - npm/.bin/npm install + - npm/.bin/npm run rebuild-tests + +# Post-install test scripts. +test_script: + # Output useful info for debugging. + - node --version + - npm --version + - cmd: npm test + +# Don't actually build. +build: off + +# Set build version format here instead of in the admin panel. +version: "{build}" + diff --git a/node_modules/mongodb/node_modules/bson/node_modules/nan/include_dirs.js b/node_modules/mongodb/node_modules/bson/node_modules/nan/include_dirs.js new file mode 100644 index 0000000..4f1dfb4 --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/node_modules/nan/include_dirs.js @@ -0,0 +1 @@ +console.log(require('path').relative('.', __dirname)); diff --git a/node_modules/mongodb/node_modules/bson/node_modules/nan/nan.h b/node_modules/mongodb/node_modules/bson/node_modules/nan/nan.h new file mode 100644 index 0000000..063de4e --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/node_modules/nan/nan.h @@ -0,0 +1,2331 @@ +/********************************************************************************** + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2014 NAN contributors: + * - Rod Vagg + * - Benjamin Byholm + * - Trevor Norris + * - Nathan Rajlich + * - Brett Lawson + * - Ben Noordhuis + * + * MIT +no-false-attribs License + * + * Version 1.3.0: current Node unstable: 0.11.13, Node stable: 0.10.30 + * + * See https://github.com/rvagg/nan for the latest update to this file + **********************************************************************************/ + +#ifndef NAN_H_ +#define NAN_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(__GNUC__) && !defined(DEBUG) +# define NAN_INLINE inline __attribute__((always_inline)) +#elif defined(_MSC_VER) && !defined(DEBUG) +# define NAN_INLINE __forceinline +#else +# define NAN_INLINE inline +#endif + +#if defined(__GNUC__) && !V8_DISABLE_DEPRECATIONS +# define NAN_DEPRECATED __attribute__((deprecated)) +#elif defined(_MSC_VER) && !V8_DISABLE_DEPRECATIONS +# define NAN_DEPRECATED __declspec(deprecated) +#else +# define NAN_DEPRECATED +#endif + +// some generic helpers + +template NAN_INLINE bool NanSetPointerSafe( + T *var + , T val +) { + if (var) { + *var = val; + return true; + } else { + return false; + } +} + +template NAN_INLINE T NanGetPointerSafe( + T *var + , T fallback = reinterpret_cast(0) +) { + if (var) { + return *var; + } else { + return fallback; + } +} + +NAN_INLINE bool NanBooleanOptionValue( + v8::Local optionsObj + , v8::Handle opt, bool def +) { + if (def) { + return optionsObj.IsEmpty() + || !optionsObj->Has(opt) + || optionsObj->Get(opt)->BooleanValue(); + } else { + return !optionsObj.IsEmpty() + && optionsObj->Has(opt) + && optionsObj->Get(opt)->BooleanValue(); + } +} + +NAN_INLINE bool NanBooleanOptionValue( + v8::Local optionsObj + , v8::Handle opt +) { + return NanBooleanOptionValue(optionsObj, opt, false); +} + +NAN_INLINE uint32_t NanUInt32OptionValue( + v8::Local optionsObj + , v8::Handle opt + , uint32_t def +) { + return !optionsObj.IsEmpty() + && optionsObj->Has(opt) + && optionsObj->Get(opt)->IsNumber() + ? optionsObj->Get(opt)->Uint32Value() + : def; +} + +#if (NODE_MODULE_VERSION > 0x000B) +// Node 0.11+ (0.11.3 and below won't compile with these) + +# define _NAN_METHOD_ARGS_TYPE const v8::FunctionCallbackInfo& +# define _NAN_METHOD_ARGS _NAN_METHOD_ARGS_TYPE args +# define _NAN_METHOD_RETURN_TYPE void + +# define _NAN_GETTER_ARGS_TYPE const v8::PropertyCallbackInfo& +# define _NAN_GETTER_ARGS _NAN_GETTER_ARGS_TYPE args +# define _NAN_GETTER_RETURN_TYPE void + +# define _NAN_SETTER_ARGS_TYPE const v8::PropertyCallbackInfo& +# define _NAN_SETTER_ARGS _NAN_SETTER_ARGS_TYPE args +# define _NAN_SETTER_RETURN_TYPE void + +# define _NAN_PROPERTY_GETTER_ARGS_TYPE \ + const v8::PropertyCallbackInfo& +# define _NAN_PROPERTY_GETTER_ARGS _NAN_PROPERTY_GETTER_ARGS_TYPE args +# define _NAN_PROPERTY_GETTER_RETURN_TYPE void + +# define _NAN_PROPERTY_SETTER_ARGS_TYPE \ + const v8::PropertyCallbackInfo& +# define _NAN_PROPERTY_SETTER_ARGS _NAN_PROPERTY_SETTER_ARGS_TYPE args +# define _NAN_PROPERTY_SETTER_RETURN_TYPE void + +# define _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE \ + const v8::PropertyCallbackInfo& +# define _NAN_PROPERTY_ENUMERATOR_ARGS _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE args +# define _NAN_PROPERTY_ENUMERATOR_RETURN_TYPE void + +# define _NAN_PROPERTY_DELETER_ARGS_TYPE \ + const v8::PropertyCallbackInfo& +# define _NAN_PROPERTY_DELETER_ARGS \ + _NAN_PROPERTY_DELETER_ARGS_TYPE args +# define _NAN_PROPERTY_DELETER_RETURN_TYPE void + +# define _NAN_PROPERTY_QUERY_ARGS_TYPE \ + const v8::PropertyCallbackInfo& +# define _NAN_PROPERTY_QUERY_ARGS _NAN_PROPERTY_QUERY_ARGS_TYPE args +# define _NAN_PROPERTY_QUERY_RETURN_TYPE void + +# define _NAN_INDEX_GETTER_ARGS_TYPE \ + const v8::PropertyCallbackInfo& +# define _NAN_INDEX_GETTER_ARGS _NAN_INDEX_GETTER_ARGS_TYPE args +# define _NAN_INDEX_GETTER_RETURN_TYPE void + +# define _NAN_INDEX_SETTER_ARGS_TYPE \ + const v8::PropertyCallbackInfo& +# define _NAN_INDEX_SETTER_ARGS _NAN_INDEX_SETTER_ARGS_TYPE args +# define _NAN_INDEX_SETTER_RETURN_TYPE void + +# define _NAN_INDEX_ENUMERATOR_ARGS_TYPE \ + const v8::PropertyCallbackInfo& +# define _NAN_INDEX_ENUMERATOR_ARGS _NAN_INDEX_ENUMERATOR_ARGS_TYPE args +# define _NAN_INDEX_ENUMERATOR_RETURN_TYPE void + +# define _NAN_INDEX_DELETER_ARGS_TYPE \ + const v8::PropertyCallbackInfo& +# define _NAN_INDEX_DELETER_ARGS _NAN_INDEX_DELETER_ARGS_TYPE args +# define _NAN_INDEX_DELETER_RETURN_TYPE void + +# define _NAN_INDEX_QUERY_ARGS_TYPE \ + const v8::PropertyCallbackInfo& +# define _NAN_INDEX_QUERY_ARGS _NAN_INDEX_QUERY_ARGS_TYPE args +# define _NAN_INDEX_QUERY_RETURN_TYPE void + + typedef v8::FunctionCallback NanFunctionCallback; + + template + NAN_INLINE v8::Local NanNew() { + return T::New(v8::Isolate::GetCurrent()); + } + + template + NAN_INLINE v8::Local NanNew(P arg1) { + return T::New(v8::Isolate::GetCurrent(), arg1); + } + + template + NAN_INLINE v8::Local NanNew( + v8::Handle receiver + , int argc + , v8::Handle argv[] = 0) { + return v8::Signature::New(v8::Isolate::GetCurrent(), receiver, argc, argv); + } + + template + NAN_INLINE v8::Local NanNew( + NanFunctionCallback callback + , v8::Handle data = v8::Handle() + , v8::Handle signature = v8::Handle()) { + return T::New(v8::Isolate::GetCurrent(), callback, data, signature); + } + + template + NAN_INLINE v8::Local NanNew(v8::Handle arg1) { + return v8::Local::New(v8::Isolate::GetCurrent(), arg1); + } + + template + NAN_INLINE v8::Local NanNew(const v8::Persistent &arg1) { + return v8::Local::New(v8::Isolate::GetCurrent(), arg1); + } + + template + NAN_INLINE v8::Local NanNew(P arg1, int arg2) { + return T::New(v8::Isolate::GetCurrent(), arg1, arg2); + } + + template<> + NAN_INLINE v8::Local NanNew() { + return v8::Array::New(v8::Isolate::GetCurrent()); + } + + template<> + NAN_INLINE v8::Local NanNew(int length) { + return v8::Array::New(v8::Isolate::GetCurrent(), length); + } + + template<> + NAN_INLINE v8::Local NanNew(double time) { + return v8::Date::New(v8::Isolate::GetCurrent(), time).As(); + } + + template<> + NAN_INLINE v8::Local NanNew(int time) { + return v8::Date::New(v8::Isolate::GetCurrent(), time).As(); + } + + typedef v8::UnboundScript NanUnboundScript; + typedef v8::Script NanBoundScript; + + template + NAN_INLINE v8::Local NanNew( + P s + , const v8::ScriptOrigin& origin + ) { + v8::ScriptCompiler::Source source(s, origin); + return v8::ScriptCompiler::CompileUnbound( + v8::Isolate::GetCurrent(), &source); + } + + template<> + NAN_INLINE v8::Local NanNew( + v8::Local s + ) { + v8::ScriptCompiler::Source source(s); + return v8::ScriptCompiler::CompileUnbound( + v8::Isolate::GetCurrent(), &source); + } + + template<> + NAN_INLINE v8::Local NanNew(bool value) { + return v8::BooleanObject::New(value).As(); + } + + template<> + NAN_INLINE v8::Local + NanNew >( + v8::Local value) { + return v8::StringObject::New(value).As(); + } + + template<> + NAN_INLINE v8::Local + NanNew >( + v8::Handle value) { + return v8::StringObject::New(value).As(); + } + + template<> + NAN_INLINE v8::Local NanNew(double val) { + return v8::NumberObject::New( + v8::Isolate::GetCurrent(), val).As(); + } + + template + NAN_INLINE v8::Local NanNew( + v8::Handle pattern, v8::RegExp::Flags flags) { + return v8::RegExp::New(pattern, flags); + } + + template + NAN_INLINE v8::Local NanNew( + v8::Local pattern, v8::RegExp::Flags flags) { + return v8::RegExp::New(pattern, flags); + } + + template + NAN_INLINE v8::Local NanNew( + v8::Handle pattern, v8::RegExp::Flags flags) { + return v8::RegExp::New(pattern, flags); + } + + template + NAN_INLINE v8::Local NanNew( + v8::Local pattern, v8::RegExp::Flags flags) { + return v8::RegExp::New(pattern, flags); + } + + template<> + NAN_INLINE v8::Local NanNew(int32_t val) { + return v8::Uint32::NewFromUnsigned( + v8::Isolate::GetCurrent(), val)->ToUint32(); + } + + template<> + NAN_INLINE v8::Local NanNew(uint32_t val) { + return v8::Uint32::NewFromUnsigned( + v8::Isolate::GetCurrent(), val)->ToUint32(); + } + + template<> + NAN_INLINE v8::Local NanNew(int32_t val) { + return v8::Int32::New(v8::Isolate::GetCurrent(), val)->ToInt32(); + } + + template<> + NAN_INLINE v8::Local NanNew(uint32_t val) { + return v8::Int32::New(v8::Isolate::GetCurrent(), val)->ToInt32(); + } + + template<> + NAN_INLINE v8::Local NanNew( + char *arg + , int length) { + return v8::String::NewFromUtf8( + v8::Isolate::GetCurrent() + , arg + , v8::String::kNormalString + , length); + } + + template<> + NAN_INLINE v8::Local NanNew( + const char *arg + , int length) { + return v8::String::NewFromUtf8( + v8::Isolate::GetCurrent() + , arg + , v8::String::kNormalString + , length); + } + + template<> + NAN_INLINE v8::Local NanNew(char *arg) { + return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), arg); + } + + template<> + NAN_INLINE v8::Local NanNew( + const char *arg) { + return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), arg); + } + + template<> + NAN_INLINE v8::Local NanNew( + uint8_t *arg + , int length) { + return v8::String::NewFromOneByte( + v8::Isolate::GetCurrent() + , arg + , v8::String::kNormalString + , length); + } + + template<> + NAN_INLINE v8::Local NanNew( + const uint8_t *arg + , int length) { + return v8::String::NewFromOneByte( + v8::Isolate::GetCurrent() + , arg + , v8::String::kNormalString + , length); + } + + template<> + NAN_INLINE v8::Local NanNew(uint8_t *arg) { + return v8::String::NewFromOneByte(v8::Isolate::GetCurrent(), arg); + } + + template<> + NAN_INLINE v8::Local NanNew( + const uint8_t *arg) { + return v8::String::NewFromOneByte(v8::Isolate::GetCurrent(), arg); + } + + template<> + NAN_INLINE v8::Local NanNew( + uint16_t *arg + , int length) { + return v8::String::NewFromTwoByte( + v8::Isolate::GetCurrent() + , arg + , v8::String::kNormalString + , length); + } + + template<> + NAN_INLINE v8::Local NanNew( + const uint16_t *arg + , int length) { + return v8::String::NewFromTwoByte( + v8::Isolate::GetCurrent() + , arg + , v8::String::kNormalString + , length); + } + template<> + NAN_INLINE v8::Local NanNew( + uint16_t *arg) { + return v8::String::NewFromTwoByte(v8::Isolate::GetCurrent(), arg); + } + + template<> + NAN_INLINE v8::Local NanNew( + const uint16_t *arg) { + return v8::String::NewFromTwoByte(v8::Isolate::GetCurrent(), arg); + } + + template<> + NAN_INLINE v8::Local NanNew( + std::string arg) { + return NanNew(arg.c_str(), arg.size()); + } + + template<> + NAN_INLINE v8::Local NanNew() { + return v8::String::Empty(v8::Isolate::GetCurrent()); + } + + NAN_INLINE v8::Local NanNew(const char* arg, int length = -1) { + return NanNew(arg, length); + } + + NAN_INLINE v8::Local NanNew( + const uint8_t* arg + , int length = -1) { + return NanNew(arg, length); + } + + NAN_INLINE v8::Local NanNew( + const uint16_t* arg + , int length = -1) { + return NanNew(arg, length); + } + + NAN_INLINE v8::Local NanNew( + const std::string& arg) { + return NanNew(arg.c_str(), arg.size()); + } + + NAN_INLINE v8::Local NanNew(double val) { + return NanNew(val); + } + + NAN_INLINE v8::Local NanNew(int val) { + return NanNew(val); + } + + NAN_INLINE v8::Local NanNew(unsigned int val) { + return NanNew(val); + } + + NAN_INLINE v8::Local NanNew(bool val) { + return NanNew(val); + } + + NAN_INLINE v8::Local NanNew( + v8::String::ExternalStringResource *resource) { + return v8::String::NewExternal(v8::Isolate::GetCurrent(), resource); + } + + NAN_INLINE v8::Local NanNew( + v8::String::ExternalAsciiStringResource *resource) { + return v8::String::NewExternal(v8::Isolate::GetCurrent(), resource); + } + +# define NanScope() v8::HandleScope scope(v8::Isolate::GetCurrent()) +# define NanEscapableScope() \ + v8::EscapableHandleScope scope(v8::Isolate::GetCurrent()) + + template + NAN_INLINE v8::Local _NanEscapeScopeHelper(v8::Handle val) { + return NanNew(val); + } + + template + NAN_INLINE v8::Local _NanEscapeScopeHelper(v8::Local val) { + return val; + } + +# define NanEscapeScope(val) scope.Escape(_NanEscapeScopeHelper(val)) +# define NanLocker() v8::Locker locker(v8::Isolate::GetCurrent()) +# define NanUnlocker() v8::Unlocker unlocker(v8::Isolate::GetCurrent()) +# define NanReturnValue(value) return args.GetReturnValue().Set(value) +# define NanReturnUndefined() return +# define NanReturnNull() return args.GetReturnValue().SetNull() +# define NanReturnEmptyString() return args.GetReturnValue().SetEmptyString() + +# define NanObjectWrapHandle(obj) obj->handle() + + NAN_INLINE v8::Local NanUndefined() { + NanEscapableScope(); + return NanEscapeScope(NanNew(v8::Undefined(v8::Isolate::GetCurrent()))); + } + + NAN_INLINE v8::Local NanNull() { + NanEscapableScope(); + return NanEscapeScope(NanNew(v8::Null(v8::Isolate::GetCurrent()))); + } + + NAN_INLINE v8::Local NanTrue() { + NanEscapableScope(); + return NanEscapeScope(NanNew(v8::True(v8::Isolate::GetCurrent()))); + } + + NAN_INLINE v8::Local NanFalse() { + NanEscapableScope(); + return NanEscapeScope(NanNew(v8::False(v8::Isolate::GetCurrent()))); + } + + NAN_INLINE int NanAdjustExternalMemory(int bc) { + return static_cast( + v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(bc)); + } + + NAN_INLINE void NanSetTemplate( + v8::Handle templ + , const char *name + , v8::Handle value) { + templ->Set(v8::Isolate::GetCurrent(), name, value); + } + + NAN_INLINE void NanSetTemplate( + v8::Handle templ + , v8::Handle name + , v8::Handle value + , v8::PropertyAttribute attributes) { + templ->Set(name, value, attributes); + } + + NAN_INLINE v8::Local NanGetCurrentContext() { + return v8::Isolate::GetCurrent()->GetCurrentContext(); + } + + NAN_INLINE void* NanGetInternalFieldPointer( + v8::Handle object + , int index) { + return object->GetAlignedPointerFromInternalField(index); + } + + NAN_INLINE void NanSetInternalFieldPointer( + v8::Handle object + , int index + , void* value) { + object->SetAlignedPointerInInternalField(index, value); + } + + NAN_INLINE void NanAddGCEpilogueCallback( + v8::Isolate::GCEpilogueCallback callback + , v8::GCType gc_type_filter = v8::kGCTypeAll) { + v8::Isolate::GetCurrent()->AddGCEpilogueCallback(callback, gc_type_filter); + } + + NAN_INLINE void NanRemoveGCEpilogueCallback( + v8::Isolate::GCEpilogueCallback callback) { + v8::Isolate::GetCurrent()->RemoveGCEpilogueCallback(callback); + } + + NAN_INLINE void NanAddGCPrologueCallback( + v8::Isolate::GCPrologueCallback callback + , v8::GCType gc_type_filter = v8::kGCTypeAll) { + v8::Isolate::GetCurrent()->AddGCPrologueCallback(callback, gc_type_filter); + } + + NAN_INLINE void NanRemoveGCPrologueCallback( + v8::Isolate::GCPrologueCallback callback) { + v8::Isolate::GetCurrent()->RemoveGCPrologueCallback(callback); + } + + NAN_INLINE void NanGetHeapStatistics( + v8::HeapStatistics *heap_statistics) { + v8::Isolate::GetCurrent()->GetHeapStatistics(heap_statistics); + } + + NAN_DEPRECATED NAN_INLINE v8::Local NanSymbol( + const char* data, int length = -1) { + return NanNew(data, length); + } + + template + NAN_INLINE void NanAssignPersistent( + v8::Persistent& handle + , v8::Handle obj) { + handle.Reset(v8::Isolate::GetCurrent(), obj); + } + + template + NAN_INLINE void NanAssignPersistent( + v8::Persistent& handle + , const v8::Persistent& obj) { + handle.Reset(v8::Isolate::GetCurrent(), obj); + } + + template + class _NanWeakCallbackData; + + template + struct _NanWeakCallbackInfo { + typedef void (*Callback)(const _NanWeakCallbackData& data); + NAN_INLINE _NanWeakCallbackInfo(v8::Handle handle, P* param, Callback cb) + : parameter(param), callback(cb) { + NanAssignPersistent(persistent, handle); + } + + NAN_INLINE ~_NanWeakCallbackInfo() { + persistent.Reset(); + } + + P* const parameter; + Callback const callback; + v8::Persistent persistent; + }; + + template + class _NanWeakCallbackData { + public: + NAN_INLINE _NanWeakCallbackData(_NanWeakCallbackInfo *info) + : info_(info) { } + + NAN_INLINE v8::Local GetValue() const { + return NanNew(info_->persistent); + } + + NAN_INLINE P* GetParameter() const { return info_->parameter; } + + NAN_INLINE bool IsNearDeath() const { + return info_->persistent.IsNearDeath(); + } + + NAN_INLINE void Revive() const; + + NAN_INLINE _NanWeakCallbackInfo* GetCallbackInfo() const { + return info_; + } + + NAN_DEPRECATED NAN_INLINE void Dispose() const { + } + + private: + _NanWeakCallbackInfo* info_; + }; + + template + static void _NanWeakCallbackDispatcher( + const v8::WeakCallbackData > &data) { + _NanWeakCallbackInfo *info = data.GetParameter(); + _NanWeakCallbackData wcbd(info); + info->callback(wcbd); + if (wcbd.IsNearDeath()) { + delete wcbd.GetCallbackInfo(); + } + } + + template + NAN_INLINE void _NanWeakCallbackData::Revive() const { + info_->persistent.SetWeak(info_, &_NanWeakCallbackDispatcher); + } + +template +NAN_INLINE _NanWeakCallbackInfo* NanMakeWeakPersistent( + v8::Handle handle + , P* parameter + , typename _NanWeakCallbackInfo::Callback callback) { + _NanWeakCallbackInfo *cbinfo = + new _NanWeakCallbackInfo(handle, parameter, callback); + cbinfo->persistent.SetWeak(cbinfo, &_NanWeakCallbackDispatcher); + return cbinfo; +} + +# define NAN_WEAK_CALLBACK(name) \ + template \ + static void name(const _NanWeakCallbackData &data) + +# define _NAN_ERROR(fun, errmsg) fun(NanNew(errmsg)) + +# define _NAN_THROW_ERROR(fun, errmsg) \ + do { \ + NanScope(); \ + v8::Isolate::GetCurrent()->ThrowException(_NAN_ERROR(fun, errmsg)); \ + } while (0); + + NAN_INLINE v8::Local NanError(const char* errmsg) { + return _NAN_ERROR(v8::Exception::Error, errmsg); + } + + NAN_INLINE void NanThrowError(const char* errmsg) { + _NAN_THROW_ERROR(v8::Exception::Error, errmsg); + } + + NAN_INLINE void NanThrowError(v8::Handle error) { + NanScope(); + v8::Isolate::GetCurrent()->ThrowException(error); + } + + NAN_INLINE v8::Local NanError( + const char *msg + , const int errorNumber + ) { + v8::Local err = v8::Exception::Error(NanNew(msg)); + v8::Local obj = err.As(); + obj->Set(NanNew("code"), NanNew(errorNumber)); + return err; + } + + NAN_INLINE void NanThrowError( + const char *msg + , const int errorNumber + ) { + NanThrowError(NanError(msg, errorNumber)); + } + + NAN_INLINE v8::Local NanTypeError(const char* errmsg) { + return _NAN_ERROR(v8::Exception::TypeError, errmsg); + } + + NAN_INLINE void NanThrowTypeError(const char* errmsg) { + _NAN_THROW_ERROR(v8::Exception::TypeError, errmsg); + } + + NAN_INLINE v8::Local NanRangeError(const char* errmsg) { + return _NAN_ERROR(v8::Exception::RangeError, errmsg); + } + + NAN_INLINE void NanThrowRangeError(const char* errmsg) { + _NAN_THROW_ERROR(v8::Exception::RangeError, errmsg); + } + + template NAN_INLINE void NanDisposePersistent( + v8::Persistent &handle + ) { + handle.Reset(); + } + + NAN_INLINE v8::Local NanNewBufferHandle ( + char *data + , size_t length + , node::smalloc::FreeCallback callback + , void *hint + ) { + return node::Buffer::New( + v8::Isolate::GetCurrent(), data, length, callback, hint); + } + + NAN_INLINE v8::Local NanNewBufferHandle ( + const char *data + , uint32_t size + ) { + return node::Buffer::New(v8::Isolate::GetCurrent(), data, size); + } + + NAN_INLINE v8::Local NanNewBufferHandle (uint32_t size) { + return node::Buffer::New(v8::Isolate::GetCurrent(), size); + } + + NAN_INLINE v8::Local NanBufferUse( + char* data + , uint32_t size + ) { + return node::Buffer::Use(v8::Isolate::GetCurrent(), data, size); + } + + NAN_INLINE bool NanHasInstance( + v8::Persistent& function_template + , v8::Handle value + ) { + return NanNew(function_template)->HasInstance(value); + } + + NAN_INLINE v8::Local NanNewContextHandle( + v8::ExtensionConfiguration* extensions = NULL + , v8::Handle tmpl = v8::Handle() + , v8::Handle obj = v8::Handle() + ) { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + return v8::Local::New( + isolate + , v8::Context::New(isolate, extensions, tmpl, obj) + ); + } + + NAN_INLINE v8::Local NanCompileScript( + v8::Local s + , const v8::ScriptOrigin& origin + ) { + v8::ScriptCompiler::Source source(s, origin); + return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &source); + } + + NAN_INLINE v8::Local NanCompileScript( + v8::Local s + ) { + v8::ScriptCompiler::Source source(s); + return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &source); + } + + NAN_INLINE v8::Local NanRunScript( + v8::Handle script + ) { + return script->BindToCurrentContext()->Run(); + } + + NAN_INLINE v8::Local NanRunScript( + v8::Handle script + ) { + return script->Run(); + } + + NAN_INLINE v8::Local NanMakeCallback( + v8::Handle target + , v8::Handle func + , int argc + , v8::Handle* argv) { + return NanNew(node::MakeCallback( + v8::Isolate::GetCurrent(), target, func, argc, argv)); + } + + NAN_INLINE v8::Local NanMakeCallback( + v8::Handle target + , v8::Handle symbol + , int argc + , v8::Handle* argv) { + return NanNew(node::MakeCallback( + v8::Isolate::GetCurrent(), target, symbol, argc, argv)); + } + + NAN_INLINE v8::Local NanMakeCallback( + v8::Handle target + , const char* method + , int argc + , v8::Handle* argv) { + return NanNew(node::MakeCallback( + v8::Isolate::GetCurrent(), target, method, argc, argv)); + } + + template + NAN_INLINE void NanSetIsolateData( + v8::Isolate *isolate + , T *data + ) { + isolate->SetData(0, data); + } + + template + NAN_INLINE T *NanGetIsolateData( + v8::Isolate *isolate + ) { + return static_cast(isolate->GetData(0)); + } + + class NanAsciiString { + public: + NAN_INLINE explicit NanAsciiString(v8::Handle from) { + v8::Local toStr = from->ToString(); + int buf_size = toStr->Length() + 1; + buf = new char[buf_size]; + size = toStr->WriteOneByte( + reinterpret_cast(buf), 0, buf_size); + } + + NAN_INLINE int Size() const { + return size; + } + + NAN_INLINE char* operator*() { return buf; } + + NAN_INLINE ~NanAsciiString() { + delete[] buf; + } + + private: + char *buf; + int size; + }; + + class NanUtf8String { + public: + NAN_INLINE explicit NanUtf8String(v8::Handle from) { + v8::Local toStr = from->ToString(); + int buf_size = toStr->Utf8Length() + 1; + buf = new char[buf_size]; + size = toStr->WriteUtf8(buf, buf_size); + } + + NAN_INLINE int Size() const { + return size; + } + + NAN_INLINE char* operator*() { return buf; } + + NAN_INLINE ~NanUtf8String() { + delete[] buf; + } + + private: + char *buf; + int size; + }; + + class NanUcs2String { + public: + NAN_INLINE explicit NanUcs2String(v8::Handle from) { + v8::Local toStr = from->ToString(); + int buf_size = toStr->Length() + 1; + buf = new uint16_t[buf_size]; + size = toStr->Write(buf, 0, buf_size); + } + + NAN_INLINE int Size() const { + return size; + } + + NAN_INLINE uint16_t* operator*() { return buf; } + + NAN_INLINE ~NanUcs2String() { + delete[] buf; + } + + private: + uint16_t *buf; + int size; + }; + +#else +// Node 0.8 and 0.10 + +# define _NAN_METHOD_ARGS_TYPE const v8::Arguments& +# define _NAN_METHOD_ARGS _NAN_METHOD_ARGS_TYPE args +# define _NAN_METHOD_RETURN_TYPE v8::Handle + +# define _NAN_GETTER_ARGS_TYPE const v8::AccessorInfo & +# define _NAN_GETTER_ARGS _NAN_GETTER_ARGS_TYPE args +# define _NAN_GETTER_RETURN_TYPE v8::Handle + +# define _NAN_SETTER_ARGS_TYPE const v8::AccessorInfo & +# define _NAN_SETTER_ARGS _NAN_SETTER_ARGS_TYPE args +# define _NAN_SETTER_RETURN_TYPE void + +# define _NAN_PROPERTY_GETTER_ARGS_TYPE const v8::AccessorInfo& +# define _NAN_PROPERTY_GETTER_ARGS _NAN_PROPERTY_GETTER_ARGS_TYPE args +# define _NAN_PROPERTY_GETTER_RETURN_TYPE v8::Handle + +# define _NAN_PROPERTY_SETTER_ARGS_TYPE const v8::AccessorInfo& +# define _NAN_PROPERTY_SETTER_ARGS _NAN_PROPERTY_SETTER_ARGS_TYPE args +# define _NAN_PROPERTY_SETTER_RETURN_TYPE v8::Handle + +# define _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE const v8::AccessorInfo& +# define _NAN_PROPERTY_ENUMERATOR_ARGS _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE args +# define _NAN_PROPERTY_ENUMERATOR_RETURN_TYPE v8::Handle + +# define _NAN_PROPERTY_DELETER_ARGS_TYPE const v8::AccessorInfo& +# define _NAN_PROPERTY_DELETER_ARGS _NAN_PROPERTY_DELETER_ARGS_TYPE args +# define _NAN_PROPERTY_DELETER_RETURN_TYPE v8::Handle + +# define _NAN_PROPERTY_QUERY_ARGS_TYPE const v8::AccessorInfo& +# define _NAN_PROPERTY_QUERY_ARGS _NAN_PROPERTY_QUERY_ARGS_TYPE args +# define _NAN_PROPERTY_QUERY_RETURN_TYPE v8::Handle + +# define _NAN_INDEX_GETTER_ARGS_TYPE const v8::AccessorInfo& +# define _NAN_INDEX_GETTER_ARGS _NAN_INDEX_GETTER_ARGS_TYPE args +# define _NAN_INDEX_GETTER_RETURN_TYPE v8::Handle + +# define _NAN_INDEX_SETTER_ARGS_TYPE const v8::AccessorInfo& +# define _NAN_INDEX_SETTER_ARGS _NAN_INDEX_SETTER_ARGS_TYPE args +# define _NAN_INDEX_SETTER_RETURN_TYPE v8::Handle + +# define _NAN_INDEX_ENUMERATOR_ARGS_TYPE const v8::AccessorInfo& +# define _NAN_INDEX_ENUMERATOR_ARGS _NAN_INDEX_ENUMERATOR_ARGS_TYPE args +# define _NAN_INDEX_ENUMERATOR_RETURN_TYPE v8::Handle + +# define _NAN_INDEX_DELETER_ARGS_TYPE const v8::AccessorInfo& +# define _NAN_INDEX_DELETER_ARGS _NAN_INDEX_DELETER_ARGS_TYPE args +# define _NAN_INDEX_DELETER_RETURN_TYPE v8::Handle + +# define _NAN_INDEX_QUERY_ARGS_TYPE const v8::AccessorInfo& +# define _NAN_INDEX_QUERY_ARGS _NAN_INDEX_QUERY_ARGS_TYPE args +# define _NAN_INDEX_QUERY_RETURN_TYPE v8::Handle + + typedef v8::InvocationCallback NanFunctionCallback; + + NAN_DEPRECATED NAN_INLINE v8::Local NanSymbol( + const char* data, int length = -1) { + return v8::String::NewSymbol(data, length); + } + + template + NAN_INLINE v8::Local NanNew() { + return v8::Local::New(T::New()); + } + + template + NAN_INLINE v8::Local NanNew(v8::Handle arg) { + return v8::Local::New(arg); + } + + template + NAN_INLINE v8::Local NanNew( + v8::Handle receiver + , int argc + , v8::Handle argv[] = 0) { + return v8::Signature::New(receiver, argc, argv); + } + + template + NAN_INLINE v8::Local NanNew( + NanFunctionCallback callback + , v8::Handle data = v8::Handle() + , v8::Handle signature = v8::Handle()) { + return T::New(callback, data, signature); + } + + template + NAN_INLINE v8::Local NanNew(const v8::Persistent &arg) { + return v8::Local::New(arg); + } + + template + NAN_INLINE v8::Local NanNew(P arg) { + return v8::Local::New(T::New(arg)); + } + + template + NAN_INLINE v8::Local NanNew(P arg, int length) { + return v8::Local::New(T::New(arg, length)); + } + + template + NAN_INLINE v8::Local NanNew( + v8::Handle pattern, v8::RegExp::Flags flags) { + return v8::RegExp::New(pattern, flags); + } + + template + NAN_INLINE v8::Local NanNew( + v8::Local pattern, v8::RegExp::Flags flags) { + return v8::RegExp::New(pattern, flags); + } + + template + NAN_INLINE v8::Local NanNew( + v8::Handle pattern, v8::RegExp::Flags flags) { + return v8::RegExp::New(pattern, flags); + } + + template + NAN_INLINE v8::Local NanNew( + v8::Local pattern, v8::RegExp::Flags flags) { + return v8::RegExp::New(pattern, flags); + } + + template<> + NAN_INLINE v8::Local NanNew() { + return v8::Array::New(); + } + + template<> + NAN_INLINE v8::Local NanNew(int length) { + return v8::Array::New(length); + } + + template<> + NAN_INLINE v8::Local NanNew(double time) { + return v8::Date::New(time).As(); + } + + template<> + NAN_INLINE v8::Local NanNew(int time) { + return v8::Date::New(time).As(); + } + + typedef v8::Script NanUnboundScript; + typedef v8::Script NanBoundScript; + + template + NAN_INLINE v8::Local NanNew( + P s + , const v8::ScriptOrigin& origin + ) { + return v8::Script::New(s, const_cast(&origin)); + } + + template<> + NAN_INLINE v8::Local NanNew( + v8::Local s + ) { + return v8::Script::New(s); + } + + template<> + NAN_INLINE v8::Local NanNew(bool value) { + return v8::BooleanObject::New(value).As(); + } + + template<> + NAN_INLINE v8::Local + NanNew >( + v8::Local value) { + return v8::StringObject::New(value).As(); + } + + template<> + NAN_INLINE v8::Local + NanNew >( + v8::Handle value) { + return v8::StringObject::New(value).As(); + } + + template<> + NAN_INLINE v8::Local NanNew(double val) { + return v8::NumberObject::New(val).As(); + } + + template<> + NAN_INLINE v8::Local NanNew(int32_t val) { + return v8::Uint32::NewFromUnsigned(val)->ToUint32(); + } + + template<> + NAN_INLINE v8::Local NanNew(uint32_t val) { + return v8::Uint32::NewFromUnsigned(val)->ToUint32(); + } + + template<> + NAN_INLINE v8::Local NanNew(int32_t val) { + return v8::Int32::New(val)->ToInt32(); + } + + template<> + NAN_INLINE v8::Local NanNew(uint32_t val) { + return v8::Int32::New(val)->ToInt32(); + } + + template<> + NAN_INLINE v8::Local NanNew( + uint8_t *arg + , int length) { + int len = length; + if (len < 0) { + size_t temp = strlen(reinterpret_cast(arg)); + assert(temp <= INT_MAX && "too long string"); + len = static_cast(temp); + } + uint16_t *warg = new uint16_t[len]; + for (int i = 0; i < len; i++) { + warg[i] = arg[i]; + } + v8::Local retval = v8::String::New(warg, len); + delete[] warg; + return retval; + } + + template<> + NAN_INLINE v8::Local NanNew( + const uint8_t *arg + , int length) { + int len = length; + if (len < 0) { + size_t temp = strlen(reinterpret_cast(arg)); + assert(temp <= INT_MAX && "too long string"); + len = static_cast(temp); + } + uint16_t *warg = new uint16_t[len]; + for (int i = 0; i < len; i++) { + warg[i] = arg[i]; + } + v8::Local retval = v8::String::New(warg, len); + delete[] warg; + return retval; + } + + template<> + NAN_INLINE v8::Local NanNew(uint8_t *arg) { + size_t temp = strlen(reinterpret_cast(arg)); + assert(temp <= INT_MAX && "too long string"); + int length = static_cast(temp); + uint16_t *warg = new uint16_t[length]; + for (int i = 0; i < length; i++) { + warg[i] = arg[i]; + } + + v8::Local retval = v8::String::New(warg, length); + delete[] warg; + return retval; + } + + template<> + NAN_INLINE v8::Local NanNew( + const uint8_t *arg) { + size_t temp = strlen(reinterpret_cast(arg)); + assert(temp <= INT_MAX && "too long string"); + int length = static_cast(temp); + uint16_t *warg = new uint16_t[length]; + for (int i = 0; i < length; i++) { + warg[i] = arg[i]; + } + v8::Local retval = v8::String::New(warg, length); + delete[] warg; + return retval; + } + + template<> + NAN_INLINE v8::Local NanNew( + std::string arg) { + return NanNew(arg.c_str(), arg.size()); + } + + template<> + NAN_INLINE v8::Local NanNew() { + return v8::String::Empty(); + } + + NAN_INLINE v8::Local NanNew(const char* arg, int length = -1) { + return NanNew(arg, length); + } + + NAN_INLINE v8::Local NanNew( + const uint8_t* arg + , int length = -1) { + return NanNew(arg, length); + } + + NAN_INLINE v8::Local NanNew( + const uint16_t* arg + , int length = -1) { + return NanNew(arg, length); + } + + NAN_INLINE v8::Local NanNew( + std::string& arg) { + return NanNew(arg.c_str(), arg.size()); + } + + NAN_INLINE v8::Local NanNew(double val) { + return NanNew(val); + } + + NAN_INLINE v8::Local NanNew(int val) { + return NanNew(val); + } + + NAN_INLINE v8::Local NanNew(unsigned int val) { + return NanNew(val); + } + + NAN_INLINE v8::Local NanNew(bool val) { + return NanNew(val); + } + + NAN_INLINE v8::Local NanNew( + v8::String::ExternalStringResource *resource) { + return v8::String::NewExternal(resource); + } + + NAN_INLINE v8::Local NanNew( + v8::String::ExternalAsciiStringResource *resource) { + return v8::String::NewExternal(resource); + } + +# define NanScope() v8::HandleScope scope +# define NanEscapableScope() v8::HandleScope scope +# define NanEscapeScope(val) scope.Close(val) +# define NanLocker() v8::Locker locker +# define NanUnlocker() v8::Unlocker unlocker +# define NanReturnValue(value) return scope.Close(value) +# define NanReturnUndefined() return v8::Undefined() +# define NanReturnNull() return v8::Null() +# define NanReturnEmptyString() return v8::String::Empty() +# define NanObjectWrapHandle(obj) v8::Local::New(obj->handle_) + + NAN_INLINE v8::Local NanUndefined() { + NanEscapableScope(); + return NanEscapeScope(NanNew(v8::Undefined())); + } + + NAN_INLINE v8::Local NanNull() { + NanEscapableScope(); + return NanEscapeScope(NanNew(v8::Null())); + } + + NAN_INLINE v8::Local NanTrue() { + NanEscapableScope(); + return NanEscapeScope(NanNew(v8::True())); + } + + NAN_INLINE v8::Local NanFalse() { + NanEscapableScope(); + return NanEscapeScope(NanNew(v8::False())); + } + + NAN_INLINE int NanAdjustExternalMemory(int bc) { + return static_cast(v8::V8::AdjustAmountOfExternalAllocatedMemory(bc)); + } + + NAN_INLINE void NanSetTemplate( + v8::Handle templ + , const char *name + , v8::Handle value) { + templ->Set(name, value); + } + + NAN_INLINE void NanSetTemplate( + v8::Handle templ + , v8::Handle name + , v8::Handle value + , v8::PropertyAttribute attributes) { + templ->Set(name, value, attributes); + } + + NAN_INLINE v8::Local NanGetCurrentContext() { + return v8::Context::GetCurrent(); + } + + NAN_INLINE void* NanGetInternalFieldPointer( + v8::Handle object + , int index) { + return object->GetPointerFromInternalField(index); + } + + NAN_INLINE void NanSetInternalFieldPointer( + v8::Handle object + , int index + , void* value) { + object->SetPointerInInternalField(index, value); + } + + NAN_INLINE void NanAddGCEpilogueCallback( + v8::GCEpilogueCallback callback + , v8::GCType gc_type_filter = v8::kGCTypeAll) { + v8::V8::AddGCEpilogueCallback(callback, gc_type_filter); + } + NAN_INLINE void NanRemoveGCEpilogueCallback( + v8::GCEpilogueCallback callback) { + v8::V8::RemoveGCEpilogueCallback(callback); + } + NAN_INLINE void NanAddGCPrologueCallback( + v8::GCPrologueCallback callback + , v8::GCType gc_type_filter = v8::kGCTypeAll) { + v8::V8::AddGCPrologueCallback(callback, gc_type_filter); + } + NAN_INLINE void NanRemoveGCPrologueCallback( + v8::GCPrologueCallback callback) { + v8::V8::RemoveGCPrologueCallback(callback); + } + NAN_INLINE void NanGetHeapStatistics( + v8::HeapStatistics *heap_statistics) { + v8::V8::GetHeapStatistics(heap_statistics); + } + + template + NAN_INLINE void NanAssignPersistent( + v8::Persistent& handle + , v8::Handle obj) { + handle.Dispose(); + handle = v8::Persistent::New(obj); + } + + template + class _NanWeakCallbackData; + + template + struct _NanWeakCallbackInfo { + typedef void (*Callback)(const _NanWeakCallbackData &data); + NAN_INLINE _NanWeakCallbackInfo(v8::Handle handle, P* param, Callback cb) + : parameter(param) + , callback(cb) + , persistent(v8::Persistent::New(handle)) { } + + NAN_INLINE ~_NanWeakCallbackInfo() { + persistent.Dispose(); + persistent.Clear(); + } + + P* const parameter; + Callback const callback; + v8::Persistent persistent; + }; + + template + class _NanWeakCallbackData { + public: + NAN_INLINE _NanWeakCallbackData(_NanWeakCallbackInfo *info) + : info_(info) { } + + NAN_INLINE v8::Local GetValue() const { + return NanNew(info_->persistent); + } + + NAN_INLINE P* GetParameter() const { return info_->parameter; } + + NAN_INLINE bool IsNearDeath() const { + return info_->persistent.IsNearDeath(); + } + + NAN_INLINE void Revive() const; + + NAN_INLINE _NanWeakCallbackInfo* GetCallbackInfo() const { + return info_; + } + + NAN_DEPRECATED NAN_INLINE void Dispose() const { + } + + private: + _NanWeakCallbackInfo* info_; + }; + + template + static void _NanWeakPersistentDispatcher( + v8::Persistent object, void *data) { + _NanWeakCallbackInfo* info = + static_cast<_NanWeakCallbackInfo*>(data); + _NanWeakCallbackData wcbd(info); + info->callback(wcbd); + if (wcbd.IsNearDeath()) { + delete wcbd.GetCallbackInfo(); + } + } + + template + NAN_INLINE void _NanWeakCallbackData::Revive() const { + info_->persistent.MakeWeak( + info_ + , &_NanWeakPersistentDispatcher); + } + + template + NAN_INLINE _NanWeakCallbackInfo* NanMakeWeakPersistent( + v8::Handle handle + , P* parameter + , typename _NanWeakCallbackInfo::Callback callback) { + _NanWeakCallbackInfo *cbinfo = + new _NanWeakCallbackInfo(handle, parameter, callback); + cbinfo->persistent.MakeWeak( + cbinfo + , &_NanWeakPersistentDispatcher); + return cbinfo; + } + +# define NAN_WEAK_CALLBACK(name) \ + template \ + static void name(const _NanWeakCallbackData &data) + +# define _NAN_ERROR(fun, errmsg) \ + fun(v8::String::New(errmsg)) + +# define _NAN_THROW_ERROR(fun, errmsg) \ + do { \ + NanScope(); \ + return v8::Local::New( \ + v8::ThrowException(_NAN_ERROR(fun, errmsg))); \ + } while (0); + + NAN_INLINE v8::Local NanError(const char* errmsg) { + return _NAN_ERROR(v8::Exception::Error, errmsg); + } + + NAN_INLINE v8::Local NanThrowError(const char* errmsg) { + _NAN_THROW_ERROR(v8::Exception::Error, errmsg); + } + + NAN_INLINE v8::Local NanThrowError( + v8::Handle error + ) { + NanScope(); + return v8::Local::New(v8::ThrowException(error)); + } + + NAN_INLINE v8::Local NanError( + const char *msg + , const int errorNumber + ) { + v8::Local err = v8::Exception::Error(v8::String::New(msg)); + v8::Local obj = err.As(); + obj->Set(v8::String::New("code"), v8::Int32::New(errorNumber)); + return err; + } + + NAN_INLINE v8::Local NanThrowError( + const char *msg + , const int errorNumber + ) { + return NanThrowError(NanError(msg, errorNumber)); + } + + NAN_INLINE v8::Local NanTypeError(const char* errmsg) { + return _NAN_ERROR(v8::Exception::TypeError, errmsg); + } + + NAN_INLINE v8::Local NanThrowTypeError( + const char* errmsg + ) { + _NAN_THROW_ERROR(v8::Exception::TypeError, errmsg); + } + + NAN_INLINE v8::Local NanRangeError( + const char* errmsg + ) { + return _NAN_ERROR(v8::Exception::RangeError, errmsg); + } + + NAN_INLINE v8::Local NanThrowRangeError( + const char* errmsg + ) { + _NAN_THROW_ERROR(v8::Exception::RangeError, errmsg); + } + + template + NAN_INLINE void NanDisposePersistent( + v8::Persistent &handle) { // NOLINT(runtime/references) + handle.Dispose(); + handle.Clear(); + } + + NAN_INLINE v8::Local NanNewBufferHandle ( + char *data + , size_t length + , node::Buffer::free_callback callback + , void *hint + ) { + return NanNew( + node::Buffer::New(data, length, callback, hint)->handle_); + } + + NAN_INLINE v8::Local NanNewBufferHandle ( + const char *data + , uint32_t size + ) { +#if NODE_MODULE_VERSION >= 0x000B + return NanNew(node::Buffer::New(data, size)->handle_); +#else + return NanNew( + node::Buffer::New(const_cast(data), size)->handle_); +#endif + } + + NAN_INLINE v8::Local NanNewBufferHandle (uint32_t size) { + return NanNew(node::Buffer::New(size)->handle_); + } + + NAN_INLINE void FreeData(char *data, void *hint) { + delete[] data; + } + + NAN_INLINE v8::Local NanBufferUse( + char* data + , uint32_t size + ) { + return NanNew( + node::Buffer::New(data, size, FreeData, NULL)->handle_); + } + + NAN_INLINE bool NanHasInstance( + v8::Persistent& function_template + , v8::Handle value + ) { + return function_template->HasInstance(value); + } + + NAN_INLINE v8::Local NanNewContextHandle( + v8::ExtensionConfiguration* extensions = NULL + , v8::Handle tmpl = v8::Handle() + , v8::Handle obj = v8::Handle() + ) { + v8::Persistent ctx = v8::Context::New(extensions, tmpl, obj); + v8::Local lctx = NanNew(ctx); + ctx.Dispose(); + return lctx; + } + + NAN_INLINE v8::Local NanCompileScript( + v8::Local s + , const v8::ScriptOrigin& origin + ) { + return v8::Script::Compile(s, const_cast(&origin)); + } + + NAN_INLINE v8::Local NanCompileScript( + v8::Local s + ) { + return v8::Script::Compile(s); + } + + NAN_INLINE v8::Local NanRunScript(v8::Handle script) { + return script->Run(); + } + + NAN_INLINE v8::Local NanMakeCallback( + v8::Handle target + , v8::Handle func + , int argc + , v8::Handle* argv) { +# if NODE_VERSION_AT_LEAST(0, 8, 0) + return NanNew(node::MakeCallback(target, func, argc, argv)); +# else + v8::TryCatch try_catch; + v8::Local result = NanNew(func->Call(target, argc, argv)); + if (try_catch.HasCaught()) { + node::FatalException(try_catch); + } + return result; +# endif + } + + NAN_INLINE v8::Local NanMakeCallback( + v8::Handle target + , v8::Handle symbol + , int argc + , v8::Handle* argv) { +# if NODE_VERSION_AT_LEAST(0, 8, 0) + return NanNew(node::MakeCallback(target, symbol, argc, argv)); +# else + v8::Local callback = target->Get(symbol).As(); + return NanMakeCallback(target, callback, argc, argv); +# endif + } + + NAN_INLINE v8::Local NanMakeCallback( + v8::Handle target + , const char* method + , int argc + , v8::Handle* argv) { +# if NODE_VERSION_AT_LEAST(0, 8, 0) + return NanNew(node::MakeCallback(target, method, argc, argv)); +# else + return NanMakeCallback(target, NanNew(method), argc, argv); +# endif + } + + template + NAN_INLINE void NanSetIsolateData( + v8::Isolate *isolate + , T *data + ) { + isolate->SetData(data); + } + + template + NAN_INLINE T *NanGetIsolateData( + v8::Isolate *isolate + ) { + return static_cast(isolate->GetData()); + } + + class NanAsciiString { + public: + NAN_INLINE explicit NanAsciiString(v8::Handle from) { + v8::Local toStr = from->ToString(); + int buf_size = toStr->Length() + 1; + buf = new char[buf_size]; + size = toStr->WriteAscii(buf, 0, buf_size); + } + + NAN_INLINE int Size() const { + return size; + } + + NAN_INLINE char* operator*() { return buf; } + + NAN_INLINE ~NanAsciiString() { + delete[] buf; + } + + private: + char *buf; + int size; + }; + + class NanUtf8String { + public: + NAN_INLINE explicit NanUtf8String(v8::Handle from) { + v8::Local toStr = from->ToString(); + int buf_size = toStr->Utf8Length() + 1; + buf = new char[buf_size]; + size = toStr->WriteUtf8(buf, buf_size); + } + + NAN_INLINE int Size() const { + return size; + } + + NAN_INLINE char* operator*() { return buf; } + + NAN_INLINE ~NanUtf8String() { + delete[] buf; + } + + private: + char *buf; + int size; + }; + + class NanUcs2String { + public: + NAN_INLINE explicit NanUcs2String(v8::Handle from) { + v8::Local toStr = from->ToString(); + int buf_size = toStr->Length() + 1; + buf = new uint16_t[buf_size]; + size = toStr->Write(buf, 0, buf_size); + } + + NAN_INLINE int Size() const { + return size; + } + + NAN_INLINE uint16_t* operator*() { return buf; } + + NAN_INLINE ~NanUcs2String() { + delete[] buf; + } + + private: + uint16_t *buf; + int size; + }; + +#endif // NODE_MODULE_VERSION + +typedef void (*NanFreeCallback)(char *data, void *hint); + +#define NAN_METHOD(name) _NAN_METHOD_RETURN_TYPE name(_NAN_METHOD_ARGS) +#define NAN_GETTER(name) \ + _NAN_GETTER_RETURN_TYPE name( \ + v8::Local property \ + , _NAN_GETTER_ARGS) +#define NAN_SETTER(name) \ + _NAN_SETTER_RETURN_TYPE name( \ + v8::Local property \ + , v8::Local value \ + , _NAN_SETTER_ARGS) +#define NAN_PROPERTY_GETTER(name) \ + _NAN_PROPERTY_GETTER_RETURN_TYPE name( \ + v8::Local property \ + , _NAN_PROPERTY_GETTER_ARGS) +#define NAN_PROPERTY_SETTER(name) \ + _NAN_PROPERTY_SETTER_RETURN_TYPE name( \ + v8::Local property \ + , v8::Local value \ + , _NAN_PROPERTY_SETTER_ARGS) +#define NAN_PROPERTY_ENUMERATOR(name) \ + _NAN_PROPERTY_ENUMERATOR_RETURN_TYPE name(_NAN_PROPERTY_ENUMERATOR_ARGS) +#define NAN_PROPERTY_DELETER(name) \ + _NAN_PROPERTY_DELETER_RETURN_TYPE name( \ + v8::Local property \ + , _NAN_PROPERTY_DELETER_ARGS) +#define NAN_PROPERTY_QUERY(name) \ + _NAN_PROPERTY_QUERY_RETURN_TYPE name( \ + v8::Local property \ + , _NAN_PROPERTY_QUERY_ARGS) +# define NAN_INDEX_GETTER(name) \ + _NAN_INDEX_GETTER_RETURN_TYPE name(uint32_t index, _NAN_INDEX_GETTER_ARGS) +#define NAN_INDEX_SETTER(name) \ + _NAN_INDEX_SETTER_RETURN_TYPE name( \ + uint32_t index \ + , v8::Local value \ + , _NAN_INDEX_SETTER_ARGS) +#define NAN_INDEX_ENUMERATOR(name) \ + _NAN_INDEX_ENUMERATOR_RETURN_TYPE name(_NAN_INDEX_ENUMERATOR_ARGS) +#define NAN_INDEX_DELETER(name) \ + _NAN_INDEX_DELETER_RETURN_TYPE name( \ + uint32_t index \ + , _NAN_INDEX_DELETER_ARGS) +#define NAN_INDEX_QUERY(name) \ + _NAN_INDEX_QUERY_RETURN_TYPE name(uint32_t index, _NAN_INDEX_QUERY_ARGS) + +class NanCallback { + public: + NanCallback() { + NanScope(); + v8::Local obj = NanNew(); + NanAssignPersistent(handle, obj); + } + + explicit NanCallback(const v8::Handle &fn) { + NanScope(); + v8::Local obj = NanNew(); + NanAssignPersistent(handle, obj); + SetFunction(fn); + } + + ~NanCallback() { + if (handle.IsEmpty()) return; + NanDisposePersistent(handle); + } + + NAN_INLINE void SetFunction(const v8::Handle &fn) { + NanScope(); + NanNew(handle)->Set(kCallbackIndex, fn); + } + + NAN_INLINE v8::Local GetFunction() const { + NanEscapableScope(); + return NanEscapeScope(NanNew(handle)->Get(kCallbackIndex) + .As()); + } + + NAN_INLINE bool IsEmpty() const { + NanScope(); + return NanNew(handle)->Get(kCallbackIndex)->IsUndefined(); + } + + v8::Handle Call(int argc, v8::Handle argv[]) const { + NanEscapableScope(); +#if (NODE_MODULE_VERSION > 0x000B) // 0.11.12+ + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::Local callback = NanNew(handle)-> + Get(kCallbackIndex).As(); + return NanEscapeScope(node::MakeCallback( + isolate + , isolate->GetCurrentContext()->Global() + , callback + , argc + , argv + )); +#else +#if NODE_VERSION_AT_LEAST(0, 8, 0) + v8::Local callback = handle-> + Get(kCallbackIndex).As(); + return NanEscapeScope(node::MakeCallback( + v8::Context::GetCurrent()->Global() + , callback + , argc + , argv + )); +#else + v8::Local callback = handle-> + Get(kCallbackIndex).As(); + return NanEscapeScope(NanMakeCallback( + v8::Context::GetCurrent()->Global(), callback, argc, argv)); +#endif +#endif + } + + private: + v8::Persistent handle; + static const uint32_t kCallbackIndex = 0; +}; + +/* abstract */ class NanAsyncWorker { + public: + explicit NanAsyncWorker(NanCallback *callback) + : callback(callback), errmsg_(NULL) { + request.data = this; + + NanScope(); + v8::Local obj = NanNew(); + NanAssignPersistent(persistentHandle, obj); + } + + virtual ~NanAsyncWorker() { + NanScope(); + + if (!persistentHandle.IsEmpty()) + NanDisposePersistent(persistentHandle); + if (callback) + delete callback; + if (errmsg_) + delete[] errmsg_; + } + + virtual void WorkComplete() { + NanScope(); + + if (errmsg_ == NULL) + HandleOKCallback(); + else + HandleErrorCallback(); + delete callback; + callback = NULL; + } + + NAN_INLINE void SaveToPersistent( + const char *key, const v8::Local &obj) { + v8::Local handle = NanNew(persistentHandle); + handle->Set(NanNew(key), obj); + } + + v8::Local GetFromPersistent(const char *key) const { + NanEscapableScope(); + v8::Local handle = NanNew(persistentHandle); + return NanEscapeScope(handle->Get(NanNew(key)).As()); + } + + virtual void Execute() = 0; + + uv_work_t request; + + protected: + v8::Persistent persistentHandle; + NanCallback *callback; + + virtual void HandleOKCallback() { + NanScope(); + + callback->Call(0, NULL); + } + + virtual void HandleErrorCallback() { + NanScope(); + + v8::Local argv[] = { + v8::Exception::Error(NanNew(ErrorMessage())) + }; + callback->Call(1, argv); + } + + void SetErrorMessage(const char *msg) { + if (errmsg_) { + delete[] errmsg_; + } + + size_t size = strlen(msg) + 1; + errmsg_ = new char[size]; + memcpy(errmsg_, msg, size); + } + + const char* ErrorMessage() const { + return errmsg_; + } + + private: + char *errmsg_; +}; + +NAN_INLINE void NanAsyncExecute (uv_work_t* req) { + NanAsyncWorker *worker = static_cast(req->data); + worker->Execute(); +} + +NAN_INLINE void NanAsyncExecuteComplete (uv_work_t* req) { + NanAsyncWorker* worker = static_cast(req->data); + worker->WorkComplete(); + delete worker; +} + +NAN_INLINE void NanAsyncQueueWorker (NanAsyncWorker* worker) { + uv_queue_work( + uv_default_loop() + , &worker->request + , NanAsyncExecute + , (uv_after_work_cb)NanAsyncExecuteComplete + ); +} + +//// Base 64 //// + +#define _nan_base64_encoded_size(size) ((size + 2 - ((size + 2) % 3)) / 3 * 4) + +// Doesn't check for padding at the end. Can be 1-2 bytes over. +NAN_INLINE size_t _nan_base64_decoded_size_fast(size_t size) { + size_t remainder = size % 4; + + size = (size / 4) * 3; + if (remainder) { + if (size == 0 && remainder == 1) { + // special case: 1-byte input cannot be decoded + size = 0; + } else { + // non-padded input, add 1 or 2 extra bytes + size += 1 + (remainder == 3); + } + } + + return size; +} + +template +NAN_INLINE size_t _nan_base64_decoded_size( + const T* src + , size_t size +) { + if (size == 0) + return 0; + + if (src[size - 1] == '=') + size--; + if (size > 0 && src[size - 1] == '=') + size--; + + return _nan_base64_decoded_size_fast(size); +} + +// supports regular and URL-safe base64 +static const int _nan_unbase64_table[] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -1, -1, -2, -1, -1 + , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 + , -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 62, -1, 63 + , 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1 + , -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 + , 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63 + , -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 + , 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 + , -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 + , -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 + , -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 +}; + +#define _nan_unbase64(x) _nan_unbase64_table[(uint8_t)(x)] + +template static size_t _nan_base64_decode( + char* buf + , size_t len + , const T* src + , const size_t srcLen +) { + char* dst = buf; + char* dstEnd = buf + len; + const T* srcEnd = src + srcLen; + + while (src < srcEnd && dst < dstEnd) { + ptrdiff_t remaining = srcEnd - src; + char a, b, c, d; + + while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--; + if (remaining == 0 || *src == '=') break; + a = _nan_unbase64(*src++); + + while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--; + if (remaining <= 1 || *src == '=') break; + b = _nan_unbase64(*src++); + + *dst++ = (a << 2) | ((b & 0x30) >> 4); + if (dst == dstEnd) break; + + while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--; + if (remaining <= 2 || *src == '=') break; + c = _nan_unbase64(*src++); + + *dst++ = ((b & 0x0F) << 4) | ((c & 0x3C) >> 2); + if (dst == dstEnd) break; + + while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--; + if (remaining <= 3 || *src == '=') break; + d = _nan_unbase64(*src++); + + *dst++ = ((c & 0x03) << 6) | (d & 0x3F); + } + + return dst - buf; +} + +//// HEX //// + +template unsigned _nan_hex2bin(T c) { + if (c >= '0' && c <= '9') return c - '0'; + if (c >= 'A' && c <= 'F') return 10 + (c - 'A'); + if (c >= 'a' && c <= 'f') return 10 + (c - 'a'); + return static_cast(-1); +} + +template static size_t _nan_hex_decode( + char* buf + , size_t len + , const T* src + , const size_t srcLen +) { + size_t i; + for (i = 0; i < len && i * 2 + 1 < srcLen; ++i) { + unsigned a = _nan_hex2bin(src[i * 2 + 0]); + unsigned b = _nan_hex2bin(src[i * 2 + 1]); + if (!~a || !~b) return i; + buf[i] = a * 16 + b; + } + + return i; +} + +static bool _NanGetExternalParts( + v8::Handle val + , const char** data + , size_t* len +) { + if (node::Buffer::HasInstance(val)) { + *data = node::Buffer::Data(val.As()); + *len = node::Buffer::Length(val.As()); + return true; + } + + assert(val->IsString()); + v8::Local str = NanNew(val.As()); + + if (str->IsExternalAscii()) { + const v8::String::ExternalAsciiStringResource* ext; + ext = str->GetExternalAsciiStringResource(); + *data = ext->data(); + *len = ext->length(); + return true; + + } else if (str->IsExternal()) { + const v8::String::ExternalStringResource* ext; + ext = str->GetExternalStringResource(); + *data = reinterpret_cast(ext->data()); + *len = ext->length(); + return true; + } + + return false; +} + +namespace Nan { + enum Encoding {ASCII, UTF8, BASE64, UCS2, BINARY, HEX, BUFFER}; +} + +/* NAN_DEPRECATED */ NAN_INLINE void* _NanRawString( + v8::Handle from + , enum Nan::Encoding encoding + , size_t *datalen + , void *buf + , size_t buflen + , int flags +) { + NanScope(); + + size_t sz_; + size_t term_len = !(flags & v8::String::NO_NULL_TERMINATION); + char *data = NULL; + size_t len; + bool is_extern = _NanGetExternalParts( + from + , const_cast(&data) + , &len); + + if (is_extern && !term_len) { + NanSetPointerSafe(datalen, len); + return data; + } + + v8::Local toStr = from->ToString(); + + char *to = static_cast(buf); + + switch (encoding) { + case Nan::ASCII: +#if NODE_MODULE_VERSION < 0x000C + sz_ = toStr->Length(); + if (to == NULL) { + to = new char[sz_ + term_len]; + } else { + assert(buflen >= sz_ + term_len && "too small buffer"); + } + NanSetPointerSafe( + datalen + , toStr->WriteAscii(to, 0, static_cast(sz_ + term_len), flags)); + return to; +#endif + case Nan::BINARY: + case Nan::BUFFER: + sz_ = toStr->Length(); + if (to == NULL) { + to = new char[sz_ + term_len]; + } else { + assert(buflen >= sz_ + term_len && "too small buffer"); + } +#if NODE_MODULE_VERSION < 0x000C + { + uint16_t* twobytebuf = new uint16_t[sz_ + term_len]; + + size_t len = toStr->Write(twobytebuf, 0, + static_cast(sz_ + term_len), flags); + + for (size_t i = 0; i < sz_ + term_len && i < len + term_len; i++) { + unsigned char *b = reinterpret_cast(&twobytebuf[i]); + to[i] = *b; + } + + NanSetPointerSafe(datalen, len); + + delete[] twobytebuf; + return to; + } +#else + NanSetPointerSafe( + datalen, + toStr->WriteOneByte( + reinterpret_cast(to) + , 0 + , static_cast(sz_ + term_len) + , flags)); + return to; +#endif + case Nan::UTF8: + sz_ = toStr->Utf8Length(); + if (to == NULL) { + to = new char[sz_ + term_len]; + } else { + assert(buflen >= sz_ + term_len && "too small buffer"); + } + NanSetPointerSafe( + datalen + , toStr->WriteUtf8(to, static_cast(sz_ + term_len) + , NULL, flags) + - term_len); + return to; + case Nan::BASE64: + { + v8::String::Value value(toStr); + sz_ = _nan_base64_decoded_size(*value, value.length()); + if (to == NULL) { + to = new char[sz_ + term_len]; + } else { + assert(buflen >= sz_ + term_len); + } + NanSetPointerSafe( + datalen + , _nan_base64_decode(to, sz_, *value, value.length())); + if (term_len) { + to[sz_] = '\0'; + } + return to; + } + case Nan::UCS2: + { + sz_ = toStr->Length(); + if (to == NULL) { + to = new char[(sz_ + term_len) * 2]; + } else { + assert(buflen >= (sz_ + term_len) * 2 && "too small buffer"); + } + + int bc = 2 * toStr->Write( + reinterpret_cast(to) + , 0 + , static_cast(sz_ + term_len) + , flags); + NanSetPointerSafe(datalen, bc); + return to; + } + case Nan::HEX: + { + v8::String::Value value(toStr); + sz_ = value.length(); + assert(!(sz_ & 1) && "bad hex data"); + if (to == NULL) { + to = new char[sz_ / 2 + term_len]; + } else { + assert(buflen >= sz_ / 2 + term_len && "too small buffer"); + } + NanSetPointerSafe( + datalen + , _nan_hex_decode(to, sz_ / 2, *value, value.length())); + } + if (term_len) { + to[sz_ / 2] = '\0'; + } + return to; + default: + assert(0 && "unknown encoding"); + } + return to; +} + +NAN_DEPRECATED NAN_INLINE void* NanRawString( + v8::Handle from + , enum Nan::Encoding encoding + , size_t *datalen + , void *buf + , size_t buflen + , int flags +) { + return _NanRawString(from, encoding, datalen, buf, buflen, flags); +} + + +NAN_DEPRECATED NAN_INLINE char* NanCString( + v8::Handle from + , size_t *datalen + , char *buf = NULL + , size_t buflen = 0 + , int flags = v8::String::NO_OPTIONS +) { + return static_cast( + _NanRawString(from, Nan::UTF8, datalen, buf, buflen, flags) + ); +} + +NAN_INLINE void NanSetPrototypeTemplate( + v8::Local templ + , const char *name + , v8::Handle value +) { + NanSetTemplate(templ->PrototypeTemplate(), name, value); +} + +NAN_INLINE void NanSetPrototypeTemplate( + v8::Local templ + , v8::Handle name + , v8::Handle value + , v8::PropertyAttribute attributes +) { + NanSetTemplate(templ->PrototypeTemplate(), name, value, attributes); +} + +NAN_INLINE void NanSetInstanceTemplate( + v8::Local templ + , const char *name + , v8::Handle value +) { + NanSetTemplate(templ->InstanceTemplate(), name, value); +} + +NAN_INLINE void NanSetInstanceTemplate( + v8::Local templ + , v8::Handle name + , v8::Handle value + , v8::PropertyAttribute attributes +) { + NanSetTemplate(templ->InstanceTemplate(), name, value, attributes); +} + +#endif // NAN_H_ diff --git a/node_modules/mongodb/node_modules/bson/node_modules/nan/package.json b/node_modules/mongodb/node_modules/bson/node_modules/nan/package.json new file mode 100644 index 0000000..25a90e8 --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/node_modules/nan/package.json @@ -0,0 +1,79 @@ +{ + "name": "nan", + "version": "1.3.0", + "description": "Native Abstractions for Node.js: C++ header for Node 0.8->0.12 compatibility", + "main": "include_dirs.js", + "repository": { + "type": "git", + "url": "git://github.com/rvagg/nan.git" + }, + "scripts": { + "test": "tap --gc test/js/*-test.js", + "rebuild-tests": "node-gyp rebuild --directory test" + }, + "contributors": [ + { + "name": "Rod Vagg", + "email": "r@va.gg", + "url": "https://github.com/rvagg" + }, + { + "name": "Benjamin Byholm", + "email": "bbyholm@abo.fi", + "url": "https://github.com/kkoopa/" + }, + { + "name": "Trevor Norris", + "email": "trev.norris@gmail.com", + "url": "https://github.com/trevnorris" + }, + { + "name": "Nathan Rajlich", + "email": "nathan@tootallnate.net", + "url": "https://github.com/TooTallNate" + }, + { + "name": "Brett Lawson", + "email": "brett19@gmail.com", + "url": "https://github.com/brett19" + }, + { + "name": "Ben Noordhuis", + "email": "info@bnoordhuis.nl", + "url": "https://github.com/bnoordhuis" + } + ], + "devDependencies": { + "bindings": "~1.2.1", + "node-gyp": "~1.0.1", + "tap": "~0.4.12", + "xtend": "~4.0.0" + }, + "license": "MIT", + "gitHead": "e482fbe142e58373d5a24f4e5a60c61e22a13f83", + "bugs": { + "url": "https://github.com/rvagg/nan/issues" + }, + "homepage": "https://github.com/rvagg/nan", + "_id": "nan@1.3.0", + "_shasum": "9a5b8d5ef97a10df3050e59b2c362d3baf779742", + "_from": "nan@1.3.0", + "_npmVersion": "1.4.21", + "_npmUser": { + "name": "rvagg", + "email": "rod@vagg.org" + }, + "maintainers": [ + { + "name": "rvagg", + "email": "rod@vagg.org" + } + ], + "dist": { + "shasum": "9a5b8d5ef97a10df3050e59b2c362d3baf779742", + "tarball": "http://registry.npmjs.org/nan/-/nan-1.3.0.tgz" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/nan/-/nan-1.3.0.tgz", + "readme": "ERROR: No README data found!" +} diff --git a/node_modules/mongodb/node_modules/bson/package.json b/node_modules/mongodb/node_modules/bson/package.json new file mode 100644 index 0000000..b9c10be --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/package.json @@ -0,0 +1,76 @@ +{ + "name": "bson", + "description": "A bson parser for node.js and the browser", + "keywords": [ + "mongodb", + "bson", + "parser" + ], + "version": "0.2.15", + "author": { + "name": "Christian Amor Kvalheim", + "email": "christkv@gmail.com" + }, + "contributors": [], + "repository": { + "type": "git", + "url": "git://github.com/mongodb/js-bson.git" + }, + "bugs": { + "url": "https://github.com/mongodb/js-bson/issues" + }, + "dependencies": { + "nan": "1.3.0" + }, + "devDependencies": { + "nodeunit": "0.9.0", + "gleak": "0.2.3", + "one": "2.X.X" + }, + "config": { + "native": false + }, + "main": "./lib/bson/index", + "directories": { + "lib": "./lib/bson" + }, + "engines": { + "node": ">=0.6.19" + }, + "scripts": { + "install": "(node-gyp rebuild 2> builderror.log) || (exit 0)", + "test": "nodeunit ./test/node && TEST_NATIVE=TRUE nodeunit ./test/node" + }, + "browser": "lib/bson/bson.js", + "licenses": [ + { + "type": "Apache License, Version 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0" + } + ], + "homepage": "https://github.com/mongodb/js-bson", + "_id": "bson@0.2.15", + "dist": { + "shasum": "556402c74bf33d8008122cc3091dc8b3b90e330c", + "tarball": "http://registry.npmjs.org/bson/-/bson-0.2.15.tgz" + }, + "_from": "bson@~0.2", + "_npmVersion": "1.4.3", + "_npmUser": { + "name": "christkv", + "email": "christkv@gmail.com" + }, + "maintainers": [ + { + "name": "octave", + "email": "chinsay@gmail.com" + }, + { + "name": "christkv", + "email": "christkv@gmail.com" + } + ], + "_shasum": "556402c74bf33d8008122cc3091dc8b3b90e330c", + "_resolved": "https://registry.npmjs.org/bson/-/bson-0.2.15.tgz", + "readme": "ERROR: No README data found!" +} diff --git a/node_modules/mongodb/node_modules/bson/tools/gleak.js b/node_modules/mongodb/node_modules/bson/tools/gleak.js new file mode 100644 index 0000000..c707cfc --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/tools/gleak.js @@ -0,0 +1,21 @@ + +var gleak = require('gleak')(); +gleak.ignore('AssertionError'); +gleak.ignore('testFullSpec_param_found'); +gleak.ignore('events'); +gleak.ignore('Uint8Array'); +gleak.ignore('Uint8ClampedArray'); +gleak.ignore('TAP_Global_Harness'); +gleak.ignore('setImmediate'); +gleak.ignore('clearImmediate'); + +gleak.ignore('DTRACE_NET_SERVER_CONNECTION'); +gleak.ignore('DTRACE_NET_STREAM_END'); +gleak.ignore('DTRACE_NET_SOCKET_READ'); +gleak.ignore('DTRACE_NET_SOCKET_WRITE'); +gleak.ignore('DTRACE_HTTP_SERVER_REQUEST'); +gleak.ignore('DTRACE_HTTP_SERVER_RESPONSE'); +gleak.ignore('DTRACE_HTTP_CLIENT_REQUEST'); +gleak.ignore('DTRACE_HTTP_CLIENT_RESPONSE'); + +module.exports = gleak; diff --git a/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/MIT.LICENSE b/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/MIT.LICENSE new file mode 100644 index 0000000..7c435ba --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/MIT.LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2008-2011 Pivotal Labs + +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/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine-html.js b/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine-html.js new file mode 100644 index 0000000..7383401 --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine-html.js @@ -0,0 +1,190 @@ +jasmine.TrivialReporter = function(doc) { + this.document = doc || document; + this.suiteDivs = {}; + this.logRunningSpecs = false; +}; + +jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) { + var el = document.createElement(type); + + for (var i = 2; i < arguments.length; i++) { + var child = arguments[i]; + + if (typeof child === 'string') { + el.appendChild(document.createTextNode(child)); + } else { + if (child) { el.appendChild(child); } + } + } + + for (var attr in attrs) { + if (attr == "className") { + el[attr] = attrs[attr]; + } else { + el.setAttribute(attr, attrs[attr]); + } + } + + return el; +}; + +jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) { + var showPassed, showSkipped; + + this.outerDiv = this.createDom('div', { className: 'jasmine_reporter' }, + this.createDom('div', { className: 'banner' }, + this.createDom('div', { className: 'logo' }, + this.createDom('span', { className: 'title' }, "Jasmine"), + this.createDom('span', { className: 'version' }, runner.env.versionString())), + this.createDom('div', { className: 'options' }, + "Show ", + showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }), + this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "), + showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }), + this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped") + ) + ), + + this.runnerDiv = this.createDom('div', { className: 'runner running' }, + this.createDom('a', { className: 'run_spec', href: '?' }, "run all"), + this.runnerMessageSpan = this.createDom('span', {}, "Running..."), + this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, "")) + ); + + this.document.body.appendChild(this.outerDiv); + + var suites = runner.suites(); + for (var i = 0; i < suites.length; i++) { + var suite = suites[i]; + var suiteDiv = this.createDom('div', { className: 'suite' }, + this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"), + this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description)); + this.suiteDivs[suite.id] = suiteDiv; + var parentDiv = this.outerDiv; + if (suite.parentSuite) { + parentDiv = this.suiteDivs[suite.parentSuite.id]; + } + parentDiv.appendChild(suiteDiv); + } + + this.startedAt = new Date(); + + var self = this; + showPassed.onclick = function(evt) { + if (showPassed.checked) { + self.outerDiv.className += ' show-passed'; + } else { + self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, ''); + } + }; + + showSkipped.onclick = function(evt) { + if (showSkipped.checked) { + self.outerDiv.className += ' show-skipped'; + } else { + self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, ''); + } + }; +}; + +jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) { + var results = runner.results(); + var className = (results.failedCount > 0) ? "runner failed" : "runner passed"; + this.runnerDiv.setAttribute("class", className); + //do it twice for IE + this.runnerDiv.setAttribute("className", className); + var specs = runner.specs(); + var specCount = 0; + for (var i = 0; i < specs.length; i++) { + if (this.specFilter(specs[i])) { + specCount++; + } + } + var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s"); + message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s"; + this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild); + + this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString())); +}; + +jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) { + var results = suite.results(); + var status = results.passed() ? 'passed' : 'failed'; + if (results.totalCount === 0) { // todo: change this to check results.skipped + status = 'skipped'; + } + this.suiteDivs[suite.id].className += " " + status; +}; + +jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) { + if (this.logRunningSpecs) { + this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...'); + } +}; + +jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) { + var results = spec.results(); + var status = results.passed() ? 'passed' : 'failed'; + if (results.skipped) { + status = 'skipped'; + } + var specDiv = this.createDom('div', { className: 'spec ' + status }, + this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"), + this.createDom('a', { + className: 'description', + href: '?spec=' + encodeURIComponent(spec.getFullName()), + title: spec.getFullName() + }, spec.description)); + + + var resultItems = results.getItems(); + var messagesDiv = this.createDom('div', { className: 'messages' }); + for (var i = 0; i < resultItems.length; i++) { + var result = resultItems[i]; + + if (result.type == 'log') { + messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString())); + } else if (result.type == 'expect' && result.passed && !result.passed()) { + messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message)); + + if (result.trace.stack) { + messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack)); + } + } + } + + if (messagesDiv.childNodes.length > 0) { + specDiv.appendChild(messagesDiv); + } + + this.suiteDivs[spec.suite.id].appendChild(specDiv); +}; + +jasmine.TrivialReporter.prototype.log = function() { + var console = jasmine.getGlobal().console; + if (console && console.log) { + if (console.log.apply) { + console.log.apply(console, arguments); + } else { + console.log(arguments); // ie fix: console.log.apply doesn't exist on ie + } + } +}; + +jasmine.TrivialReporter.prototype.getLocation = function() { + return this.document.location; +}; + +jasmine.TrivialReporter.prototype.specFilter = function(spec) { + var paramMap = {}; + var params = this.getLocation().search.substring(1).split('&'); + for (var i = 0; i < params.length; i++) { + var p = params[i].split('='); + paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]); + } + + if (!paramMap.spec) { + return true; + } + return spec.getFullName().indexOf(paramMap.spec) === 0; +}; diff --git a/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine.css b/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine.css new file mode 100644 index 0000000..6583fe7 --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine.css @@ -0,0 +1,166 @@ +body { + font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; +} + + +.jasmine_reporter a:visited, .jasmine_reporter a { + color: #303; +} + +.jasmine_reporter a:hover, .jasmine_reporter a:active { + color: blue; +} + +.run_spec { + float:right; + padding-right: 5px; + font-size: .8em; + text-decoration: none; +} + +.jasmine_reporter { + margin: 0 5px; +} + +.banner { + color: #303; + background-color: #fef; + padding: 5px; +} + +.logo { + float: left; + font-size: 1.1em; + padding-left: 5px; +} + +.logo .version { + font-size: .6em; + padding-left: 1em; +} + +.runner.running { + background-color: yellow; +} + + +.options { + text-align: right; + font-size: .8em; +} + + + + +.suite { + border: 1px outset gray; + margin: 5px 0; + padding-left: 1em; +} + +.suite .suite { + margin: 5px; +} + +.suite.passed { + background-color: #dfd; +} + +.suite.failed { + background-color: #fdd; +} + +.spec { + margin: 5px; + padding-left: 1em; + clear: both; +} + +.spec.failed, .spec.passed, .spec.skipped { + padding-bottom: 5px; + border: 1px solid gray; +} + +.spec.failed { + background-color: #fbb; + border-color: red; +} + +.spec.passed { + background-color: #bfb; + border-color: green; +} + +.spec.skipped { + background-color: #bbb; +} + +.messages { + border-left: 1px dashed gray; + padding-left: 1em; + padding-right: 1em; +} + +.passed { + background-color: #cfc; + display: none; +} + +.failed { + background-color: #fbb; +} + +.skipped { + color: #777; + background-color: #eee; + display: none; +} + + +/*.resultMessage {*/ + /*white-space: pre;*/ +/*}*/ + +.resultMessage span.result { + display: block; + line-height: 2em; + color: black; +} + +.resultMessage .mismatch { + color: black; +} + +.stackTrace { + white-space: pre; + font-size: .8em; + margin-left: 10px; + max-height: 5em; + overflow: auto; + border: 1px inset red; + padding: 1em; + background: #eef; +} + +.finished-at { + padding-left: 1em; + font-size: .6em; +} + +.show-passed .passed, +.show-skipped .skipped { + display: block; +} + + +#jasmine_content { + position:fixed; + right: 100%; +} + +.runner { + border: 1px solid gray; + display: block; + margin: 5px 0; + padding: 2px 0 2px 10px; +} diff --git a/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine.js b/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine.js new file mode 100644 index 0000000..c3d2dc7 --- /dev/null +++ b/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine.js @@ -0,0 +1,2476 @@ +var isCommonJS = typeof window == "undefined"; + +/** + * Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework. + * + * @namespace + */ +var jasmine = {}; +if (isCommonJS) exports.jasmine = jasmine; +/** + * @private + */ +jasmine.unimplementedMethod_ = function() { + throw new Error("unimplemented method"); +}; + +/** + * Use jasmine.undefined instead of undefined, since undefined is just + * a plain old variable and may be redefined by somebody else. + * + * @private + */ +jasmine.undefined = jasmine.___undefined___; + +/** + * Show diagnostic messages in the console if set to true + * + */ +jasmine.VERBOSE = false; + +/** + * Default interval in milliseconds for event loop yields (e.g. to allow network activity or to refresh the screen with the HTML-based runner). Small values here may result in slow test running. Zero means no updates until all tests have completed. + * + */ +jasmine.DEFAULT_UPDATE_INTERVAL = 250; + +/** + * Default timeout interval in milliseconds for waitsFor() blocks. + */ +jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000; + +jasmine.getGlobal = function() { + function getGlobal() { + return this; + } + + return getGlobal(); +}; + +/** + * Allows for bound functions to be compared. Internal use only. + * + * @ignore + * @private + * @param base {Object} bound 'this' for the function + * @param name {Function} function to find + */ +jasmine.bindOriginal_ = function(base, name) { + var original = base[name]; + if (original.apply) { + return function() { + return original.apply(base, arguments); + }; + } else { + // IE support + return jasmine.getGlobal()[name]; + } +}; + +jasmine.setTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'setTimeout'); +jasmine.clearTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearTimeout'); +jasmine.setInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'setInterval'); +jasmine.clearInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearInterval'); + +jasmine.MessageResult = function(values) { + this.type = 'log'; + this.values = values; + this.trace = new Error(); // todo: test better +}; + +jasmine.MessageResult.prototype.toString = function() { + var text = ""; + for (var i = 0; i < this.values.length; i++) { + if (i > 0) text += " "; + if (jasmine.isString_(this.values[i])) { + text += this.values[i]; + } else { + text += jasmine.pp(this.values[i]); + } + } + return text; +}; + +jasmine.ExpectationResult = function(params) { + this.type = 'expect'; + this.matcherName = params.matcherName; + this.passed_ = params.passed; + this.expected = params.expected; + this.actual = params.actual; + this.message = this.passed_ ? 'Passed.' : params.message; + + var trace = (params.trace || new Error(this.message)); + this.trace = this.passed_ ? '' : trace; +}; + +jasmine.ExpectationResult.prototype.toString = function () { + return this.message; +}; + +jasmine.ExpectationResult.prototype.passed = function () { + return this.passed_; +}; + +/** + * Getter for the Jasmine environment. Ensures one gets created + */ +jasmine.getEnv = function() { + var env = jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env(); + return env; +}; + +/** + * @ignore + * @private + * @param value + * @returns {Boolean} + */ +jasmine.isArray_ = function(value) { + return jasmine.isA_("Array", value); +}; + +/** + * @ignore + * @private + * @param value + * @returns {Boolean} + */ +jasmine.isString_ = function(value) { + return jasmine.isA_("String", value); +}; + +/** + * @ignore + * @private + * @param value + * @returns {Boolean} + */ +jasmine.isNumber_ = function(value) { + return jasmine.isA_("Number", value); +}; + +/** + * @ignore + * @private + * @param {String} typeName + * @param value + * @returns {Boolean} + */ +jasmine.isA_ = function(typeName, value) { + return Object.prototype.toString.apply(value) === '[object ' + typeName + ']'; +}; + +/** + * Pretty printer for expecations. Takes any object and turns it into a human-readable string. + * + * @param value {Object} an object to be outputted + * @returns {String} + */ +jasmine.pp = function(value) { + var stringPrettyPrinter = new jasmine.StringPrettyPrinter(); + stringPrettyPrinter.format(value); + return stringPrettyPrinter.string; +}; + +/** + * Returns true if the object is a DOM Node. + * + * @param {Object} obj object to check + * @returns {Boolean} + */ +jasmine.isDomNode = function(obj) { + return obj.nodeType > 0; +}; + +/** + * Returns a matchable 'generic' object of the class type. For use in expecations of type when values don't matter. + * + * @example + * // don't care about which function is passed in, as long as it's a function + * expect(mySpy).toHaveBeenCalledWith(jasmine.any(Function)); + * + * @param {Class} clazz + * @returns matchable object of the type clazz + */ +jasmine.any = function(clazz) { + return new jasmine.Matchers.Any(clazz); +}; + +/** + * Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks. + * + * Spies should be created in test setup, before expectations. They can then be checked, using the standard Jasmine + * expectation syntax. Spies can be checked if they were called or not and what the calling params were. + * + * A Spy has the following fields: wasCalled, callCount, mostRecentCall, and argsForCall (see docs). + * + * Spies are torn down at the end of every spec. + * + * Note: Do not call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj. + * + * @example + * // a stub + * var myStub = jasmine.createSpy('myStub'); // can be used anywhere + * + * // spy example + * var foo = { + * not: function(bool) { return !bool; } + * } + * + * // actual foo.not will not be called, execution stops + * spyOn(foo, 'not'); + + // foo.not spied upon, execution will continue to implementation + * spyOn(foo, 'not').andCallThrough(); + * + * // fake example + * var foo = { + * not: function(bool) { return !bool; } + * } + * + * // foo.not(val) will return val + * spyOn(foo, 'not').andCallFake(function(value) {return value;}); + * + * // mock example + * foo.not(7 == 7); + * expect(foo.not).toHaveBeenCalled(); + * expect(foo.not).toHaveBeenCalledWith(true); + * + * @constructor + * @see spyOn, jasmine.createSpy, jasmine.createSpyObj + * @param {String} name + */ +jasmine.Spy = function(name) { + /** + * The name of the spy, if provided. + */ + this.identity = name || 'unknown'; + /** + * Is this Object a spy? + */ + this.isSpy = true; + /** + * The actual function this spy stubs. + */ + this.plan = function() { + }; + /** + * Tracking of the most recent call to the spy. + * @example + * var mySpy = jasmine.createSpy('foo'); + * mySpy(1, 2); + * mySpy.mostRecentCall.args = [1, 2]; + */ + this.mostRecentCall = {}; + + /** + * Holds arguments for each call to the spy, indexed by call count + * @example + * var mySpy = jasmine.createSpy('foo'); + * mySpy(1, 2); + * mySpy(7, 8); + * mySpy.mostRecentCall.args = [7, 8]; + * mySpy.argsForCall[0] = [1, 2]; + * mySpy.argsForCall[1] = [7, 8]; + */ + this.argsForCall = []; + this.calls = []; +}; + +/** + * Tells a spy to call through to the actual implemenatation. + * + * @example + * var foo = { + * bar: function() { // do some stuff } + * } + * + * // defining a spy on an existing property: foo.bar + * spyOn(foo, 'bar').andCallThrough(); + */ +jasmine.Spy.prototype.andCallThrough = function() { + this.plan = this.originalValue; + return this; +}; + +/** + * For setting the return value of a spy. + * + * @example + * // defining a spy from scratch: foo() returns 'baz' + * var foo = jasmine.createSpy('spy on foo').andReturn('baz'); + * + * // defining a spy on an existing property: foo.bar() returns 'baz' + * spyOn(foo, 'bar').andReturn('baz'); + * + * @param {Object} value + */ +jasmine.Spy.prototype.andReturn = function(value) { + this.plan = function() { + return value; + }; + return this; +}; + +/** + * For throwing an exception when a spy is called. + * + * @example + * // defining a spy from scratch: foo() throws an exception w/ message 'ouch' + * var foo = jasmine.createSpy('spy on foo').andThrow('baz'); + * + * // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch' + * spyOn(foo, 'bar').andThrow('baz'); + * + * @param {String} exceptionMsg + */ +jasmine.Spy.prototype.andThrow = function(exceptionMsg) { + this.plan = function() { + throw exceptionMsg; + }; + return this; +}; + +/** + * Calls an alternate implementation when a spy is called. + * + * @example + * var baz = function() { + * // do some stuff, return something + * } + * // defining a spy from scratch: foo() calls the function baz + * var foo = jasmine.createSpy('spy on foo').andCall(baz); + * + * // defining a spy on an existing property: foo.bar() calls an anonymnous function + * spyOn(foo, 'bar').andCall(function() { return 'baz';} ); + * + * @param {Function} fakeFunc + */ +jasmine.Spy.prototype.andCallFake = function(fakeFunc) { + this.plan = fakeFunc; + return this; +}; + +/** + * Resets all of a spy's the tracking variables so that it can be used again. + * + * @example + * spyOn(foo, 'bar'); + * + * foo.bar(); + * + * expect(foo.bar.callCount).toEqual(1); + * + * foo.bar.reset(); + * + * expect(foo.bar.callCount).toEqual(0); + */ +jasmine.Spy.prototype.reset = function() { + this.wasCalled = false; + this.callCount = 0; + this.argsForCall = []; + this.calls = []; + this.mostRecentCall = {}; +}; + +jasmine.createSpy = function(name) { + + var spyObj = function() { + spyObj.wasCalled = true; + spyObj.callCount++; + var args = jasmine.util.argsToArray(arguments); + spyObj.mostRecentCall.object = this; + spyObj.mostRecentCall.args = args; + spyObj.argsForCall.push(args); + spyObj.calls.push({object: this, args: args}); + return spyObj.plan.apply(this, arguments); + }; + + var spy = new jasmine.Spy(name); + + for (var prop in spy) { + spyObj[prop] = spy[prop]; + } + + spyObj.reset(); + + return spyObj; +}; + +/** + * Determines whether an object is a spy. + * + * @param {jasmine.Spy|Object} putativeSpy + * @returns {Boolean} + */ +jasmine.isSpy = function(putativeSpy) { + return putativeSpy && putativeSpy.isSpy; +}; + +/** + * Creates a more complicated spy: an Object that has every property a function that is a spy. Used for stubbing something + * large in one call. + * + * @param {String} baseName name of spy class + * @param {Array} methodNames array of names of methods to make spies + */ +jasmine.createSpyObj = function(baseName, methodNames) { + if (!jasmine.isArray_(methodNames) || methodNames.length === 0) { + throw new Error('createSpyObj requires a non-empty array of method names to create spies for'); + } + var obj = {}; + for (var i = 0; i < methodNames.length; i++) { + obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]); + } + return obj; +}; + +/** + * All parameters are pretty-printed and concatenated together, then written to the current spec's output. + * + * Be careful not to leave calls to jasmine.log in production code. + */ +jasmine.log = function() { + var spec = jasmine.getEnv().currentSpec; + spec.log.apply(spec, arguments); +}; + +/** + * Function that installs a spy on an existing object's method name. Used within a Spec to create a spy. + * + * @example + * // spy example + * var foo = { + * not: function(bool) { return !bool; } + * } + * spyOn(foo, 'not'); // actual foo.not will not be called, execution stops + * + * @see jasmine.createSpy + * @param obj + * @param methodName + * @returns a Jasmine spy that can be chained with all spy methods + */ +var spyOn = function(obj, methodName) { + return jasmine.getEnv().currentSpec.spyOn(obj, methodName); +}; +if (isCommonJS) exports.spyOn = spyOn; + +/** + * Creates a Jasmine spec that will be added to the current suite. + * + * // TODO: pending tests + * + * @example + * it('should be true', function() { + * expect(true).toEqual(true); + * }); + * + * @param {String} desc description of this specification + * @param {Function} func defines the preconditions and expectations of the spec + */ +var it = function(desc, func) { + return jasmine.getEnv().it(desc, func); +}; +if (isCommonJS) exports.it = it; + +/** + * Creates a disabled Jasmine spec. + * + * A convenience method that allows existing specs to be disabled temporarily during development. + * + * @param {String} desc description of this specification + * @param {Function} func defines the preconditions and expectations of the spec + */ +var xit = function(desc, func) { + return jasmine.getEnv().xit(desc, func); +}; +if (isCommonJS) exports.xit = xit; + +/** + * Starts a chain for a Jasmine expectation. + * + * It is passed an Object that is the actual value and should chain to one of the many + * jasmine.Matchers functions. + * + * @param {Object} actual Actual value to test against and expected value + */ +var expect = function(actual) { + return jasmine.getEnv().currentSpec.expect(actual); +}; +if (isCommonJS) exports.expect = expect; + +/** + * Defines part of a jasmine spec. Used in cominbination with waits or waitsFor in asynchrnous specs. + * + * @param {Function} func Function that defines part of a jasmine spec. + */ +var runs = function(func) { + jasmine.getEnv().currentSpec.runs(func); +}; +if (isCommonJS) exports.runs = runs; + +/** + * Waits a fixed time period before moving to the next block. + * + * @deprecated Use waitsFor() instead + * @param {Number} timeout milliseconds to wait + */ +var waits = function(timeout) { + jasmine.getEnv().currentSpec.waits(timeout); +}; +if (isCommonJS) exports.waits = waits; + +/** + * Waits for the latchFunction to return true before proceeding to the next block. + * + * @param {Function} latchFunction + * @param {String} optional_timeoutMessage + * @param {Number} optional_timeout + */ +var waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) { + jasmine.getEnv().currentSpec.waitsFor.apply(jasmine.getEnv().currentSpec, arguments); +}; +if (isCommonJS) exports.waitsFor = waitsFor; + +/** + * A function that is called before each spec in a suite. + * + * Used for spec setup, including validating assumptions. + * + * @param {Function} beforeEachFunction + */ +var beforeEach = function(beforeEachFunction) { + jasmine.getEnv().beforeEach(beforeEachFunction); +}; +if (isCommonJS) exports.beforeEach = beforeEach; + +/** + * A function that is called after each spec in a suite. + * + * Used for restoring any state that is hijacked during spec execution. + * + * @param {Function} afterEachFunction + */ +var afterEach = function(afterEachFunction) { + jasmine.getEnv().afterEach(afterEachFunction); +}; +if (isCommonJS) exports.afterEach = afterEach; + +/** + * Defines a suite of specifications. + * + * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared + * are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization + * of setup in some tests. + * + * @example + * // TODO: a simple suite + * + * // TODO: a simple suite with a nested describe block + * + * @param {String} description A string, usually the class under test. + * @param {Function} specDefinitions function that defines several specs. + */ +var describe = function(description, specDefinitions) { + return jasmine.getEnv().describe(description, specDefinitions); +}; +if (isCommonJS) exports.describe = describe; + +/** + * Disables a suite of specifications. Used to disable some suites in a file, or files, temporarily during development. + * + * @param {String} description A string, usually the class under test. + * @param {Function} specDefinitions function that defines several specs. + */ +var xdescribe = function(description, specDefinitions) { + return jasmine.getEnv().xdescribe(description, specDefinitions); +}; +if (isCommonJS) exports.xdescribe = xdescribe; + + +// Provide the XMLHttpRequest class for IE 5.x-6.x: +jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() { + function tryIt(f) { + try { + return f(); + } catch(e) { + } + return null; + } + + var xhr = tryIt(function() { + return new ActiveXObject("Msxml2.XMLHTTP.6.0"); + }) || + tryIt(function() { + return new ActiveXObject("Msxml2.XMLHTTP.3.0"); + }) || + tryIt(function() { + return new ActiveXObject("Msxml2.XMLHTTP"); + }) || + tryIt(function() { + return new ActiveXObject("Microsoft.XMLHTTP"); + }); + + if (!xhr) throw new Error("This browser does not support XMLHttpRequest."); + + return xhr; +} : XMLHttpRequest; +/** + * @namespace + */ +jasmine.util = {}; + +/** + * Declare that a child class inherit it's prototype from the parent class. + * + * @private + * @param {Function} childClass + * @param {Function} parentClass + */ +jasmine.util.inherit = function(childClass, parentClass) { + /** + * @private + */ + var subclass = function() { + }; + subclass.prototype = parentClass.prototype; + childClass.prototype = new subclass(); +}; + +jasmine.util.formatException = function(e) { + var lineNumber; + if (e.line) { + lineNumber = e.line; + } + else if (e.lineNumber) { + lineNumber = e.lineNumber; + } + + var file; + + if (e.sourceURL) { + file = e.sourceURL; + } + else if (e.fileName) { + file = e.fileName; + } + + var message = (e.name && e.message) ? (e.name + ': ' + e.message) : e.toString(); + + if (file && lineNumber) { + message += ' in ' + file + ' (line ' + lineNumber + ')'; + } + + return message; +}; + +jasmine.util.htmlEscape = function(str) { + if (!str) return str; + return str.replace(/&/g, '&') + .replace(//g, '>'); +}; + +jasmine.util.argsToArray = function(args) { + var arrayOfArgs = []; + for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]); + return arrayOfArgs; +}; + +jasmine.util.extend = function(destination, source) { + for (var property in source) destination[property] = source[property]; + return destination; +}; + +/** + * Environment for Jasmine + * + * @constructor + */ +jasmine.Env = function() { + this.currentSpec = null; + this.currentSuite = null; + this.currentRunner_ = new jasmine.Runner(this); + + this.reporter = new jasmine.MultiReporter(); + + this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL; + this.defaultTimeoutInterval = jasmine.DEFAULT_TIMEOUT_INTERVAL; + this.lastUpdate = 0; + this.specFilter = function() { + return true; + }; + + this.nextSpecId_ = 0; + this.nextSuiteId_ = 0; + this.equalityTesters_ = []; + + // wrap matchers + this.matchersClass = function() { + jasmine.Matchers.apply(this, arguments); + }; + jasmine.util.inherit(this.matchersClass, jasmine.Matchers); + + jasmine.Matchers.wrapInto_(jasmine.Matchers.prototype, this.matchersClass); +}; + + +jasmine.Env.prototype.setTimeout = jasmine.setTimeout; +jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout; +jasmine.Env.prototype.setInterval = jasmine.setInterval; +jasmine.Env.prototype.clearInterval = jasmine.clearInterval; + +/** + * @returns an object containing jasmine version build info, if set. + */ +jasmine.Env.prototype.version = function () { + if (jasmine.version_) { + return jasmine.version_; + } else { + throw new Error('Version not set'); + } +}; + +/** + * @returns string containing jasmine version build info, if set. + */ +jasmine.Env.prototype.versionString = function() { + if (!jasmine.version_) { + return "version unknown"; + } + + var version = this.version(); + var versionString = version.major + "." + version.minor + "." + version.build; + if (version.release_candidate) { + versionString += ".rc" + version.release_candidate; + } + versionString += " revision " + version.revision; + return versionString; +}; + +/** + * @returns a sequential integer starting at 0 + */ +jasmine.Env.prototype.nextSpecId = function () { + return this.nextSpecId_++; +}; + +/** + * @returns a sequential integer starting at 0 + */ +jasmine.Env.prototype.nextSuiteId = function () { + return this.nextSuiteId_++; +}; + +/** + * Register a reporter to receive status updates from Jasmine. + * @param {jasmine.Reporter} reporter An object which will receive status updates. + */ +jasmine.Env.prototype.addReporter = function(reporter) { + this.reporter.addReporter(reporter); +}; + +jasmine.Env.prototype.execute = function() { + this.currentRunner_.execute(); +}; + +jasmine.Env.prototype.describe = function(description, specDefinitions) { + var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite); + + var parentSuite = this.currentSuite; + if (parentSuite) { + parentSuite.add(suite); + } else { + this.currentRunner_.add(suite); + } + + this.currentSuite = suite; + + var declarationError = null; + try { + specDefinitions.call(suite); + } catch(e) { + declarationError = e; + } + + if (declarationError) { + this.it("encountered a declaration exception", function() { + throw declarationError; + }); + } + + this.currentSuite = parentSuite; + + return suite; +}; + +jasmine.Env.prototype.beforeEach = function(beforeEachFunction) { + if (this.currentSuite) { + this.currentSuite.beforeEach(beforeEachFunction); + } else { + this.currentRunner_.beforeEach(beforeEachFunction); + } +}; + +jasmine.Env.prototype.currentRunner = function () { + return this.currentRunner_; +}; + +jasmine.Env.prototype.afterEach = function(afterEachFunction) { + if (this.currentSuite) { + this.currentSuite.afterEach(afterEachFunction); + } else { + this.currentRunner_.afterEach(afterEachFunction); + } + +}; + +jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) { + return { + execute: function() { + } + }; +}; + +jasmine.Env.prototype.it = function(description, func) { + var spec = new jasmine.Spec(this, this.currentSuite, description); + this.currentSuite.add(spec); + this.currentSpec = spec; + + if (func) { + spec.runs(func); + } + + return spec; +}; + +jasmine.Env.prototype.xit = function(desc, func) { + return { + id: this.nextSpecId(), + runs: function() { + } + }; +}; + +jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) { + if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) { + return true; + } + + a.__Jasmine_been_here_before__ = b; + b.__Jasmine_been_here_before__ = a; + + var hasKey = function(obj, keyName) { + return obj !== null && obj[keyName] !== jasmine.undefined; + }; + + for (var property in b) { + if (!hasKey(a, property) && hasKey(b, property)) { + mismatchKeys.push("expected has key '" + property + "', but missing from actual."); + } + } + for (property in a) { + if (!hasKey(b, property) && hasKey(a, property)) { + mismatchKeys.push("expected missing key '" + property + "', but present in actual."); + } + } + for (property in b) { + if (property == '__Jasmine_been_here_before__') continue; + if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) { + mismatchValues.push("'" + property + "' was '" + (b[property] ? jasmine.util.htmlEscape(b[property].toString()) : b[property]) + "' in expected, but was '" + (a[property] ? jasmine.util.htmlEscape(a[property].toString()) : a[property]) + "' in actual."); + } + } + + if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) { + mismatchValues.push("arrays were not the same length"); + } + + delete a.__Jasmine_been_here_before__; + delete b.__Jasmine_been_here_before__; + return (mismatchKeys.length === 0 && mismatchValues.length === 0); +}; + +jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) { + mismatchKeys = mismatchKeys || []; + mismatchValues = mismatchValues || []; + + for (var i = 0; i < this.equalityTesters_.length; i++) { + var equalityTester = this.equalityTesters_[i]; + var result = equalityTester(a, b, this, mismatchKeys, mismatchValues); + if (result !== jasmine.undefined) return result; + } + + if (a === b) return true; + + if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null) { + return (a == jasmine.undefined && b == jasmine.undefined); + } + + if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) { + return a === b; + } + + if (a instanceof Date && b instanceof Date) { + return a.getTime() == b.getTime(); + } + + if (a instanceof jasmine.Matchers.Any) { + return a.matches(b); + } + + if (b instanceof jasmine.Matchers.Any) { + return b.matches(a); + } + + if (jasmine.isString_(a) && jasmine.isString_(b)) { + return (a == b); + } + + if (jasmine.isNumber_(a) && jasmine.isNumber_(b)) { + return (a == b); + } + + if (typeof a === "object" && typeof b === "object") { + return this.compareObjects_(a, b, mismatchKeys, mismatchValues); + } + + //Straight check + return (a === b); +}; + +jasmine.Env.prototype.contains_ = function(haystack, needle) { + if (jasmine.isArray_(haystack)) { + for (var i = 0; i < haystack.length; i++) { + if (this.equals_(haystack[i], needle)) return true; + } + return false; + } + return haystack.indexOf(needle) >= 0; +}; + +jasmine.Env.prototype.addEqualityTester = function(equalityTester) { + this.equalityTesters_.push(equalityTester); +}; +/** No-op base class for Jasmine reporters. + * + * @constructor + */ +jasmine.Reporter = function() { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportRunnerStarting = function(runner) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportRunnerResults = function(runner) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportSuiteResults = function(suite) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportSpecStarting = function(spec) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportSpecResults = function(spec) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.log = function(str) { +}; + +/** + * Blocks are functions with executable code that make up a spec. + * + * @constructor + * @param {jasmine.Env} env + * @param {Function} func + * @param {jasmine.Spec} spec + */ +jasmine.Block = function(env, func, spec) { + this.env = env; + this.func = func; + this.spec = spec; +}; + +jasmine.Block.prototype.execute = function(onComplete) { + try { + this.func.apply(this.spec); + } catch (e) { + this.spec.fail(e); + } + onComplete(); +}; +/** JavaScript API reporter. + * + * @constructor + */ +jasmine.JsApiReporter = function() { + this.started = false; + this.finished = false; + this.suites_ = []; + this.results_ = {}; +}; + +jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) { + this.started = true; + var suites = runner.topLevelSuites(); + for (var i = 0; i < suites.length; i++) { + var suite = suites[i]; + this.suites_.push(this.summarize_(suite)); + } +}; + +jasmine.JsApiReporter.prototype.suites = function() { + return this.suites_; +}; + +jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) { + var isSuite = suiteOrSpec instanceof jasmine.Suite; + var summary = { + id: suiteOrSpec.id, + name: suiteOrSpec.description, + type: isSuite ? 'suite' : 'spec', + children: [] + }; + + if (isSuite) { + var children = suiteOrSpec.children(); + for (var i = 0; i < children.length; i++) { + summary.children.push(this.summarize_(children[i])); + } + } + return summary; +}; + +jasmine.JsApiReporter.prototype.results = function() { + return this.results_; +}; + +jasmine.JsApiReporter.prototype.resultsForSpec = function(specId) { + return this.results_[specId]; +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) { + this.finished = true; +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) { + this.results_[spec.id] = { + messages: spec.results().getItems(), + result: spec.results().failedCount > 0 ? "failed" : "passed" + }; +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.log = function(str) { +}; + +jasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){ + var results = {}; + for (var i = 0; i < specIds.length; i++) { + var specId = specIds[i]; + results[specId] = this.summarizeResult_(this.results_[specId]); + } + return results; +}; + +jasmine.JsApiReporter.prototype.summarizeResult_ = function(result){ + var summaryMessages = []; + var messagesLength = result.messages.length; + for (var messageIndex = 0; messageIndex < messagesLength; messageIndex++) { + var resultMessage = result.messages[messageIndex]; + summaryMessages.push({ + text: resultMessage.type == 'log' ? resultMessage.toString() : jasmine.undefined, + passed: resultMessage.passed ? resultMessage.passed() : true, + type: resultMessage.type, + message: resultMessage.message, + trace: { + stack: resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack : jasmine.undefined + } + }); + } + + return { + result : result.result, + messages : summaryMessages + }; +}; + +/** + * @constructor + * @param {jasmine.Env} env + * @param actual + * @param {jasmine.Spec} spec + */ +jasmine.Matchers = function(env, actual, spec, opt_isNot) { + this.env = env; + this.actual = actual; + this.spec = spec; + this.isNot = opt_isNot || false; + this.reportWasCalled_ = false; +}; + +// todo: @deprecated as of Jasmine 0.11, remove soon [xw] +jasmine.Matchers.pp = function(str) { + throw new Error("jasmine.Matchers.pp() is no longer supported, please use jasmine.pp() instead!"); +}; + +// todo: @deprecated Deprecated as of Jasmine 0.10. Rewrite your custom matchers to return true or false. [xw] +jasmine.Matchers.prototype.report = function(result, failing_message, details) { + throw new Error("As of jasmine 0.11, custom matchers must be implemented differently -- please see jasmine docs"); +}; + +jasmine.Matchers.wrapInto_ = function(prototype, matchersClass) { + for (var methodName in prototype) { + if (methodName == 'report') continue; + var orig = prototype[methodName]; + matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName, orig); + } +}; + +jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) { + return function() { + var matcherArgs = jasmine.util.argsToArray(arguments); + var result = matcherFunction.apply(this, arguments); + + if (this.isNot) { + result = !result; + } + + if (this.reportWasCalled_) return result; + + var message; + if (!result) { + if (this.message) { + message = this.message.apply(this, arguments); + if (jasmine.isArray_(message)) { + message = message[this.isNot ? 1 : 0]; + } + } else { + var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); }); + message = "Expected " + jasmine.pp(this.actual) + (this.isNot ? " not " : " ") + englishyPredicate; + if (matcherArgs.length > 0) { + for (var i = 0; i < matcherArgs.length; i++) { + if (i > 0) message += ","; + message += " " + jasmine.pp(matcherArgs[i]); + } + } + message += "."; + } + } + var expectationResult = new jasmine.ExpectationResult({ + matcherName: matcherName, + passed: result, + expected: matcherArgs.length > 1 ? matcherArgs : matcherArgs[0], + actual: this.actual, + message: message + }); + this.spec.addMatcherResult(expectationResult); + return jasmine.undefined; + }; +}; + + + + +/** + * toBe: compares the actual to the expected using === + * @param expected + */ +jasmine.Matchers.prototype.toBe = function(expected) { + return this.actual === expected; +}; + +/** + * toNotBe: compares the actual to the expected using !== + * @param expected + * @deprecated as of 1.0. Use not.toBe() instead. + */ +jasmine.Matchers.prototype.toNotBe = function(expected) { + return this.actual !== expected; +}; + +/** + * toEqual: compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc. + * + * @param expected + */ +jasmine.Matchers.prototype.toEqual = function(expected) { + return this.env.equals_(this.actual, expected); +}; + +/** + * toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual + * @param expected + * @deprecated as of 1.0. Use not.toNotEqual() instead. + */ +jasmine.Matchers.prototype.toNotEqual = function(expected) { + return !this.env.equals_(this.actual, expected); +}; + +/** + * Matcher that compares the actual to the expected using a regular expression. Constructs a RegExp, so takes + * a pattern or a String. + * + * @param expected + */ +jasmine.Matchers.prototype.toMatch = function(expected) { + return new RegExp(expected).test(this.actual); +}; + +/** + * Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch + * @param expected + * @deprecated as of 1.0. Use not.toMatch() instead. + */ +jasmine.Matchers.prototype.toNotMatch = function(expected) { + return !(new RegExp(expected).test(this.actual)); +}; + +/** + * Matcher that compares the actual to jasmine.undefined. + */ +jasmine.Matchers.prototype.toBeDefined = function() { + return (this.actual !== jasmine.undefined); +}; + +/** + * Matcher that compares the actual to jasmine.undefined. + */ +jasmine.Matchers.prototype.toBeUndefined = function() { + return (this.actual === jasmine.undefined); +}; + +/** + * Matcher that compares the actual to null. + */ +jasmine.Matchers.prototype.toBeNull = function() { + return (this.actual === null); +}; + +/** + * Matcher that boolean not-nots the actual. + */ +jasmine.Matchers.prototype.toBeTruthy = function() { + return !!this.actual; +}; + + +/** + * Matcher that boolean nots the actual. + */ +jasmine.Matchers.prototype.toBeFalsy = function() { + return !this.actual; +}; + + +/** + * Matcher that checks to see if the actual, a Jasmine spy, was called. + */ +jasmine.Matchers.prototype.toHaveBeenCalled = function() { + if (arguments.length > 0) { + throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith'); + } + + if (!jasmine.isSpy(this.actual)) { + throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + } + + this.message = function() { + return [ + "Expected spy " + this.actual.identity + " to have been called.", + "Expected spy " + this.actual.identity + " not to have been called." + ]; + }; + + return this.actual.wasCalled; +}; + +/** @deprecated Use expect(xxx).toHaveBeenCalled() instead */ +jasmine.Matchers.prototype.wasCalled = jasmine.Matchers.prototype.toHaveBeenCalled; + +/** + * Matcher that checks to see if the actual, a Jasmine spy, was not called. + * + * @deprecated Use expect(xxx).not.toHaveBeenCalled() instead + */ +jasmine.Matchers.prototype.wasNotCalled = function() { + if (arguments.length > 0) { + throw new Error('wasNotCalled does not take arguments'); + } + + if (!jasmine.isSpy(this.actual)) { + throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + } + + this.message = function() { + return [ + "Expected spy " + this.actual.identity + " to not have been called.", + "Expected spy " + this.actual.identity + " to have been called." + ]; + }; + + return !this.actual.wasCalled; +}; + +/** + * Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters. + * + * @example + * + */ +jasmine.Matchers.prototype.toHaveBeenCalledWith = function() { + var expectedArgs = jasmine.util.argsToArray(arguments); + if (!jasmine.isSpy(this.actual)) { + throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + } + this.message = function() { + if (this.actual.callCount === 0) { + // todo: what should the failure message for .not.toHaveBeenCalledWith() be? is this right? test better. [xw] + return [ + "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.", + "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but it was." + ]; + } else { + return [ + "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall), + "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall) + ]; + } + }; + + return this.env.contains_(this.actual.argsForCall, expectedArgs); +}; + +/** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */ +jasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.prototype.toHaveBeenCalledWith; + +/** @deprecated Use expect(xxx).not.toHaveBeenCalledWith() instead */ +jasmine.Matchers.prototype.wasNotCalledWith = function() { + var expectedArgs = jasmine.util.argsToArray(arguments); + if (!jasmine.isSpy(this.actual)) { + throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + } + + this.message = function() { + return [ + "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was", + "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was" + ]; + }; + + return !this.env.contains_(this.actual.argsForCall, expectedArgs); +}; + +/** + * Matcher that checks that the expected item is an element in the actual Array. + * + * @param {Object} expected + */ +jasmine.Matchers.prototype.toContain = function(expected) { + return this.env.contains_(this.actual, expected); +}; + +/** + * Matcher that checks that the expected item is NOT an element in the actual Array. + * + * @param {Object} expected + * @deprecated as of 1.0. Use not.toNotContain() instead. + */ +jasmine.Matchers.prototype.toNotContain = function(expected) { + return !this.env.contains_(this.actual, expected); +}; + +jasmine.Matchers.prototype.toBeLessThan = function(expected) { + return this.actual < expected; +}; + +jasmine.Matchers.prototype.toBeGreaterThan = function(expected) { + return this.actual > expected; +}; + +/** + * Matcher that checks that the expected item is equal to the actual item + * up to a given level of decimal precision (default 2). + * + * @param {Number} expected + * @param {Number} precision + */ +jasmine.Matchers.prototype.toBeCloseTo = function(expected, precision) { + if (!(precision === 0)) { + precision = precision || 2; + } + var multiplier = Math.pow(10, precision); + var actual = Math.round(this.actual * multiplier); + expected = Math.round(expected * multiplier); + return expected == actual; +}; + +/** + * Matcher that checks that the expected exception was thrown by the actual. + * + * @param {String} expected + */ +jasmine.Matchers.prototype.toThrow = function(expected) { + var result = false; + var exception; + if (typeof this.actual != 'function') { + throw new Error('Actual is not a function'); + } + try { + this.actual(); + } catch (e) { + exception = e; + } + if (exception) { + result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected)); + } + + var not = this.isNot ? "not " : ""; + + this.message = function() { + if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) { + return ["Expected function " + not + "to throw", expected ? expected.message || expected : "an exception", ", but it threw", exception.message || exception].join(' '); + } else { + return "Expected function to throw an exception."; + } + }; + + return result; +}; + +jasmine.Matchers.Any = function(expectedClass) { + this.expectedClass = expectedClass; +}; + +jasmine.Matchers.Any.prototype.matches = function(other) { + if (this.expectedClass == String) { + return typeof other == 'string' || other instanceof String; + } + + if (this.expectedClass == Number) { + return typeof other == 'number' || other instanceof Number; + } + + if (this.expectedClass == Function) { + return typeof other == 'function' || other instanceof Function; + } + + if (this.expectedClass == Object) { + return typeof other == 'object'; + } + + return other instanceof this.expectedClass; +}; + +jasmine.Matchers.Any.prototype.toString = function() { + return ''; +}; + +/** + * @constructor + */ +jasmine.MultiReporter = function() { + this.subReporters_ = []; +}; +jasmine.util.inherit(jasmine.MultiReporter, jasmine.Reporter); + +jasmine.MultiReporter.prototype.addReporter = function(reporter) { + this.subReporters_.push(reporter); +}; + +(function() { + var functionNames = [ + "reportRunnerStarting", + "reportRunnerResults", + "reportSuiteResults", + "reportSpecStarting", + "reportSpecResults", + "log" + ]; + for (var i = 0; i < functionNames.length; i++) { + var functionName = functionNames[i]; + jasmine.MultiReporter.prototype[functionName] = (function(functionName) { + return function() { + for (var j = 0; j < this.subReporters_.length; j++) { + var subReporter = this.subReporters_[j]; + if (subReporter[functionName]) { + subReporter[functionName].apply(subReporter, arguments); + } + } + }; + })(functionName); + } +})(); +/** + * Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults + * + * @constructor + */ +jasmine.NestedResults = function() { + /** + * The total count of results + */ + this.totalCount = 0; + /** + * Number of passed results + */ + this.passedCount = 0; + /** + * Number of failed results + */ + this.failedCount = 0; + /** + * Was this suite/spec skipped? + */ + this.skipped = false; + /** + * @ignore + */ + this.items_ = []; +}; + +/** + * Roll up the result counts. + * + * @param result + */ +jasmine.NestedResults.prototype.rollupCounts = function(result) { + this.totalCount += result.totalCount; + this.passedCount += result.passedCount; + this.failedCount += result.failedCount; +}; + +/** + * Adds a log message. + * @param values Array of message parts which will be concatenated later. + */ +jasmine.NestedResults.prototype.log = function(values) { + this.items_.push(new jasmine.MessageResult(values)); +}; + +/** + * Getter for the results: message & results. + */ +jasmine.NestedResults.prototype.getItems = function() { + return this.items_; +}; + +/** + * Adds a result, tracking counts (total, passed, & failed) + * @param {jasmine.ExpectationResult|jasmine.NestedResults} result + */ +jasmine.NestedResults.prototype.addResult = function(result) { + if (result.type != 'log') { + if (result.items_) { + this.rollupCounts(result); + } else { + this.totalCount++; + if (result.passed()) { + this.passedCount++; + } else { + this.failedCount++; + } + } + } + this.items_.push(result); +}; + +/** + * @returns {Boolean} True if everything below passed + */ +jasmine.NestedResults.prototype.passed = function() { + return this.passedCount === this.totalCount; +}; +/** + * Base class for pretty printing for expectation results. + */ +jasmine.PrettyPrinter = function() { + this.ppNestLevel_ = 0; +}; + +/** + * Formats a value in a nice, human-readable string. + * + * @param value + */ +jasmine.PrettyPrinter.prototype.format = function(value) { + if (this.ppNestLevel_ > 40) { + throw new Error('jasmine.PrettyPrinter: format() nested too deeply!'); + } + + this.ppNestLevel_++; + try { + if (value === jasmine.undefined) { + this.emitScalar('undefined'); + } else if (value === null) { + this.emitScalar('null'); + } else if (value === jasmine.getGlobal()) { + this.emitScalar(''); + } else if (value instanceof jasmine.Matchers.Any) { + this.emitScalar(value.toString()); + } else if (typeof value === 'string') { + this.emitString(value); + } else if (jasmine.isSpy(value)) { + this.emitScalar("spy on " + value.identity); + } else if (value instanceof RegExp) { + this.emitScalar(value.toString()); + } else if (typeof value === 'function') { + this.emitScalar('Function'); + } else if (typeof value.nodeType === 'number') { + this.emitScalar('HTMLNode'); + } else if (value instanceof Date) { + this.emitScalar('Date(' + value + ')'); + } else if (value.__Jasmine_been_here_before__) { + this.emitScalar(''); + } else if (jasmine.isArray_(value) || typeof value == 'object') { + value.__Jasmine_been_here_before__ = true; + if (jasmine.isArray_(value)) { + this.emitArray(value); + } else { + this.emitObject(value); + } + delete value.__Jasmine_been_here_before__; + } else { + this.emitScalar(value.toString()); + } + } finally { + this.ppNestLevel_--; + } +}; + +jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) { + for (var property in obj) { + if (property == '__Jasmine_been_here_before__') continue; + fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) !== jasmine.undefined && + obj.__lookupGetter__(property) !== null) : false); + } +}; + +jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_; +jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_; +jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_; +jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_; + +jasmine.StringPrettyPrinter = function() { + jasmine.PrettyPrinter.call(this); + + this.string = ''; +}; +jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter); + +jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) { + this.append(value); +}; + +jasmine.StringPrettyPrinter.prototype.emitString = function(value) { + this.append("'" + value + "'"); +}; + +jasmine.StringPrettyPrinter.prototype.emitArray = function(array) { + this.append('[ '); + for (var i = 0; i < array.length; i++) { + if (i > 0) { + this.append(', '); + } + this.format(array[i]); + } + this.append(' ]'); +}; + +jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) { + var self = this; + this.append('{ '); + var first = true; + + this.iterateObject(obj, function(property, isGetter) { + if (first) { + first = false; + } else { + self.append(', '); + } + + self.append(property); + self.append(' : '); + if (isGetter) { + self.append(''); + } else { + self.format(obj[property]); + } + }); + + this.append(' }'); +}; + +jasmine.StringPrettyPrinter.prototype.append = function(value) { + this.string += value; +}; +jasmine.Queue = function(env) { + this.env = env; + this.blocks = []; + this.running = false; + this.index = 0; + this.offset = 0; + this.abort = false; +}; + +jasmine.Queue.prototype.addBefore = function(block) { + this.blocks.unshift(block); +}; + +jasmine.Queue.prototype.add = function(block) { + this.blocks.push(block); +}; + +jasmine.Queue.prototype.insertNext = function(block) { + this.blocks.splice((this.index + this.offset + 1), 0, block); + this.offset++; +}; + +jasmine.Queue.prototype.start = function(onComplete) { + this.running = true; + this.onComplete = onComplete; + this.next_(); +}; + +jasmine.Queue.prototype.isRunning = function() { + return this.running; +}; + +jasmine.Queue.LOOP_DONT_RECURSE = true; + +jasmine.Queue.prototype.next_ = function() { + var self = this; + var goAgain = true; + + while (goAgain) { + goAgain = false; + + if (self.index < self.blocks.length && !this.abort) { + var calledSynchronously = true; + var completedSynchronously = false; + + var onComplete = function () { + if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously) { + completedSynchronously = true; + return; + } + + if (self.blocks[self.index].abort) { + self.abort = true; + } + + self.offset = 0; + self.index++; + + var now = new Date().getTime(); + if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) { + self.env.lastUpdate = now; + self.env.setTimeout(function() { + self.next_(); + }, 0); + } else { + if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously) { + goAgain = true; + } else { + self.next_(); + } + } + }; + self.blocks[self.index].execute(onComplete); + + calledSynchronously = false; + if (completedSynchronously) { + onComplete(); + } + + } else { + self.running = false; + if (self.onComplete) { + self.onComplete(); + } + } + } +}; + +jasmine.Queue.prototype.results = function() { + var results = new jasmine.NestedResults(); + for (var i = 0; i < this.blocks.length; i++) { + if (this.blocks[i].results) { + results.addResult(this.blocks[i].results()); + } + } + return results; +}; + + +/** + * Runner + * + * @constructor + * @param {jasmine.Env} env + */ +jasmine.Runner = function(env) { + var self = this; + self.env = env; + self.queue = new jasmine.Queue(env); + self.before_ = []; + self.after_ = []; + self.suites_ = []; +}; + +jasmine.Runner.prototype.execute = function() { + var self = this; + if (self.env.reporter.reportRunnerStarting) { + self.env.reporter.reportRunnerStarting(this); + } + self.queue.start(function () { + self.finishCallback(); + }); +}; + +jasmine.Runner.prototype.beforeEach = function(beforeEachFunction) { + beforeEachFunction.typeName = 'beforeEach'; + this.before_.splice(0,0,beforeEachFunction); +}; + +jasmine.Runner.prototype.afterEach = function(afterEachFunction) { + afterEachFunction.typeName = 'afterEach'; + this.after_.splice(0,0,afterEachFunction); +}; + + +jasmine.Runner.prototype.finishCallback = function() { + this.env.reporter.reportRunnerResults(this); +}; + +jasmine.Runner.prototype.addSuite = function(suite) { + this.suites_.push(suite); +}; + +jasmine.Runner.prototype.add = function(block) { + if (block instanceof jasmine.Suite) { + this.addSuite(block); + } + this.queue.add(block); +}; + +jasmine.Runner.prototype.specs = function () { + var suites = this.suites(); + var specs = []; + for (var i = 0; i < suites.length; i++) { + specs = specs.concat(suites[i].specs()); + } + return specs; +}; + +jasmine.Runner.prototype.suites = function() { + return this.suites_; +}; + +jasmine.Runner.prototype.topLevelSuites = function() { + var topLevelSuites = []; + for (var i = 0; i < this.suites_.length; i++) { + if (!this.suites_[i].parentSuite) { + topLevelSuites.push(this.suites_[i]); + } + } + return topLevelSuites; +}; + +jasmine.Runner.prototype.results = function() { + return this.queue.results(); +}; +/** + * Internal representation of a Jasmine specification, or test. + * + * @constructor + * @param {jasmine.Env} env + * @param {jasmine.Suite} suite + * @param {String} description + */ +jasmine.Spec = function(env, suite, description) { + if (!env) { + throw new Error('jasmine.Env() required'); + } + if (!suite) { + throw new Error('jasmine.Suite() required'); + } + var spec = this; + spec.id = env.nextSpecId ? env.nextSpecId() : null; + spec.env = env; + spec.suite = suite; + spec.description = description; + spec.queue = new jasmine.Queue(env); + + spec.afterCallbacks = []; + spec.spies_ = []; + + spec.results_ = new jasmine.NestedResults(); + spec.results_.description = description; + spec.matchersClass = null; +}; + +jasmine.Spec.prototype.getFullName = function() { + return this.suite.getFullName() + ' ' + this.description + '.'; +}; + + +jasmine.Spec.prototype.results = function() { + return this.results_; +}; + +/** + * All parameters are pretty-printed and concatenated together, then written to the spec's output. + * + * Be careful not to leave calls to jasmine.log in production code. + */ +jasmine.Spec.prototype.log = function() { + return this.results_.log(arguments); +}; + +jasmine.Spec.prototype.runs = function (func) { + var block = new jasmine.Block(this.env, func, this); + this.addToQueue(block); + return this; +}; + +jasmine.Spec.prototype.addToQueue = function (block) { + if (this.queue.isRunning()) { + this.queue.insertNext(block); + } else { + this.queue.add(block); + } +}; + +/** + * @param {jasmine.ExpectationResult} result + */ +jasmine.Spec.prototype.addMatcherResult = function(result) { + this.results_.addResult(result); +}; + +jasmine.Spec.prototype.expect = function(actual) { + var positive = new (this.getMatchersClass_())(this.env, actual, this); + positive.not = new (this.getMatchersClass_())(this.env, actual, this, true); + return positive; +}; + +/** + * Waits a fixed time period before moving to the next block. + * + * @deprecated Use waitsFor() instead + * @param {Number} timeout milliseconds to wait + */ +jasmine.Spec.prototype.waits = function(timeout) { + var waitsFunc = new jasmine.WaitsBlock(this.env, timeout, this); + this.addToQueue(waitsFunc); + return this; +}; + +/** + * Waits for the latchFunction to return true before proceeding to the next block. + * + * @param {Function} latchFunction + * @param {String} optional_timeoutMessage + * @param {Number} optional_timeout + */ +jasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) { + var latchFunction_ = null; + var optional_timeoutMessage_ = null; + var optional_timeout_ = null; + + for (var i = 0; i < arguments.length; i++) { + var arg = arguments[i]; + switch (typeof arg) { + case 'function': + latchFunction_ = arg; + break; + case 'string': + optional_timeoutMessage_ = arg; + break; + case 'number': + optional_timeout_ = arg; + break; + } + } + + var waitsForFunc = new jasmine.WaitsForBlock(this.env, optional_timeout_, latchFunction_, optional_timeoutMessage_, this); + this.addToQueue(waitsForFunc); + return this; +}; + +jasmine.Spec.prototype.fail = function (e) { + var expectationResult = new jasmine.ExpectationResult({ + passed: false, + message: e ? jasmine.util.formatException(e) : 'Exception', + trace: { stack: e.stack } + }); + this.results_.addResult(expectationResult); +}; + +jasmine.Spec.prototype.getMatchersClass_ = function() { + return this.matchersClass || this.env.matchersClass; +}; + +jasmine.Spec.prototype.addMatchers = function(matchersPrototype) { + var parent = this.getMatchersClass_(); + var newMatchersClass = function() { + parent.apply(this, arguments); + }; + jasmine.util.inherit(newMatchersClass, parent); + jasmine.Matchers.wrapInto_(matchersPrototype, newMatchersClass); + this.matchersClass = newMatchersClass; +}; + +jasmine.Spec.prototype.finishCallback = function() { + this.env.reporter.reportSpecResults(this); +}; + +jasmine.Spec.prototype.finish = function(onComplete) { + this.removeAllSpies(); + this.finishCallback(); + if (onComplete) { + onComplete(); + } +}; + +jasmine.Spec.prototype.after = function(doAfter) { + if (this.queue.isRunning()) { + this.queue.add(new jasmine.Block(this.env, doAfter, this)); + } else { + this.afterCallbacks.unshift(doAfter); + } +}; + +jasmine.Spec.prototype.execute = function(onComplete) { + var spec = this; + if (!spec.env.specFilter(spec)) { + spec.results_.skipped = true; + spec.finish(onComplete); + return; + } + + this.env.reporter.reportSpecStarting(this); + + spec.env.currentSpec = spec; + + spec.addBeforesAndAftersToQueue(); + + spec.queue.start(function () { + spec.finish(onComplete); + }); +}; + +jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() { + var runner = this.env.currentRunner(); + var i; + + for (var suite = this.suite; suite; suite = suite.parentSuite) { + for (i = 0; i < suite.before_.length; i++) { + this.queue.addBefore(new jasmine.Block(this.env, suite.before_[i], this)); + } + } + for (i = 0; i < runner.before_.length; i++) { + this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this)); + } + for (i = 0; i < this.afterCallbacks.length; i++) { + this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this)); + } + for (suite = this.suite; suite; suite = suite.parentSuite) { + for (i = 0; i < suite.after_.length; i++) { + this.queue.add(new jasmine.Block(this.env, suite.after_[i], this)); + } + } + for (i = 0; i < runner.after_.length; i++) { + this.queue.add(new jasmine.Block(this.env, runner.after_[i], this)); + } +}; + +jasmine.Spec.prototype.explodes = function() { + throw 'explodes function should not have been called'; +}; + +jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) { + if (obj == jasmine.undefined) { + throw "spyOn could not find an object to spy upon for " + methodName + "()"; + } + + if (!ignoreMethodDoesntExist && obj[methodName] === jasmine.undefined) { + throw methodName + '() method does not exist'; + } + + if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) { + throw new Error(methodName + ' has already been spied upon'); + } + + var spyObj = jasmine.createSpy(methodName); + + this.spies_.push(spyObj); + spyObj.baseObj = obj; + spyObj.methodName = methodName; + spyObj.originalValue = obj[methodName]; + + obj[methodName] = spyObj; + + return spyObj; +}; + +jasmine.Spec.prototype.removeAllSpies = function() { + for (var i = 0; i < this.spies_.length; i++) { + var spy = this.spies_[i]; + spy.baseObj[spy.methodName] = spy.originalValue; + } + this.spies_ = []; +}; + +/** + * Internal representation of a Jasmine suite. + * + * @constructor + * @param {jasmine.Env} env + * @param {String} description + * @param {Function} specDefinitions + * @param {jasmine.Suite} parentSuite + */ +jasmine.Suite = function(env, description, specDefinitions, parentSuite) { + var self = this; + self.id = env.nextSuiteId ? env.nextSuiteId() : null; + self.description = description; + self.queue = new jasmine.Queue(env); + self.parentSuite = parentSuite; + self.env = env; + self.before_ = []; + self.after_ = []; + self.children_ = []; + self.suites_ = []; + self.specs_ = []; +}; + +jasmine.Suite.prototype.getFullName = function() { + var fullName = this.description; + for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) { + fullName = parentSuite.description + ' ' + fullName; + } + return fullName; +}; + +jasmine.Suite.prototype.finish = function(onComplete) { + this.env.reporter.reportSuiteResults(this); + this.finished = true; + if (typeof(onComplete) == 'function') { + onComplete(); + } +}; + +jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) { + beforeEachFunction.typeName = 'beforeEach'; + this.before_.unshift(beforeEachFunction); +}; + +jasmine.Suite.prototype.afterEach = function(afterEachFunction) { + afterEachFunction.typeName = 'afterEach'; + this.after_.unshift(afterEachFunction); +}; + +jasmine.Suite.prototype.results = function() { + return this.queue.results(); +}; + +jasmine.Suite.prototype.add = function(suiteOrSpec) { + this.children_.push(suiteOrSpec); + if (suiteOrSpec instanceof jasmine.Suite) { + this.suites_.push(suiteOrSpec); + this.env.currentRunner().addSuite(suiteOrSpec); + } else { + this.specs_.push(suiteOrSpec); + } + this.queue.add(suiteOrSpec); +}; + +jasmine.Suite.prototype.specs = function() { + return this.specs_; +}; + +jasmine.Suite.prototype.suites = function() { + return this.suites_; +}; + +jasmine.Suite.prototype.children = function() { + return this.children_; +}; + +jasmine.Suite.prototype.execute = function(onComplete) { + var self = this; + this.queue.start(function () { + self.finish(onComplete); + }); +}; +jasmine.WaitsBlock = function(env, timeout, spec) { + this.timeout = timeout; + jasmine.Block.call(this, env, null, spec); +}; + +jasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block); + +jasmine.WaitsBlock.prototype.execute = function (onComplete) { + if (jasmine.VERBOSE) { + this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...'); + } + this.env.setTimeout(function () { + onComplete(); + }, this.timeout); +}; +/** + * A block which waits for some condition to become true, with timeout. + * + * @constructor + * @extends jasmine.Block + * @param {jasmine.Env} env The Jasmine environment. + * @param {Number} timeout The maximum time in milliseconds to wait for the condition to become true. + * @param {Function} latchFunction A function which returns true when the desired condition has been met. + * @param {String} message The message to display if the desired condition hasn't been met within the given time period. + * @param {jasmine.Spec} spec The Jasmine spec. + */ +jasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) { + this.timeout = timeout || env.defaultTimeoutInterval; + this.latchFunction = latchFunction; + this.message = message; + this.totalTimeSpentWaitingForLatch = 0; + jasmine.Block.call(this, env, null, spec); +}; +jasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block); + +jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 10; + +jasmine.WaitsForBlock.prototype.execute = function(onComplete) { + if (jasmine.VERBOSE) { + this.env.reporter.log('>> Jasmine waiting for ' + (this.message || 'something to happen')); + } + var latchFunctionResult; + try { + latchFunctionResult = this.latchFunction.apply(this.spec); + } catch (e) { + this.spec.fail(e); + onComplete(); + return; + } + + if (latchFunctionResult) { + onComplete(); + } else if (this.totalTimeSpentWaitingForLatch >= this.timeout) { + var message = 'timed out after ' + this.timeout + ' msec waiting for ' + (this.message || 'something to happen'); + this.spec.fail({ + name: 'timeout', + message: message + }); + + this.abort = true; + onComplete(); + } else { + this.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT; + var self = this; + this.env.setTimeout(function() { + self.execute(onComplete); + }, jasmine.WaitsForBlock.TIMEOUT_INCREMENT); + } +}; +// Mock setTimeout, clearTimeout +// Contributed by Pivotal Computer Systems, www.pivotalsf.com + +jasmine.FakeTimer = function() { + this.reset(); + + var self = this; + self.setTimeout = function(funcToCall, millis) { + self.timeoutsMade++; + self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false); + return self.timeoutsMade; + }; + + self.setInterval = function(funcToCall, millis) { + self.timeoutsMade++; + self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true); + return self.timeoutsMade; + }; + + self.clearTimeout = function(timeoutKey) { + self.scheduledFunctions[timeoutKey] = jasmine.undefined; + }; + + self.clearInterval = function(timeoutKey) { + self.scheduledFunctions[timeoutKey] = jasmine.undefined; + }; + +}; + +jasmine.FakeTimer.prototype.reset = function() { + this.timeoutsMade = 0; + this.scheduledFunctions = {}; + this.nowMillis = 0; +}; + +jasmine.FakeTimer.prototype.tick = function(millis) { + var oldMillis = this.nowMillis; + var newMillis = oldMillis + millis; + this.runFunctionsWithinRange(oldMillis, newMillis); + this.nowMillis = newMillis; +}; + +jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) { + var scheduledFunc; + var funcsToRun = []; + for (var timeoutKey in this.scheduledFunctions) { + scheduledFunc = this.scheduledFunctions[timeoutKey]; + if (scheduledFunc != jasmine.undefined && + scheduledFunc.runAtMillis >= oldMillis && + scheduledFunc.runAtMillis <= nowMillis) { + funcsToRun.push(scheduledFunc); + this.scheduledFunctions[timeoutKey] = jasmine.undefined; + } + } + + if (funcsToRun.length > 0) { + funcsToRun.sort(function(a, b) { + return a.runAtMillis - b.runAtMillis; + }); + for (var i = 0; i < funcsToRun.length; ++i) { + try { + var funcToRun = funcsToRun[i]; + this.nowMillis = funcToRun.runAtMillis; + funcToRun.funcToCall(); + if (funcToRun.recurring) { + this.scheduleFunction(funcToRun.timeoutKey, + funcToRun.funcToCall, + funcToRun.millis, + true); + } + } catch(e) { + } + } + this.runFunctionsWithinRange(oldMillis, nowMillis); + } +}; + +jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) { + this.scheduledFunctions[timeoutKey] = { + runAtMillis: this.nowMillis + millis, + funcToCall: funcToCall, + recurring: recurring, + timeoutKey: timeoutKey, + millis: millis + }; +}; + +/** + * @namespace + */ +jasmine.Clock = { + defaultFakeTimer: new jasmine.FakeTimer(), + + reset: function() { + jasmine.Clock.assertInstalled(); + jasmine.Clock.defaultFakeTimer.reset(); + }, + + tick: function(millis) { + jasmine.Clock.assertInstalled(); + jasmine.Clock.defaultFakeTimer.tick(millis); + }, + + runFunctionsWithinRange: function(oldMillis, nowMillis) { + jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis); + }, + + scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) { + jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring); + }, + + useMock: function() { + if (!jasmine.Clock.isInstalled()) { + var spec = jasmine.getEnv().currentSpec; + spec.after(jasmine.Clock.uninstallMock); + + jasmine.Clock.installMock(); + } + }, + + installMock: function() { + jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer; + }, + + uninstallMock: function() { + jasmine.Clock.assertInstalled(); + jasmine.Clock.installed = jasmine.Clock.real; + }, + + real: { + setTimeout: jasmine.getGlobal().setTimeout, + clearTimeout: jasmine.getGlobal().clearTimeout, + setInterval: jasmine.getGlobal().setInterval, + clearInterval: jasmine.getGlobal().clearInterval + }, + + assertInstalled: function() { + if (!jasmine.Clock.isInstalled()) { + throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()"); + } + }, + + isInstalled: function() { + return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer; + }, + + installed: null +}; +jasmine.Clock.installed = jasmine.Clock.real; + +//else for IE support +jasmine.getGlobal().setTimeout = function(funcToCall, millis) { + if (jasmine.Clock.installed.setTimeout.apply) { + return jasmine.Clock.installed.setTimeout.apply(this, arguments); + } else { + return jasmine.Clock.installed.setTimeout(funcToCall, millis); + } +}; + +jasmine.getGlobal().setInterval = function(funcToCall, millis) { + if (jasmine.Clock.installed.setInterval.apply) { + return jasmine.Clock.installed.setInterval.apply(this, arguments); + } else { + return jasmine.Clock.installed.setInterval(funcToCall, millis); + } +}; + +jasmine.getGlobal().clearTimeout = function(timeoutKey) { + if (jasmine.Clock.installed.clearTimeout.apply) { + return jasmine.Clock.installed.clearTimeout.apply(this, arguments); + } else { + return jasmine.Clock.installed.clearTimeout(timeoutKey); + } +}; + +jasmine.getGlobal().clearInterval = function(timeoutKey) { + if (jasmine.Clock.installed.clearTimeout.apply) { + return jasmine.Clock.installed.clearInterval.apply(this, arguments); + } else { + return jasmine.Clock.installed.clearInterval(timeoutKey); + } +}; + +jasmine.version_= { + "major": 1, + "minor": 1, + "build": 0, + "revision": 1315677058 +}; diff --git a/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine_favicon.png b/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine_favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..218f3b43713598fa5a3e78b57aceb909c33f46df GIT binary patch literal 905 zcmV;419tq0P)Px#AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_0008u zNkl3{fod28|PjmA)7fYg4w8-(2my9xtBGOs}K`n&t1VzxMO^X)M zrW+Ln1udc?q6TP)z5gAjt)P&D!M$+HJK#x<`xnD030zwD?KrxxY!2tlA zGc-58?0D7SsT)7Km=v+tNVNUk`?s@;^OxCF)y6P}_mL;~7;S<@b|MzmKq)m8l@yky zT1~ECpxZw@64!nkI34QLiUsA%i%N>-$&zGYR7WJyi9ERMyS(%kf z7A_r)X>!90&m(FwDQZ>q;+nOa*KR2+E6Fz)QwU=W1Oyo*4>_qlm|~joa|{4_A_3W8 z#FFZzRp-xMIx5a7D_Fj3&#r^TbIY@cND1d0f*^qDIs{!pw!IWGQ_%l4#ASm_D5Vet z0%ek7^)@xPihX_G0&hIc9*14ca=D!8oG}vW?H%~w^F?f_s>zU|fKrNJXJ_d6{v!t( zpEoqMws_yQws>3o?VW8Txq~#->dJG^ELW5irR!s`(_JvD^6;r+ho~eIK@ia8_lH(h zt*-p?CFC1_h2MV=?jP){uW!7WjLjCaO&c1D+tf582!XEaoB#xWAYcN5f$sLtf$koW zQs{{>)ZTq?FC6|J_%n}AWbiFK(Bo-%^-{H`*)E(ucjo-r%SYm)W5f6tN=xz=S646E fNXW#U{x?4WXWJ> $(depfile) +# Add extra rules as in (2). +# We remove slashes and replace spaces with new lines; +# remove blank lines; +# delete the first line and append a colon to the remaining lines. +sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\ + grep -v '^$$' |\ + sed -e 1d -e 's|$$|:|' \ + >> $(depfile) +rm $(depfile).raw +endef + +# Command definitions: +# - cmd_foo is the actual command to run; +# - quiet_cmd_foo is the brief-output summary of the command. + +quiet_cmd_cc = CC($(TOOLSET)) $@ +cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $< + +quiet_cmd_cxx = CXX($(TOOLSET)) $@ +cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< + +quiet_cmd_objc = CXX($(TOOLSET)) $@ +cmd_objc = $(CC.$(TOOLSET)) $(GYP_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $< + +quiet_cmd_objcxx = CXX($(TOOLSET)) $@ +cmd_objcxx = $(CXX.$(TOOLSET)) $(GYP_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $< + +# Commands for precompiled header files. +quiet_cmd_pch_c = CXX($(TOOLSET)) $@ +cmd_pch_c = $(CC.$(TOOLSET)) $(GYP_PCH_CFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< +quiet_cmd_pch_cc = CXX($(TOOLSET)) $@ +cmd_pch_cc = $(CC.$(TOOLSET)) $(GYP_PCH_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< +quiet_cmd_pch_m = CXX($(TOOLSET)) $@ +cmd_pch_m = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $< +quiet_cmd_pch_mm = CXX($(TOOLSET)) $@ +cmd_pch_mm = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $< + +# gyp-mac-tool is written next to the root Makefile by gyp. +# Use $(4) for the command, since $(2) and $(3) are used as flag by do_cmd +# already. +quiet_cmd_mac_tool = MACTOOL $(4) $< +cmd_mac_tool = ./gyp-mac-tool $(4) $< "$@" + +quiet_cmd_mac_package_framework = PACKAGE FRAMEWORK $@ +cmd_mac_package_framework = ./gyp-mac-tool package-framework "$@" $(4) + +quiet_cmd_infoplist = INFOPLIST $@ +cmd_infoplist = $(CC.$(TOOLSET)) -E -P -Wno-trigraphs -x c $(INFOPLIST_DEFINES) "$<" -o "$@" + +quiet_cmd_touch = TOUCH $@ +cmd_touch = touch $@ + +quiet_cmd_copy = COPY $@ +# send stderr to /dev/null to ignore messages when linking directories. +cmd_copy = rm -rf "$@" && cp -af "$<" "$@" + +quiet_cmd_alink = LIBTOOL-STATIC $@ +cmd_alink = rm -f $@ && ./gyp-mac-tool filter-libtool libtool $(GYP_LIBTOOLFLAGS) -static -o $@ $(filter %.o,$^) + +quiet_cmd_link = LINK($(TOOLSET)) $@ +cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS) + +quiet_cmd_solink = SOLINK($(TOOLSET)) $@ +cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS) + +quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@ +cmd_solink_module = $(LINK.$(TOOLSET)) -bundle $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS) + + +# Define an escape_quotes function to escape single quotes. +# This allows us to handle quotes properly as long as we always use +# use single quotes and escape_quotes. +escape_quotes = $(subst ','\'',$(1)) +# This comment is here just to include a ' to unconfuse syntax highlighting. +# Define an escape_vars function to escape '$' variable syntax. +# This allows us to read/write command lines with shell variables (e.g. +# $LD_LIBRARY_PATH), without triggering make substitution. +escape_vars = $(subst $$,$$$$,$(1)) +# Helper that expands to a shell command to echo a string exactly as it is in +# make. This uses printf instead of echo because printf's behaviour with respect +# to escape sequences is more portable than echo's across different shells +# (e.g., dash, bash). +exact_echo = printf '%s\n' '$(call escape_quotes,$(1))' + +# Helper to compare the command we're about to run against the command +# we logged the last time we ran the command. Produces an empty +# string (false) when the commands match. +# Tricky point: Make has no string-equality test function. +# The kernel uses the following, but it seems like it would have false +# positives, where one string reordered its arguments. +# arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \ +# $(filter-out $(cmd_$@), $(cmd_$(1)))) +# We instead substitute each for the empty string into the other, and +# say they're equal if both substitutions produce the empty string. +# .d files contain ? instead of spaces, take that into account. +command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\ + $(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1)))) + +# Helper that is non-empty when a prerequisite changes. +# Normally make does this implicitly, but we force rules to always run +# so we can check their command lines. +# $? -- new prerequisites +# $| -- order-only dependencies +prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?)) + +# Helper that executes all postbuilds until one fails. +define do_postbuilds + @E=0;\ + for p in $(POSTBUILDS); do\ + eval $$p;\ + E=$$?;\ + if [ $$E -ne 0 ]; then\ + break;\ + fi;\ + done;\ + if [ $$E -ne 0 ]; then\ + rm -rf "$@";\ + exit $$E;\ + fi +endef + +# do_cmd: run a command via the above cmd_foo names, if necessary. +# Should always run for a given target to handle command-line changes. +# Second argument, if non-zero, makes it do asm/C/C++ dependency munging. +# Third argument, if non-zero, makes it do POSTBUILDS processing. +# Note: We intentionally do NOT call dirx for depfile, since it contains ? for +# spaces already and dirx strips the ? characters. +define do_cmd +$(if $(or $(command_changed),$(prereq_changed)), + @$(call exact_echo, $($(quiet)cmd_$(1))) + @mkdir -p "$(call dirx,$@)" "$(dir $(depfile))" + $(if $(findstring flock,$(word 2,$(cmd_$1))), + @$(cmd_$(1)) + @echo " $(quiet_cmd_$(1)): Finished", + @$(cmd_$(1)) + ) + @$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile) + @$(if $(2),$(fixup_dep)) + $(if $(and $(3), $(POSTBUILDS)), + $(call do_postbuilds) + ) +) +endef + +# Declare the "all" target first so it is the default, +# even though we don't have the deps yet. +.PHONY: all +all: + +# make looks for ways to re-generate included makefiles, but in our case, we +# don't have a direct way. Explicitly telling make that it has nothing to do +# for them makes it go faster. +%.d: ; + +# Use FORCE_DO_CMD to force a target to run. Should be coupled with +# do_cmd. +.PHONY: FORCE_DO_CMD +FORCE_DO_CMD: + +TOOLSET := target +# Suffix rules, putting all outputs into $(obj). +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.c FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cxx FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.m FORCE_DO_CMD + @$(call do_cmd,objc,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.mm FORCE_DO_CMD + @$(call do_cmd,objcxx,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.S FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.s FORCE_DO_CMD + @$(call do_cmd,cc,1) + +# Try building from generated source, too. +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cxx FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.m FORCE_DO_CMD + @$(call do_cmd,objc,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.mm FORCE_DO_CMD + @$(call do_cmd,objcxx,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.S FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.s FORCE_DO_CMD + @$(call do_cmd,cc,1) + +$(obj).$(TOOLSET)/%.o: $(obj)/%.c FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.cpp FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.cxx FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.m FORCE_DO_CMD + @$(call do_cmd,objc,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.mm FORCE_DO_CMD + @$(call do_cmd,objcxx,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.S FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.s FORCE_DO_CMD + @$(call do_cmd,cc,1) + + +ifeq ($(strip $(foreach prefix,$(NO_LOAD),\ + $(findstring $(join ^,$(prefix)),\ + $(join ^,kerberos.target.mk)))),) + include kerberos.target.mk +endif + +quiet_cmd_regen_makefile = ACTION Regenerating $@ +cmd_regen_makefile = cd $(srcdir); /usr/local/lib/node_modules/npm/node_modules/node-gyp/gyp/gyp_main.py -fmake --ignore-environment "--toplevel-dir=." -I/Users/voxfeed_1/code/offhours/argon/node_modules/mongodb/node_modules/kerberos/build/config.gypi -I/usr/local/lib/node_modules/npm/node_modules/node-gyp/addon.gypi -I/Users/voxfeed_1/.node-gyp/0.10.31/common.gypi "--depth=." "-Goutput_dir=." "--generator-output=build" "-Dlibrary=shared_library" "-Dvisibility=default" "-Dnode_root_dir=/Users/voxfeed_1/.node-gyp/0.10.31" "-Dmodule_root_dir=/Users/voxfeed_1/code/offhours/argon/node_modules/mongodb/node_modules/kerberos" binding.gyp +Makefile: $(srcdir)/../../../../../../../../../usr/local/lib/node_modules/npm/node_modules/node-gyp/addon.gypi $(srcdir)/build/config.gypi $(srcdir)/binding.gyp $(srcdir)/../../../../../../../.node-gyp/0.10.31/common.gypi + $(call do_cmd,regen_makefile) + +# "all" is a concatenation of the "all" targets from all the included +# sub-makefiles. This is just here to clarify. +all: + +# Add in dependency-tracking rules. $(all_deps) is the list of every single +# target in our tree. Only consider the ones with .d (dependency) info: +d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d)) +ifneq ($(d_files),) + include $(d_files) +endif diff --git a/node_modules/mongodb/node_modules/kerberos/build/Release/.deps/Release/obj.target/kerberos/lib/kerberos.o.d.raw b/node_modules/mongodb/node_modules/kerberos/build/Release/.deps/Release/obj.target/kerberos/lib/kerberos.o.d.raw new file mode 100644 index 0000000..5cff6ce --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/build/Release/.deps/Release/obj.target/kerberos/lib/kerberos.o.d.raw @@ -0,0 +1,15 @@ +Release/obj.target/kerberos/lib/kerberos.o: ../lib/kerberos.cc \ + ../lib/kerberos.h /Users/voxfeed_1/.node-gyp/0.10.31/src/node.h \ + /Users/voxfeed_1/.node-gyp/0.10.31/deps/uv/include/uv.h \ + /Users/voxfeed_1/.node-gyp/0.10.31/deps/uv/include/uv-private/uv-unix.h \ + /Users/voxfeed_1/.node-gyp/0.10.31/deps/uv/include/uv-private/ngx-queue.h \ + /Users/voxfeed_1/.node-gyp/0.10.31/deps/uv/include/uv-private/uv-darwin.h \ + /Users/voxfeed_1/.node-gyp/0.10.31/deps/v8/include/v8.h \ + /Users/voxfeed_1/.node-gyp/0.10.31/deps/v8/include/v8stdint.h \ + /Users/voxfeed_1/.node-gyp/0.10.31/src/node_object_wrap.h \ + ../node_modules/nan/nan.h \ + /Users/voxfeed_1/.node-gyp/0.10.31/src/node_buffer.h \ + /Users/voxfeed_1/.node-gyp/0.10.31/src/node_version.h \ + /Users/voxfeed_1/.node-gyp/0.10.31/src/util.h \ + /Users/voxfeed_1/.node-gyp/0.10.31/src/string_bytes.h \ + ../lib/kerberosgss.h ../lib/worker.h ../lib/kerberos_context.h diff --git a/node_modules/mongodb/node_modules/kerberos/build/binding.Makefile b/node_modules/mongodb/node_modules/kerberos/build/binding.Makefile new file mode 100644 index 0000000..69e964f --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/build/binding.Makefile @@ -0,0 +1,6 @@ +# This file is generated by gyp; do not edit. + +export builddir_name ?= ./build/. +.PHONY: all +all: + $(MAKE) kerberos diff --git a/node_modules/mongodb/node_modules/kerberos/build/config.gypi b/node_modules/mongodb/node_modules/kerberos/build/config.gypi new file mode 100644 index 0000000..e804b11 --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/build/config.gypi @@ -0,0 +1,119 @@ +# Do not edit. File was generated by node-gyp's "configure" step +{ + "target_defaults": { + "cflags": [], + "default_configuration": "Release", + "defines": [], + "include_dirs": [], + "libraries": [] + }, + "variables": { + "clang": 1, + "host_arch": "x64", + "node_install_npm": "false", + "node_prefix": "/usr/local/Cellar/node/0.10.31", + "node_shared_cares": "false", + "node_shared_http_parser": "false", + "node_shared_libuv": "false", + "node_shared_openssl": "false", + "node_shared_v8": "false", + "node_shared_zlib": "false", + "node_tag": "", + "node_unsafe_optimizations": 0, + "node_use_dtrace": "true", + "node_use_etw": "false", + "node_use_openssl": "true", + "node_use_perfctr": "false", + "python": "/usr/local/opt/python/bin/python2.7", + "target_arch": "x64", + "v8_enable_gdbjit": 0, + "v8_no_strict_aliasing": 1, + "v8_use_snapshot": "true", + "want_separate_host_toolset": 0, + "nodedir": "/Users/voxfeed_1/.node-gyp/0.10.31", + "copy_dev_lib": "true", + "standalone_static_library": 1, + "save_dev": "", + "browser": "", + "viewer": "man", + "rollback": "true", + "usage": "", + "globalignorefile": "/usr/local/etc/npmignore", + "init_author_url": "", + "shell": "/bin/bash", + "parseable": "", + "shrinkwrap": "true", + "email": "contacto@voxfeed.com", + "init_license": "ISC", + "init_author_email": "contacto@voxfeed.com", + "cache_max": "Infinity", + "sign_git_tag": "", + "cert": "", + "git_tag_version": "true", + "local_address": "", + "long": "", + "registry": "https://registry.npmjs.org/", + "fetch_retries": "2", + "npat": "", + "key": "", + "message": "%s", + "versions": "", + "globalconfig": "/usr/local/etc/npmrc", + "always_auth": "", + "spin": "true", + "cache_lock_retries": "10", + "cafile": "", + "heading": "npm", + "fetch_retry_mintimeout": "10000", + "proprietary_attribs": "true", + "json": "", + "description": "true", + "engine_strict": "", + "https_proxy": "", + "init_module": "/Users/voxfeed_1/.npm-init.js", + "userconfig": "/Users/voxfeed_1/.npmrc", + "node_version": "0.10.31", + "user": "", + "save": "true", + "editor": "vi", + "tag": "latest", + "global": "", + "username": "voxfeed", + "optional": "true", + "bin_links": "true", + "force": "", + "searchopts": "", + "depth": "Infinity", + "rebuild_bundle": "true", + "searchsort": "name", + "unicode": "true", + "fetch_retry_maxtimeout": "60000", + "ca": "", + "save_prefix": "^", + "strict_ssl": "true", + "dev": "", + "fetch_retry_factor": "10", + "group": "20", + "save_exact": "", + "cache_lock_stale": "60000", + "version": "", + "cache_min": "10", + "cache": "/Users/voxfeed_1/.npm", + "searchexclude": "", + "color": "true", + "save_optional": "", + "user_agent": "npm/1.4.27 node/v0.10.31 darwin x64", + "ignore_scripts": "", + "cache_lock_wait": "10000", + "production": "", + "save_bundle": "", + "umask": "18", + "init_author_name": "VoxFeed", + "git": "git", + "onload_script": "", + "tmp": "/var/folders/8l/gc9d_yxd60b5nf5vxn5_rjfm0000gp/T", + "unsafe_perm": "true", + "link": "", + "prefix": "/usr/local" + } +} diff --git a/node_modules/mongodb/node_modules/kerberos/build/gyp-mac-tool b/node_modules/mongodb/node_modules/kerberos/build/gyp-mac-tool new file mode 100755 index 0000000..7abfed5 --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/build/gyp-mac-tool @@ -0,0 +1,512 @@ +#!/usr/bin/env python +# Generated by gyp. Do not edit. +# Copyright (c) 2012 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Utility functions to perform Xcode-style build steps. + +These functions are executed via gyp-mac-tool when using the Makefile generator. +""" + +import fcntl +import fnmatch +import glob +import json +import os +import plistlib +import re +import shutil +import string +import subprocess +import sys +import tempfile + + +def main(args): + executor = MacTool() + exit_code = executor.Dispatch(args) + if exit_code is not None: + sys.exit(exit_code) + + +class MacTool(object): + """This class performs all the Mac tooling steps. The methods can either be + executed directly, or dispatched from an argument list.""" + + def Dispatch(self, args): + """Dispatches a string command to a method.""" + if len(args) < 1: + raise Exception("Not enough arguments") + + method = "Exec%s" % self._CommandifyName(args[0]) + return getattr(self, method)(*args[1:]) + + def _CommandifyName(self, name_string): + """Transforms a tool name like copy-info-plist to CopyInfoPlist""" + return name_string.title().replace('-', '') + + def ExecCopyBundleResource(self, source, dest): + """Copies a resource file to the bundle/Resources directory, performing any + necessary compilation on each resource.""" + extension = os.path.splitext(source)[1].lower() + if os.path.isdir(source): + # Copy tree. + # TODO(thakis): This copies file attributes like mtime, while the + # single-file branch below doesn't. This should probably be changed to + # be consistent with the single-file branch. + if os.path.exists(dest): + shutil.rmtree(dest) + shutil.copytree(source, dest) + elif extension == '.xib': + return self._CopyXIBFile(source, dest) + elif extension == '.storyboard': + return self._CopyXIBFile(source, dest) + elif extension == '.strings': + self._CopyStringsFile(source, dest) + else: + shutil.copy(source, dest) + + def _CopyXIBFile(self, source, dest): + """Compiles a XIB file with ibtool into a binary plist in the bundle.""" + + # ibtool sometimes crashes with relative paths. See crbug.com/314728. + base = os.path.dirname(os.path.realpath(__file__)) + if os.path.relpath(source): + source = os.path.join(base, source) + if os.path.relpath(dest): + dest = os.path.join(base, dest) + + args = ['xcrun', 'ibtool', '--errors', '--warnings', '--notices', + '--output-format', 'human-readable-text', '--compile', dest, source] + ibtool_section_re = re.compile(r'/\*.*\*/') + ibtool_re = re.compile(r'.*note:.*is clipping its content') + ibtoolout = subprocess.Popen(args, stdout=subprocess.PIPE) + current_section_header = None + for line in ibtoolout.stdout: + if ibtool_section_re.match(line): + current_section_header = line + elif not ibtool_re.match(line): + if current_section_header: + sys.stdout.write(current_section_header) + current_section_header = None + sys.stdout.write(line) + return ibtoolout.returncode + + def _CopyStringsFile(self, source, dest): + """Copies a .strings file using iconv to reconvert the input into UTF-16.""" + input_code = self._DetectInputEncoding(source) or "UTF-8" + + # Xcode's CpyCopyStringsFile / builtin-copyStrings seems to call + # CFPropertyListCreateFromXMLData() behind the scenes; at least it prints + # CFPropertyListCreateFromXMLData(): Old-style plist parser: missing + # semicolon in dictionary. + # on invalid files. Do the same kind of validation. + import CoreFoundation + s = open(source, 'rb').read() + d = CoreFoundation.CFDataCreate(None, s, len(s)) + _, error = CoreFoundation.CFPropertyListCreateFromXMLData(None, d, 0, None) + if error: + return + + fp = open(dest, 'wb') + fp.write(s.decode(input_code).encode('UTF-16')) + fp.close() + + def _DetectInputEncoding(self, file_name): + """Reads the first few bytes from file_name and tries to guess the text + encoding. Returns None as a guess if it can't detect it.""" + fp = open(file_name, 'rb') + try: + header = fp.read(3) + except e: + fp.close() + return None + fp.close() + if header.startswith("\xFE\xFF"): + return "UTF-16" + elif header.startswith("\xFF\xFE"): + return "UTF-16" + elif header.startswith("\xEF\xBB\xBF"): + return "UTF-8" + else: + return None + + def ExecCopyInfoPlist(self, source, dest, *keys): + """Copies the |source| Info.plist to the destination directory |dest|.""" + # Read the source Info.plist into memory. + fd = open(source, 'r') + lines = fd.read() + fd.close() + + # Insert synthesized key/value pairs (e.g. BuildMachineOSBuild). + plist = plistlib.readPlistFromString(lines) + if keys: + plist = dict(plist.items() + json.loads(keys[0]).items()) + lines = plistlib.writePlistToString(plist) + + # Go through all the environment variables and replace them as variables in + # the file. + IDENT_RE = re.compile('[/\s]') + for key in os.environ: + if key.startswith('_'): + continue + evar = '${%s}' % key + evalue = os.environ[key] + lines = string.replace(lines, evar, evalue) + + # Xcode supports various suffices on environment variables, which are + # all undocumented. :rfc1034identifier is used in the standard project + # template these days, and :identifier was used earlier. They are used to + # convert non-url characters into things that look like valid urls -- + # except that the replacement character for :identifier, '_' isn't valid + # in a URL either -- oops, hence :rfc1034identifier was born. + evar = '${%s:identifier}' % key + evalue = IDENT_RE.sub('_', os.environ[key]) + lines = string.replace(lines, evar, evalue) + + evar = '${%s:rfc1034identifier}' % key + evalue = IDENT_RE.sub('-', os.environ[key]) + lines = string.replace(lines, evar, evalue) + + # Remove any keys with values that haven't been replaced. + lines = lines.split('\n') + for i in range(len(lines)): + if lines[i].strip().startswith("${"): + lines[i] = None + lines[i - 1] = None + lines = '\n'.join(filter(lambda x: x is not None, lines)) + + # Write out the file with variables replaced. + fd = open(dest, 'w') + fd.write(lines) + fd.close() + + # Now write out PkgInfo file now that the Info.plist file has been + # "compiled". + self._WritePkgInfo(dest) + + def _WritePkgInfo(self, info_plist): + """This writes the PkgInfo file from the data stored in Info.plist.""" + plist = plistlib.readPlist(info_plist) + if not plist: + return + + # Only create PkgInfo for executable types. + package_type = plist['CFBundlePackageType'] + if package_type != 'APPL': + return + + # The format of PkgInfo is eight characters, representing the bundle type + # and bundle signature, each four characters. If that is missing, four + # '?' characters are used instead. + signature_code = plist.get('CFBundleSignature', '????') + if len(signature_code) != 4: # Wrong length resets everything, too. + signature_code = '?' * 4 + + dest = os.path.join(os.path.dirname(info_plist), 'PkgInfo') + fp = open(dest, 'w') + fp.write('%s%s' % (package_type, signature_code)) + fp.close() + + def ExecFlock(self, lockfile, *cmd_list): + """Emulates the most basic behavior of Linux's flock(1).""" + # Rely on exception handling to report errors. + fd = os.open(lockfile, os.O_RDONLY|os.O_NOCTTY|os.O_CREAT, 0o666) + fcntl.flock(fd, fcntl.LOCK_EX) + return subprocess.call(cmd_list) + + def ExecFilterLibtool(self, *cmd_list): + """Calls libtool and filters out '/path/to/libtool: file: foo.o has no + symbols'.""" + libtool_re = re.compile(r'^.*libtool: file: .* has no symbols$') + libtoolout = subprocess.Popen(cmd_list, stderr=subprocess.PIPE) + _, err = libtoolout.communicate() + for line in err.splitlines(): + if not libtool_re.match(line): + print >>sys.stderr, line + return libtoolout.returncode + + def ExecPackageFramework(self, framework, version): + """Takes a path to Something.framework and the Current version of that and + sets up all the symlinks.""" + # Find the name of the binary based on the part before the ".framework". + binary = os.path.basename(framework).split('.')[0] + + CURRENT = 'Current' + RESOURCES = 'Resources' + VERSIONS = 'Versions' + + if not os.path.exists(os.path.join(framework, VERSIONS, version, binary)): + # Binary-less frameworks don't seem to contain symlinks (see e.g. + # chromium's out/Debug/org.chromium.Chromium.manifest/ bundle). + return + + # Move into the framework directory to set the symlinks correctly. + pwd = os.getcwd() + os.chdir(framework) + + # Set up the Current version. + self._Relink(version, os.path.join(VERSIONS, CURRENT)) + + # Set up the root symlinks. + self._Relink(os.path.join(VERSIONS, CURRENT, binary), binary) + self._Relink(os.path.join(VERSIONS, CURRENT, RESOURCES), RESOURCES) + + # Back to where we were before! + os.chdir(pwd) + + def _Relink(self, dest, link): + """Creates a symlink to |dest| named |link|. If |link| already exists, + it is overwritten.""" + if os.path.lexists(link): + os.remove(link) + os.symlink(dest, link) + + def ExecCodeSignBundle(self, key, resource_rules, entitlements, provisioning): + """Code sign a bundle. + + This function tries to code sign an iOS bundle, following the same + algorithm as Xcode: + 1. copy ResourceRules.plist from the user or the SDK into the bundle, + 2. pick the provisioning profile that best match the bundle identifier, + and copy it into the bundle as embedded.mobileprovision, + 3. copy Entitlements.plist from user or SDK next to the bundle, + 4. code sign the bundle. + """ + resource_rules_path = self._InstallResourceRules(resource_rules) + substitutions, overrides = self._InstallProvisioningProfile( + provisioning, self._GetCFBundleIdentifier()) + entitlements_path = self._InstallEntitlements( + entitlements, substitutions, overrides) + subprocess.check_call([ + 'codesign', '--force', '--sign', key, '--resource-rules', + resource_rules_path, '--entitlements', entitlements_path, + os.path.join( + os.environ['TARGET_BUILD_DIR'], + os.environ['FULL_PRODUCT_NAME'])]) + + def _InstallResourceRules(self, resource_rules): + """Installs ResourceRules.plist from user or SDK into the bundle. + + Args: + resource_rules: string, optional, path to the ResourceRules.plist file + to use, default to "${SDKROOT}/ResourceRules.plist" + + Returns: + Path to the copy of ResourceRules.plist into the bundle. + """ + source_path = resource_rules + target_path = os.path.join( + os.environ['BUILT_PRODUCTS_DIR'], + os.environ['CONTENTS_FOLDER_PATH'], + 'ResourceRules.plist') + if not source_path: + source_path = os.path.join( + os.environ['SDKROOT'], 'ResourceRules.plist') + shutil.copy2(source_path, target_path) + return target_path + + def _InstallProvisioningProfile(self, profile, bundle_identifier): + """Installs embedded.mobileprovision into the bundle. + + Args: + profile: string, optional, short name of the .mobileprovision file + to use, if empty or the file is missing, the best file installed + will be used + bundle_identifier: string, value of CFBundleIdentifier from Info.plist + + Returns: + A tuple containing two dictionary: variables substitutions and values + to overrides when generating the entitlements file. + """ + source_path, provisioning_data, team_id = self._FindProvisioningProfile( + profile, bundle_identifier) + target_path = os.path.join( + os.environ['BUILT_PRODUCTS_DIR'], + os.environ['CONTENTS_FOLDER_PATH'], + 'embedded.mobileprovision') + shutil.copy2(source_path, target_path) + substitutions = self._GetSubstitutions(bundle_identifier, team_id + '.') + return substitutions, provisioning_data['Entitlements'] + + def _FindProvisioningProfile(self, profile, bundle_identifier): + """Finds the .mobileprovision file to use for signing the bundle. + + Checks all the installed provisioning profiles (or if the user specified + the PROVISIONING_PROFILE variable, only consult it) and select the most + specific that correspond to the bundle identifier. + + Args: + profile: string, optional, short name of the .mobileprovision file + to use, if empty or the file is missing, the best file installed + will be used + bundle_identifier: string, value of CFBundleIdentifier from Info.plist + + Returns: + A tuple of the path to the selected provisioning profile, the data of + the embedded plist in the provisioning profile and the team identifier + to use for code signing. + + Raises: + SystemExit: if no .mobileprovision can be used to sign the bundle. + """ + profiles_dir = os.path.join( + os.environ['HOME'], 'Library', 'MobileDevice', 'Provisioning Profiles') + if not os.path.isdir(profiles_dir): + print >>sys.stderr, ( + 'cannot find mobile provisioning for %s' % bundle_identifier) + sys.exit(1) + provisioning_profiles = None + if profile: + profile_path = os.path.join(profiles_dir, profile + '.mobileprovision') + if os.path.exists(profile_path): + provisioning_profiles = [profile_path] + if not provisioning_profiles: + provisioning_profiles = glob.glob( + os.path.join(profiles_dir, '*.mobileprovision')) + valid_provisioning_profiles = {} + for profile_path in provisioning_profiles: + profile_data = self._LoadProvisioningProfile(profile_path) + app_id_pattern = profile_data.get( + 'Entitlements', {}).get('application-identifier', '') + for team_identifier in profile_data.get('TeamIdentifier', []): + app_id = '%s.%s' % (team_identifier, bundle_identifier) + if fnmatch.fnmatch(app_id, app_id_pattern): + valid_provisioning_profiles[app_id_pattern] = ( + profile_path, profile_data, team_identifier) + if not valid_provisioning_profiles: + print >>sys.stderr, ( + 'cannot find mobile provisioning for %s' % bundle_identifier) + sys.exit(1) + # If the user has multiple provisioning profiles installed that can be + # used for ${bundle_identifier}, pick the most specific one (ie. the + # provisioning profile whose pattern is the longest). + selected_key = max(valid_provisioning_profiles, key=lambda v: len(v)) + return valid_provisioning_profiles[selected_key] + + def _LoadProvisioningProfile(self, profile_path): + """Extracts the plist embedded in a provisioning profile. + + Args: + profile_path: string, path to the .mobileprovision file + + Returns: + Content of the plist embedded in the provisioning profile as a dictionary. + """ + with tempfile.NamedTemporaryFile() as temp: + subprocess.check_call([ + 'security', 'cms', '-D', '-i', profile_path, '-o', temp.name]) + return self._LoadPlistMaybeBinary(temp.name) + + def _LoadPlistMaybeBinary(self, plist_path): + """Loads into a memory a plist possibly encoded in binary format. + + This is a wrapper around plistlib.readPlist that tries to convert the + plist to the XML format if it can't be parsed (assuming that it is in + the binary format). + + Args: + plist_path: string, path to a plist file, in XML or binary format + + Returns: + Content of the plist as a dictionary. + """ + try: + # First, try to read the file using plistlib that only supports XML, + # and if an exception is raised, convert a temporary copy to XML and + # load that copy. + return plistlib.readPlist(plist_path) + except: + pass + with tempfile.NamedTemporaryFile() as temp: + shutil.copy2(plist_path, temp.name) + subprocess.check_call(['plutil', '-convert', 'xml1', temp.name]) + return plistlib.readPlist(temp.name) + + def _GetSubstitutions(self, bundle_identifier, app_identifier_prefix): + """Constructs a dictionary of variable substitutions for Entitlements.plist. + + Args: + bundle_identifier: string, value of CFBundleIdentifier from Info.plist + app_identifier_prefix: string, value for AppIdentifierPrefix + + Returns: + Dictionary of substitutions to apply when generating Entitlements.plist. + """ + return { + 'CFBundleIdentifier': bundle_identifier, + 'AppIdentifierPrefix': app_identifier_prefix, + } + + def _GetCFBundleIdentifier(self): + """Extracts CFBundleIdentifier value from Info.plist in the bundle. + + Returns: + Value of CFBundleIdentifier in the Info.plist located in the bundle. + """ + info_plist_path = os.path.join( + os.environ['TARGET_BUILD_DIR'], + os.environ['INFOPLIST_PATH']) + info_plist_data = self._LoadPlistMaybeBinary(info_plist_path) + return info_plist_data['CFBundleIdentifier'] + + def _InstallEntitlements(self, entitlements, substitutions, overrides): + """Generates and install the ${BundleName}.xcent entitlements file. + + Expands variables "$(variable)" pattern in the source entitlements file, + add extra entitlements defined in the .mobileprovision file and the copy + the generated plist to "${BundlePath}.xcent". + + Args: + entitlements: string, optional, path to the Entitlements.plist template + to use, defaults to "${SDKROOT}/Entitlements.plist" + substitutions: dictionary, variable substitutions + overrides: dictionary, values to add to the entitlements + + Returns: + Path to the generated entitlements file. + """ + source_path = entitlements + target_path = os.path.join( + os.environ['BUILT_PRODUCTS_DIR'], + os.environ['PRODUCT_NAME'] + '.xcent') + if not source_path: + source_path = os.path.join( + os.environ['SDKROOT'], + 'Entitlements.plist') + shutil.copy2(source_path, target_path) + data = self._LoadPlistMaybeBinary(target_path) + data = self._ExpandVariables(data, substitutions) + if overrides: + for key in overrides: + if key not in data: + data[key] = overrides[key] + plistlib.writePlist(data, target_path) + return target_path + + def _ExpandVariables(self, data, substitutions): + """Expands variables "$(variable)" in data. + + Args: + data: object, can be either string, list or dictionary + substitutions: dictionary, variable substitutions to perform + + Returns: + Copy of data where each references to "$(variable)" has been replaced + by the corresponding value found in substitutions, or left intact if + the key was not found. + """ + if isinstance(data, str): + for key, value in substitutions.iteritems(): + data = data.replace('$(%s)' % key, value) + return data + if isinstance(data, list): + return [self._ExpandVariables(v, substitutions) for v in data] + if isinstance(data, dict): + return dict((k, self._ExpandVariables(data[k], + substitutions)) for k in data) + return data + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) diff --git a/node_modules/mongodb/node_modules/kerberos/build/kerberos.target.mk b/node_modules/mongodb/node_modules/kerberos/build/kerberos.target.mk new file mode 100644 index 0000000..3df1650 --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/build/kerberos.target.mk @@ -0,0 +1,172 @@ +# This file is generated by gyp; do not edit. + +TOOLSET := target +TARGET := kerberos +DEFS_Debug := \ + '-D_DARWIN_USE_64_BIT_INODE=1' \ + '-D_LARGEFILE_SOURCE' \ + '-D_FILE_OFFSET_BITS=64' \ + '-D__MACOSX_CORE__' \ + '-DBUILDING_NODE_EXTENSION' \ + '-DDEBUG' \ + '-D_DEBUG' + +# Flags passed to all source files. +CFLAGS_Debug := \ + -O0 \ + -gdwarf-2 \ + -mmacosx-version-min=10.5 \ + -arch x86_64 \ + -Wall \ + -Wendif-labels \ + -W \ + -Wno-unused-parameter + +# Flags passed to only C files. +CFLAGS_C_Debug := \ + -fno-strict-aliasing + +# Flags passed to only C++ files. +CFLAGS_CC_Debug := \ + -fno-rtti \ + -fno-threadsafe-statics \ + -fno-strict-aliasing + +# Flags passed to only ObjC files. +CFLAGS_OBJC_Debug := + +# Flags passed to only ObjC++ files. +CFLAGS_OBJCC_Debug := + +INCS_Debug := \ + -I/Users/voxfeed_1/.node-gyp/0.10.31/src \ + -I/Users/voxfeed_1/.node-gyp/0.10.31/deps/uv/include \ + -I/Users/voxfeed_1/.node-gyp/0.10.31/deps/v8/include \ + -I$(srcdir)/node_modules/nan \ + -I/usr/include/mit-krb5 + +DEFS_Release := \ + '-D_DARWIN_USE_64_BIT_INODE=1' \ + '-D_LARGEFILE_SOURCE' \ + '-D_FILE_OFFSET_BITS=64' \ + '-D__MACOSX_CORE__' \ + '-DBUILDING_NODE_EXTENSION' + +# Flags passed to all source files. +CFLAGS_Release := \ + -Os \ + -gdwarf-2 \ + -mmacosx-version-min=10.5 \ + -arch x86_64 \ + -Wall \ + -Wendif-labels \ + -W \ + -Wno-unused-parameter + +# Flags passed to only C files. +CFLAGS_C_Release := \ + -fno-strict-aliasing + +# Flags passed to only C++ files. +CFLAGS_CC_Release := \ + -fno-rtti \ + -fno-threadsafe-statics \ + -fno-strict-aliasing + +# Flags passed to only ObjC files. +CFLAGS_OBJC_Release := + +# Flags passed to only ObjC++ files. +CFLAGS_OBJCC_Release := + +INCS_Release := \ + -I/Users/voxfeed_1/.node-gyp/0.10.31/src \ + -I/Users/voxfeed_1/.node-gyp/0.10.31/deps/uv/include \ + -I/Users/voxfeed_1/.node-gyp/0.10.31/deps/v8/include \ + -I$(srcdir)/node_modules/nan \ + -I/usr/include/mit-krb5 + +OBJS := \ + $(obj).target/$(TARGET)/lib/kerberos.o \ + $(obj).target/$(TARGET)/lib/worker.o \ + $(obj).target/$(TARGET)/lib/kerberosgss.o \ + $(obj).target/$(TARGET)/lib/base64.o \ + $(obj).target/$(TARGET)/lib/kerberos_context.o + +# Add to the list of files we specially track dependencies for. +all_deps += $(OBJS) + +# CFLAGS et al overrides must be target-local. +# See "Target-specific Variable Values" in the GNU Make manual. +$(OBJS): TOOLSET := $(TOOLSET) +$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) +$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) +$(OBJS): GYP_OBJCFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) $(CFLAGS_OBJC_$(BUILDTYPE)) +$(OBJS): GYP_OBJCXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) $(CFLAGS_OBJCC_$(BUILDTYPE)) + +# Suffix rules, putting all outputs into $(obj). + +$(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) + +$(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.c FORCE_DO_CMD + @$(call do_cmd,cc,1) + +# Try building from generated source, too. + +$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) + +$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD + @$(call do_cmd,cc,1) + +$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) + +$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.c FORCE_DO_CMD + @$(call do_cmd,cc,1) + +# End of this set of suffix rules +### Rules for final target. +LDFLAGS_Debug := \ + -Wl,-search_paths_first \ + -mmacosx-version-min=10.5 \ + -arch x86_64 \ + -L$(builddir) + +LIBTOOLFLAGS_Debug := \ + -Wl,-search_paths_first + +LDFLAGS_Release := \ + -Wl,-search_paths_first \ + -mmacosx-version-min=10.5 \ + -arch x86_64 \ + -L$(builddir) + +LIBTOOLFLAGS_Release := \ + -Wl,-search_paths_first + +LIBS := \ + -undefined dynamic_lookup \ + -lkrb5 + +$(builddir)/kerberos.node: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE)) +$(builddir)/kerberos.node: LIBS := $(LIBS) +$(builddir)/kerberos.node: GYP_LIBTOOLFLAGS := $(LIBTOOLFLAGS_$(BUILDTYPE)) +$(builddir)/kerberos.node: TOOLSET := $(TOOLSET) +$(builddir)/kerberos.node: $(OBJS) FORCE_DO_CMD + $(call do_cmd,solink_module) + +all_deps += $(builddir)/kerberos.node +# Add target alias +.PHONY: kerberos +kerberos: $(builddir)/kerberos.node + +# Short alias for building this executable. +.PHONY: kerberos.node +kerberos.node: $(builddir)/kerberos.node + +# Add executable to "all" target. +.PHONY: all +all: $(builddir)/kerberos.node + diff --git a/node_modules/mongodb/node_modules/kerberos/builderror.log b/node_modules/mongodb/node_modules/kerberos/builderror.log new file mode 100644 index 0000000..ed23681 --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/builderror.log @@ -0,0 +1,23 @@ +xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance + +xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance + +../lib/kerberos.cc:79:3: error: use of undeclared identifier 'scope' + NanReturnValue(args.This()); + ^ +../node_modules/nan/nan.h:1281:39: note: expanded from macro 'NanReturnValue' +# define NanReturnValue(value) return scope.Close(value) + ^ +1 error generated. +make: *** [Release/obj.target/kerberos/lib/kerberos.o] Error 1 +gyp ERR! build error +gyp ERR! stack Error: `make` failed with exit code: 2 +gyp ERR! stack at ChildProcess.onExit (/usr/local/lib/node_modules/npm/node_modules/node-gyp/lib/build.js:267:23) +gyp ERR! stack at ChildProcess.emit (events.js:98:17) +gyp ERR! stack at Process.ChildProcess._handle.onexit (child_process.js:810:12) +gyp ERR! System Darwin 13.4.0 +gyp ERR! command "node" "/usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild" +gyp ERR! cwd /Users/voxfeed_1/code/offhours/argon/node_modules/mongodb/node_modules/kerberos +gyp ERR! node -v v0.10.31 +gyp ERR! node-gyp -v v1.0.1 +gyp ERR! not ok diff --git a/node_modules/mongodb/node_modules/kerberos/index.js b/node_modules/mongodb/node_modules/kerberos/index.js new file mode 100644 index 0000000..b8c8532 --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/index.js @@ -0,0 +1,6 @@ +// Get the Kerberos library +module.exports = require('./lib/kerberos'); +// Set up the auth processes +module.exports['processes'] = { + MongoAuthProcess: require('./lib/auth_processes/mongodb').MongoAuthProcess +} \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/auth_processes/mongodb.js b/node_modules/mongodb/node_modules/kerberos/lib/auth_processes/mongodb.js new file mode 100644 index 0000000..f1e9231 --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/lib/auth_processes/mongodb.js @@ -0,0 +1,281 @@ +var format = require('util').format; + +var MongoAuthProcess = function(host, port, service_name) { + // Check what system we are on + if(process.platform == 'win32') { + this._processor = new Win32MongoProcessor(host, port, service_name); + } else { + this._processor = new UnixMongoProcessor(host, port, service_name); + } +} + +MongoAuthProcess.prototype.init = function(username, password, callback) { + this._processor.init(username, password, callback); +} + +MongoAuthProcess.prototype.transition = function(payload, callback) { + this._processor.transition(payload, callback); +} + +/******************************************************************* + * + * Win32 SSIP Processor for MongoDB + * + *******************************************************************/ +var Win32MongoProcessor = function(host, port, service_name) { + this.host = host; + this.port = port + // SSIP classes + this.ssip = require("../kerberos").SSIP; + // Set up first transition + this._transition = Win32MongoProcessor.first_transition(this); + // Set up service name + service_name = service_name || "mongodb"; + // Set up target + this.target = format("%s/%s", service_name, host); + // Number of retries + this.retries = 10; +} + +Win32MongoProcessor.prototype.init = function(username, password, callback) { + var self = this; + // Save the values used later + this.username = username; + this.password = password; + // Aquire credentials + this.ssip.SecurityCredentials.aquire_kerberos(username, password, function(err, security_credentials) { + if(err) return callback(err); + // Save credentials + self.security_credentials = security_credentials; + // Callback with success + callback(null); + }); +} + +Win32MongoProcessor.prototype.transition = function(payload, callback) { + if(this._transition == null) return callback(new Error("Transition finished")); + this._transition(payload, callback); +} + +Win32MongoProcessor.first_transition = function(self) { + return function(payload, callback) { + self.ssip.SecurityContext.initialize( + self.security_credentials, + self.target, + payload, function(err, security_context) { + if(err) return callback(err); + + // If no context try again until we have no more retries + if(!security_context.hasContext) { + if(self.retries == 0) return callback(new Error("Failed to initialize security context")); + // Update the number of retries + self.retries = self.retries - 1; + // Set next transition + return self.transition(payload, callback); + } + + // Set next transition + self._transition = Win32MongoProcessor.second_transition(self); + self.security_context = security_context; + // Return the payload + callback(null, security_context.payload); + }); + } +} + +Win32MongoProcessor.second_transition = function(self) { + return function(payload, callback) { + // Perform a step + self.security_context.initialize(self.target, payload, function(err, security_context) { + if(err) return callback(err); + + // If no context try again until we have no more retries + if(!security_context.hasContext) { + if(self.retries == 0) return callback(new Error("Failed to initialize security context")); + // Update the number of retries + self.retries = self.retries - 1; + // Set next transition + self._transition = Win32MongoProcessor.first_transition(self); + // Retry + return self.transition(payload, callback); + } + + // Set next transition + self._transition = Win32MongoProcessor.third_transition(self); + // Return the payload + callback(null, security_context.payload); + }); + } +} + +Win32MongoProcessor.third_transition = function(self) { + return function(payload, callback) { + var messageLength = 0; + // Get the raw bytes + var encryptedBytes = new Buffer(payload, 'base64'); + var encryptedMessage = new Buffer(messageLength); + // Copy first byte + encryptedBytes.copy(encryptedMessage, 0, 0, messageLength); + // Set up trailer + var securityTrailerLength = encryptedBytes.length - messageLength; + var securityTrailer = new Buffer(securityTrailerLength); + // Copy the bytes + encryptedBytes.copy(securityTrailer, 0, messageLength, securityTrailerLength); + + // Types used + var SecurityBuffer = self.ssip.SecurityBuffer; + var SecurityBufferDescriptor = self.ssip.SecurityBufferDescriptor; + + // Set up security buffers + var buffers = [ + new SecurityBuffer(SecurityBuffer.DATA, encryptedBytes) + , new SecurityBuffer(SecurityBuffer.STREAM, securityTrailer) + ]; + + // Set up the descriptor + var descriptor = new SecurityBufferDescriptor(buffers); + + // Decrypt the data + self.security_context.decryptMessage(descriptor, function(err, security_context) { + if(err) return callback(err); + + var length = 4; + if(self.username != null) { + length += self.username.length; + } + + var bytesReceivedFromServer = new Buffer(length); + bytesReceivedFromServer[0] = 0x01; // NO_PROTECTION + bytesReceivedFromServer[1] = 0x00; // NO_PROTECTION + bytesReceivedFromServer[2] = 0x00; // NO_PROTECTION + bytesReceivedFromServer[3] = 0x00; // NO_PROTECTION + + if(self.username != null) { + var authorization_id_bytes = new Buffer(self.username, 'utf8'); + authorization_id_bytes.copy(bytesReceivedFromServer, 4, 0); + } + + self.security_context.queryContextAttributes(0x00, function(err, sizes) { + if(err) return callback(err); + + var buffers = [ + new SecurityBuffer(SecurityBuffer.TOKEN, new Buffer(sizes.securityTrailer)) + , new SecurityBuffer(SecurityBuffer.DATA, bytesReceivedFromServer) + , new SecurityBuffer(SecurityBuffer.PADDING, new Buffer(sizes.blockSize)) + ] + + var descriptor = new SecurityBufferDescriptor(buffers); + + self.security_context.encryptMessage(descriptor, 0x80000001, function(err, security_context) { + if(err) return callback(err); + callback(null, security_context.payload); + }); + }); + }); + } +} + +/******************************************************************* + * + * UNIX MIT Kerberos processor + * + *******************************************************************/ +var UnixMongoProcessor = function(host, port, service_name) { + this.host = host; + this.port = port + // SSIP classes + this.Kerberos = require("../kerberos").Kerberos; + this.kerberos = new this.Kerberos(); + service_name = service_name || "mongodb"; + // Set up first transition + this._transition = UnixMongoProcessor.first_transition(this); + // Set up target + this.target = format("%s@%s", service_name, host); + // Number of retries + this.retries = 10; +} + +UnixMongoProcessor.prototype.init = function(username, password, callback) { + var self = this; + this.username = username; + this.password = password; + // Call client initiate + this.kerberos.authGSSClientInit( + self.target + , this.Kerberos.GSS_C_MUTUAL_FLAG, function(err, context) { + self.context = context; + // Return the context + callback(null, context); + }); +} + +UnixMongoProcessor.prototype.transition = function(payload, callback) { + if(this._transition == null) return callback(new Error("Transition finished")); + this._transition(payload, callback); +} + +UnixMongoProcessor.first_transition = function(self) { + return function(payload, callback) { + self.kerberos.authGSSClientStep(self.context, '', function(err, result) { + if(err) return callback(err); + // Set up the next step + self._transition = UnixMongoProcessor.second_transition(self); + // Return the payload + callback(null, self.context.response); + }) + } +} + +UnixMongoProcessor.second_transition = function(self) { + return function(payload, callback) { + self.kerberos.authGSSClientStep(self.context, payload, function(err, result) { + if(err && self.retries == 0) return callback(err); + // Attempt to re-establish a context + if(err) { + // Adjust the number of retries + self.retries = self.retries - 1; + // Call same step again + return self.transition(payload, callback); + } + + // Set up the next step + self._transition = UnixMongoProcessor.third_transition(self); + // Return the payload + callback(null, self.context.response || ''); + }); + } +} + +UnixMongoProcessor.third_transition = function(self) { + return function(payload, callback) { + // GSS Client Unwrap + self.kerberos.authGSSClientUnwrap(self.context, payload, function(err, result) { + if(err) return callback(err, false); + + // Wrap the response + self.kerberos.authGSSClientWrap(self.context, self.context.response, self.username, function(err, result) { + if(err) return callback(err, false); + // Set up the next step + self._transition = UnixMongoProcessor.fourth_transition(self); + // Return the payload + callback(null, self.context.response); + }); + }); + } +} + +UnixMongoProcessor.fourth_transition = function(self) { + return function(payload, callback) { + // Clean up context + self.kerberos.authGSSClientClean(self.context, function(err, result) { + if(err) return callback(err, false); + // Set the transition to null + self._transition = null; + // Callback with valid authentication + callback(null, true); + }); + } +} + +// Set the process +exports.MongoAuthProcess = MongoAuthProcess; \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/base64.c b/node_modules/mongodb/node_modules/kerberos/lib/base64.c new file mode 100644 index 0000000..aca0a61 --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/lib/base64.c @@ -0,0 +1,134 @@ +/** + * Copyright (c) 2006-2008 Apple Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +#include "base64.h" + +#include +#include +#include +#include + +void die2(const char *message) { + if(errno) { + perror(message); + } else { + printf("ERROR: %s\n", message); + } + + exit(1); +} + +// base64 tables +static char basis_64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static signed char index_64[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,62, -1,-1,-1,63, + 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, + 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, + -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, + 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1 +}; +#define CHAR64(c) (((c) < 0 || (c) > 127) ? -1 : index_64[(c)]) + +// base64_encode : base64 encode +// +// value : data to encode +// vlen : length of data +// (result) : new char[] - c-str of result +char *base64_encode(const unsigned char *value, int vlen) +{ + char *result = (char *)malloc((vlen * 4) / 3 + 5); + if(result == NULL) die2("Memory allocation failed"); + char *out = result; + while (vlen >= 3) + { + *out++ = basis_64[value[0] >> 2]; + *out++ = basis_64[((value[0] << 4) & 0x30) | (value[1] >> 4)]; + *out++ = basis_64[((value[1] << 2) & 0x3C) | (value[2] >> 6)]; + *out++ = basis_64[value[2] & 0x3F]; + value += 3; + vlen -= 3; + } + if (vlen > 0) + { + *out++ = basis_64[value[0] >> 2]; + unsigned char oval = (value[0] << 4) & 0x30; + if (vlen > 1) oval |= value[1] >> 4; + *out++ = basis_64[oval]; + *out++ = (vlen < 2) ? '=' : basis_64[(value[1] << 2) & 0x3C]; + *out++ = '='; + } + *out = '\0'; + + return result; +} + +// base64_decode : base64 decode +// +// value : c-str to decode +// rlen : length of decoded result +// (result) : new unsigned char[] - decoded result +unsigned char *base64_decode(const char *value, int *rlen) +{ + *rlen = 0; + int c1, c2, c3, c4; + + int vlen = strlen(value); + unsigned char *result =(unsigned char *)malloc((vlen * 3) / 4 + 1); + if(result == NULL) die2("Memory allocation failed"); + unsigned char *out = result; + + while (1) + { + if (value[0]==0) + return result; + c1 = value[0]; + if (CHAR64(c1) == -1) + goto base64_decode_error;; + c2 = value[1]; + if (CHAR64(c2) == -1) + goto base64_decode_error;; + c3 = value[2]; + if ((c3 != '=') && (CHAR64(c3) == -1)) + goto base64_decode_error;; + c4 = value[3]; + if ((c4 != '=') && (CHAR64(c4) == -1)) + goto base64_decode_error;; + + value += 4; + *out++ = (CHAR64(c1) << 2) | (CHAR64(c2) >> 4); + *rlen += 1; + if (c3 != '=') + { + *out++ = ((CHAR64(c2) << 4) & 0xf0) | (CHAR64(c3) >> 2); + *rlen += 1; + if (c4 != '=') + { + *out++ = ((CHAR64(c3) << 6) & 0xc0) | CHAR64(c4); + *rlen += 1; + } + } + } + +base64_decode_error: + *result = 0; + *rlen = 0; + return result; +} diff --git a/node_modules/mongodb/node_modules/kerberos/lib/base64.h b/node_modules/mongodb/node_modules/kerberos/lib/base64.h new file mode 100644 index 0000000..9152e6a --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/lib/base64.h @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2006-2008 Apple Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +#ifndef BASE64_H +#define BASE64_H + +char *base64_encode(const unsigned char *value, int vlen); +unsigned char *base64_decode(const char *value, int *rlen); + +#endif \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/kerberos.cc b/node_modules/mongodb/node_modules/kerberos/lib/kerberos.cc new file mode 100644 index 0000000..4e2bc85 --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/lib/kerberos.cc @@ -0,0 +1,591 @@ +#include "kerberos.h" +#include +#include +#include "worker.h" +#include "kerberos_context.h" + +#ifndef ARRAY_SIZE +# define ARRAY_SIZE(a) (sizeof((a)) / sizeof((a)[0])) +#endif + +void die(const char *message) { + if(errno) { + perror(message); + } else { + printf("ERROR: %s\n", message); + } + + exit(1); +} + +// Call structs +typedef struct AuthGSSClientCall { + uint32_t flags; + char *uri; +} AuthGSSClientCall; + +typedef struct AuthGSSClientStepCall { + KerberosContext *context; + char *challenge; +} AuthGSSClientStepCall; + +typedef struct AuthGSSClientUnwrapCall { + KerberosContext *context; + char *challenge; +} AuthGSSClientUnwrapCall; + +typedef struct AuthGSSClientWrapCall { + KerberosContext *context; + char *challenge; + char *user_name; +} AuthGSSClientWrapCall; + +typedef struct AuthGSSClientCleanCall { + KerberosContext *context; +} AuthGSSClientCleanCall; + +Kerberos::Kerberos() : ObjectWrap() { +} + +Persistent Kerberos::constructor_template; + +void Kerberos::Initialize(v8::Handle target) { + // Grab the scope of the call from Node + NanScope(); + + // Define a new function template + Local t = NanNew(New); + t->InstanceTemplate()->SetInternalFieldCount(1); + t->SetClassName(NanNew("Kerberos")); + + // Set up method for the Kerberos instance + NODE_SET_PROTOTYPE_METHOD(t, "authGSSClientInit", AuthGSSClientInit); + NODE_SET_PROTOTYPE_METHOD(t, "authGSSClientStep", AuthGSSClientStep); + NODE_SET_PROTOTYPE_METHOD(t, "authGSSClientUnwrap", AuthGSSClientUnwrap); + NODE_SET_PROTOTYPE_METHOD(t, "authGSSClientWrap", AuthGSSClientWrap); + NODE_SET_PROTOTYPE_METHOD(t, "authGSSClientClean", AuthGSSClientClean); + + NanAssignPersistent(constructor_template, t); + + // Set the symbol + target->ForceSet(NanNew("Kerberos"), t->GetFunction()); +} + +NAN_METHOD(Kerberos::New) { + // Create a Kerberos instance + Kerberos *kerberos = new Kerberos(); + // Return the kerberos object + kerberos->Wrap(args.This()); + NanReturnValue(args.This()); +} + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// authGSSClientInit +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +static void _authGSSClientInit(Worker *worker) { + gss_client_state *state; + gss_client_response *response; + + // Allocate state + state = (gss_client_state *)malloc(sizeof(gss_client_state)); + if(state == NULL) die("Memory allocation failed"); + + // Unpack the parameter data struct + AuthGSSClientCall *call = (AuthGSSClientCall *)worker->parameters; + // Start the kerberos client + response = authenticate_gss_client_init(call->uri, call->flags, state); + + // Release the parameter struct memory + free(call->uri); + free(call); + + // If we have an error mark worker as having had an error + if(response->return_code == AUTH_GSS_ERROR) { + worker->error = TRUE; + worker->error_code = response->return_code; + worker->error_message = response->message; + free(state); + } else { + worker->return_value = state; + } + + // Free structure + free(response); +} + +static Handle _map_authGSSClientInit(Worker *worker) { + KerberosContext *context = KerberosContext::New(); + context->state = (gss_client_state *)worker->return_value; + return NanObjectWrapHandle(context); +} + +// Initialize method +NAN_METHOD(Kerberos::AuthGSSClientInit) { + NanScope(); + + // Ensure valid call + if(args.Length() != 3) return NanThrowError("Requires a service string uri, integer flags and a callback function"); + if(args.Length() == 3 && !args[0]->IsString() && !args[1]->IsInt32() && !args[2]->IsFunction()) + return NanThrowError("Requires a service string uri, integer flags and a callback function"); + + Local service = args[0]->ToString(); + // Convert uri string to c-string + char *service_str = (char *)calloc(service->Utf8Length() + 1, sizeof(char)); + if(service_str == NULL) die("Memory allocation failed"); + + // Write v8 string to c-string + service->WriteUtf8(service_str); + + // Allocate a structure + AuthGSSClientCall *call = (AuthGSSClientCall *)calloc(1, sizeof(AuthGSSClientCall)); + if(call == NULL) die("Memory allocation failed"); + call->flags =args[1]->ToInt32()->Uint32Value(); + call->uri = service_str; + + // Unpack the callback + Local callbackHandle = Local::Cast(args[2]); + NanCallback *callback = new NanCallback(callbackHandle); + + // Let's allocate some space + Worker *worker = new Worker(); + worker->error = false; + worker->request.data = worker; + worker->callback = callback; + worker->parameters = call; + worker->execute = _authGSSClientInit; + worker->mapper = _map_authGSSClientInit; + + // Schedule the worker with lib_uv + uv_queue_work(uv_default_loop(), &worker->request, Kerberos::Process, (uv_after_work_cb)Kerberos::After); + // Return no value as it's callback based + NanReturnValue(NanUndefined()); +} + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// authGSSClientStep +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +static void _authGSSClientStep(Worker *worker) { + gss_client_state *state; + gss_client_response *response; + char *challenge; + + // Unpack the parameter data struct + AuthGSSClientStepCall *call = (AuthGSSClientStepCall *)worker->parameters; + // Get the state + state = call->context->state; + challenge = call->challenge; + + // Check what kind of challenge we have + if(call->challenge == NULL) { + challenge = (char *)""; + } + + // Perform authentication step + response = authenticate_gss_client_step(state, challenge); + + // If we have an error mark worker as having had an error + if(response->return_code == AUTH_GSS_ERROR) { + worker->error = TRUE; + worker->error_code = response->return_code; + worker->error_message = response->message; + } else { + worker->return_code = response->return_code; + } + + // Free up structure + if(call->challenge != NULL) free(call->challenge); + free(call); + free(response); +} + +static Handle _map_authGSSClientStep(Worker *worker) { + NanScope(); + // Return the return code + return NanNew(worker->return_code); +} + +// Initialize method +NAN_METHOD(Kerberos::AuthGSSClientStep) { + NanScope(); + + // Ensure valid call + if(args.Length() != 2 && args.Length() != 3) return NanThrowError("Requires a GSS context, optional challenge string and callback function"); + if(args.Length() == 2 && !KerberosContext::HasInstance(args[0])) return NanThrowError("Requires a GSS context, optional challenge string and callback function"); + if(args.Length() == 3 && !KerberosContext::HasInstance(args[0]) && !args[1]->IsString()) return NanThrowError("Requires a GSS context, optional challenge string and callback function"); + + // Challenge string + char *challenge_str = NULL; + // Let's unpack the parameters + Local object = args[0]->ToObject(); + KerberosContext *kerberos_context = KerberosContext::Unwrap(object); + + // If we have a challenge string + if(args.Length() == 3) { + // Unpack the challenge string + Local challenge = args[1]->ToString(); + // Convert uri string to c-string + challenge_str = (char *)calloc(challenge->Utf8Length() + 1, sizeof(char)); + if(challenge_str == NULL) die("Memory allocation failed"); + // Write v8 string to c-string + challenge->WriteUtf8(challenge_str); + } + + // Allocate a structure + AuthGSSClientStepCall *call = (AuthGSSClientStepCall *)calloc(1, sizeof(AuthGSSClientCall)); + if(call == NULL) die("Memory allocation failed"); + call->context = kerberos_context; + call->challenge = challenge_str; + + // Unpack the callback + Local callbackHandle = Local::Cast(args[2]); + NanCallback *callback = new NanCallback(callbackHandle); + + // Let's allocate some space + Worker *worker = new Worker(); + worker->error = false; + worker->request.data = worker; + worker->callback = callback; + worker->parameters = call; + worker->execute = _authGSSClientStep; + worker->mapper = _map_authGSSClientStep; + + // Schedule the worker with lib_uv + uv_queue_work(uv_default_loop(), &worker->request, Kerberos::Process, (uv_after_work_cb)Kerberos::After); + + // Return no value as it's callback based + NanReturnValue(NanUndefined()); +} + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// authGSSClientUnwrap +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +static void _authGSSClientUnwrap(Worker *worker) { + gss_client_response *response; + char *challenge; + + // Unpack the parameter data struct + AuthGSSClientUnwrapCall *call = (AuthGSSClientUnwrapCall *)worker->parameters; + challenge = call->challenge; + + // Check what kind of challenge we have + if(call->challenge == NULL) { + challenge = (char *)""; + } + + // Perform authentication step + response = authenticate_gss_client_unwrap(call->context->state, challenge); + + // If we have an error mark worker as having had an error + if(response->return_code == AUTH_GSS_ERROR) { + worker->error = TRUE; + worker->error_code = response->return_code; + worker->error_message = response->message; + } else { + worker->return_code = response->return_code; + } + + // Free up structure + if(call->challenge != NULL) free(call->challenge); + free(call); + free(response); +} + +static Handle _map_authGSSClientUnwrap(Worker *worker) { + NanScope(); + // Return the return code + return NanNew(worker->return_code); +} + +// Initialize method +NAN_METHOD(Kerberos::AuthGSSClientUnwrap) { + NanScope(); + + // Ensure valid call + if(args.Length() != 2 && args.Length() != 3) return NanThrowError("Requires a GSS context, optional challenge string and callback function"); + if(args.Length() == 2 && !KerberosContext::HasInstance(args[0]) && !args[1]->IsFunction()) return NanThrowError("Requires a GSS context, optional challenge string and callback function"); + if(args.Length() == 3 && !KerberosContext::HasInstance(args[0]) && !args[1]->IsString() && !args[2]->IsFunction()) return NanThrowError("Requires a GSS context, optional challenge string and callback function"); + + // Challenge string + char *challenge_str = NULL; + // Let's unpack the parameters + Local object = args[0]->ToObject(); + KerberosContext *kerberos_context = KerberosContext::Unwrap(object); + + // If we have a challenge string + if(args.Length() == 3) { + // Unpack the challenge string + Local challenge = args[1]->ToString(); + // Convert uri string to c-string + challenge_str = (char *)calloc(challenge->Utf8Length() + 1, sizeof(char)); + if(challenge_str == NULL) die("Memory allocation failed"); + // Write v8 string to c-string + challenge->WriteUtf8(challenge_str); + } + + // Allocate a structure + AuthGSSClientUnwrapCall *call = (AuthGSSClientUnwrapCall *)calloc(1, sizeof(AuthGSSClientUnwrapCall)); + if(call == NULL) die("Memory allocation failed"); + call->context = kerberos_context; + call->challenge = challenge_str; + + // Unpack the callback + Local callbackHandle = args.Length() == 3 ? Local::Cast(args[2]) : Local::Cast(args[1]); + NanCallback *callback = new NanCallback(callbackHandle); + + // Let's allocate some space + Worker *worker = new Worker(); + worker->error = false; + worker->request.data = worker; + worker->callback = callback; + worker->parameters = call; + worker->execute = _authGSSClientUnwrap; + worker->mapper = _map_authGSSClientUnwrap; + + // Schedule the worker with lib_uv + uv_queue_work(uv_default_loop(), &worker->request, Kerberos::Process, (uv_after_work_cb)Kerberos::After); + + // Return no value as it's callback based + // return scope.Close(NanUndefined()); + NanReturnValue(NanUndefined()); +} + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// authGSSClientWrap +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +static void _authGSSClientWrap(Worker *worker) { + gss_client_response *response; + char *user_name = NULL; + + // Unpack the parameter data struct + AuthGSSClientWrapCall *call = (AuthGSSClientWrapCall *)worker->parameters; + user_name = call->user_name; + + // Check what kind of challenge we have + if(call->user_name == NULL) { + user_name = (char *)""; + } + + // Perform authentication step + response = authenticate_gss_client_wrap(call->context->state, call->challenge, user_name); + + // If we have an error mark worker as having had an error + if(response->return_code == AUTH_GSS_ERROR) { + worker->error = TRUE; + worker->error_code = response->return_code; + worker->error_message = response->message; + } else { + worker->return_code = response->return_code; + } + + // Free up structure + if(call->challenge != NULL) free(call->challenge); + if(call->user_name != NULL) free(call->user_name); + free(call); + free(response); +} + +static Handle _map_authGSSClientWrap(Worker *worker) { + NanScope(); + // Return the return code + return NanNew(worker->return_code); +} + +// Initialize method +NAN_METHOD(Kerberos::AuthGSSClientWrap) { + NanScope(); + + // Ensure valid call + if(args.Length() != 3 && args.Length() != 4) return NanThrowError("Requires a GSS context, the result from the authGSSClientResponse after authGSSClientUnwrap, optional user name and callback function"); + if(args.Length() == 3 && !KerberosContext::HasInstance(args[0]) && !args[1]->IsString() && !args[2]->IsFunction()) return NanThrowError("Requires a GSS context, the result from the authGSSClientResponse after authGSSClientUnwrap, optional user name and callback function"); + if(args.Length() == 4 && !KerberosContext::HasInstance(args[0]) && !args[1]->IsString() && !args[2]->IsString() && !args[2]->IsFunction()) return NanThrowError("Requires a GSS context, the result from the authGSSClientResponse after authGSSClientUnwrap, optional user name and callback function"); + + // Challenge string + char *challenge_str = NULL; + char *user_name_str = NULL; + + // Let's unpack the kerberos context + Local object = args[0]->ToObject(); + KerberosContext *kerberos_context = KerberosContext::Unwrap(object); + + // Unpack the challenge string + Local challenge = args[1]->ToString(); + // Convert uri string to c-string + challenge_str = (char *)calloc(challenge->Utf8Length() + 1, sizeof(char)); + if(challenge_str == NULL) die("Memory allocation failed"); + // Write v8 string to c-string + challenge->WriteUtf8(challenge_str); + + // If we have a user string + if(args.Length() == 4) { + // Unpack user name + Local user_name = args[2]->ToString(); + // Convert uri string to c-string + user_name_str = (char *)calloc(user_name->Utf8Length() + 1, sizeof(char)); + if(user_name_str == NULL) die("Memory allocation failed"); + // Write v8 string to c-string + user_name->WriteUtf8(user_name_str); + } + + // Allocate a structure + AuthGSSClientWrapCall *call = (AuthGSSClientWrapCall *)calloc(1, sizeof(AuthGSSClientWrapCall)); + if(call == NULL) die("Memory allocation failed"); + call->context = kerberos_context; + call->challenge = challenge_str; + call->user_name = user_name_str; + + // Unpack the callback + Local callbackHandle = args.Length() == 4 ? Local::Cast(args[3]) : Local::Cast(args[2]); + NanCallback *callback = new NanCallback(callbackHandle); + + // Let's allocate some space + Worker *worker = new Worker(); + worker->error = false; + worker->request.data = worker; + worker->callback = callback; + worker->parameters = call; + worker->execute = _authGSSClientWrap; + worker->mapper = _map_authGSSClientWrap; + + // Schedule the worker with lib_uv + uv_queue_work(uv_default_loop(), &worker->request, Kerberos::Process, (uv_after_work_cb)Kerberos::After); + + // Return no value as it's callback based + NanReturnValue(NanUndefined()); +} + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// authGSSClientWrap +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +static void _authGSSClientClean(Worker *worker) { + gss_client_response *response; + + // Unpack the parameter data struct + AuthGSSClientCleanCall *call = (AuthGSSClientCleanCall *)worker->parameters; + + // Perform authentication step + response = authenticate_gss_client_clean(call->context->state); + + // If we have an error mark worker as having had an error + if(response->return_code == AUTH_GSS_ERROR) { + worker->error = TRUE; + worker->error_code = response->return_code; + worker->error_message = response->message; + } else { + worker->return_code = response->return_code; + } + + // Free up structure + free(call); + free(response); +} + +static Handle _map_authGSSClientClean(Worker *worker) { + NanScope(); + // Return the return code + return NanNew(worker->return_code); +} + +// Initialize method +NAN_METHOD(Kerberos::AuthGSSClientClean) { + NanScope(); + + // // Ensure valid call + if(args.Length() != 2) return NanThrowError("Requires a GSS context and callback function"); + if(!KerberosContext::HasInstance(args[0]) && !args[1]->IsFunction()) return NanThrowError("Requires a GSS context and callback function"); + + // Let's unpack the kerberos context + Local object = args[0]->ToObject(); + KerberosContext *kerberos_context = KerberosContext::Unwrap(object); + + // Allocate a structure + AuthGSSClientCleanCall *call = (AuthGSSClientCleanCall *)calloc(1, sizeof(AuthGSSClientCleanCall)); + if(call == NULL) die("Memory allocation failed"); + call->context = kerberos_context; + + // Unpack the callback + Local callbackHandle = Local::Cast(args[1]); + NanCallback *callback = new NanCallback(callbackHandle); + + // Let's allocate some space + Worker *worker = new Worker(); + worker->error = false; + worker->request.data = worker; + worker->callback = callback; + worker->parameters = call; + worker->execute = _authGSSClientClean; + worker->mapper = _map_authGSSClientClean; + + // Schedule the worker with lib_uv + uv_queue_work(uv_default_loop(), &worker->request, Kerberos::Process, (uv_after_work_cb)Kerberos::After); + + // Return no value as it's callback based + NanReturnValue(NanUndefined()); +} + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// UV Lib callbacks +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +void Kerberos::Process(uv_work_t* work_req) { + // Grab the worker + Worker *worker = static_cast(work_req->data); + // Execute the worker code + worker->execute(worker); +} + +void Kerberos::After(uv_work_t* work_req) { + // Grab the scope of the call from Node + NanScope(); + + // Get the worker reference + Worker *worker = static_cast(work_req->data); + + // If we have an error + if(worker->error) { + Local err = v8::Exception::Error(NanNew(worker->error_message)); + Local obj = err->ToObject(); + obj->Set(NanNew("code"), NanNew(worker->error_code)); + Local args[2] = { err, NanNull() }; + // Execute the error + v8::TryCatch try_catch; + + // Call the callback + worker->callback->Call(ARRAY_SIZE(args), args); + + // If we have an exception handle it as a fatalexception + if (try_catch.HasCaught()) { + node::FatalException(try_catch); + } + } else { + // // Map the data + Handle result = worker->mapper(worker); + // Set up the callback with a null first + Handle args[2] = { NanNull(), result}; + + // Wrap the callback function call in a TryCatch so that we can call + // node's FatalException afterwards. This makes it possible to catch + // the exception from JavaScript land using the + // process.on('uncaughtException') event. + v8::TryCatch try_catch; + + // Call the callback + worker->callback->Call(ARRAY_SIZE(args), args); + + // If we have an exception handle it as a fatalexception + if (try_catch.HasCaught()) { + node::FatalException(try_catch); + } + } + + // Clean up the memory + delete worker->callback; + delete worker; +} + +// Exporting function +extern "C" void init(Handle target) { + NanScope(); + Kerberos::Initialize(target); + KerberosContext::Initialize(target); +} + +NODE_MODULE(kerberos, init); diff --git a/node_modules/mongodb/node_modules/kerberos/lib/kerberos.h b/node_modules/mongodb/node_modules/kerberos/lib/kerberos.h new file mode 100644 index 0000000..b037d4e --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/lib/kerberos.h @@ -0,0 +1,49 @@ +#ifndef KERBEROS_H +#define KERBEROS_H + +#include +#include +#include +#include + +#include "nan.h" +#include +#include + +#include "util.h" + +extern "C" { + #include "kerberosgss.h" +} + +using namespace v8; +using namespace node; + +class Kerberos : public ObjectWrap { + +public: + Kerberos(); + ~Kerberos() {}; + + // Constructor used for creating new Kerberos objects from C++ + static Persistent constructor_template; + + // Initialize function for the object + static void Initialize(Handle target); + + // Method available + static NAN_METHOD(AuthGSSClientInit); + static NAN_METHOD(AuthGSSClientStep); + static NAN_METHOD(AuthGSSClientUnwrap); + static NAN_METHOD(AuthGSSClientWrap); + static NAN_METHOD(AuthGSSClientClean); + +private: + static NAN_METHOD(New); + // Handles the uv calls + static void Process(uv_work_t* work_req); + // Called after work is done + static void After(uv_work_t* work_req); +}; + +#endif \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/kerberos.js b/node_modules/mongodb/node_modules/kerberos/lib/kerberos.js new file mode 100644 index 0000000..b1a701b --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/lib/kerberos.js @@ -0,0 +1,91 @@ +var kerberos = require('../build/Release/kerberos') + , KerberosNative = kerberos.Kerberos; + +var Kerberos = function() { + this._native_kerberos = new KerberosNative(); +} + +Kerberos.prototype.authGSSClientInit = function(uri, flags, callback) { + return this._native_kerberos.authGSSClientInit(uri, flags, callback); +} + +Kerberos.prototype.authGSSClientStep = function(context, challenge, callback) { + if(typeof challenge == 'function') { + callback = challenge; + challenge = ''; + } + + return this._native_kerberos.authGSSClientStep(context, challenge, callback); +} + +Kerberos.prototype.authGSSClientUnwrap = function(context, challenge, callback) { + if(typeof challenge == 'function') { + callback = challenge; + challenge = ''; + } + + return this._native_kerberos.authGSSClientUnwrap(context, challenge, callback); +} + +Kerberos.prototype.authGSSClientWrap = function(context, challenge, user_name, callback) { + if(typeof user_name == 'function') { + callback = user_name; + user_name = ''; + } + + return this._native_kerberos.authGSSClientWrap(context, challenge, user_name, callback); +} + +Kerberos.prototype.authGSSClientClean = function(context, callback) { + return this._native_kerberos.authGSSClientClean(context, callback); +} + +Kerberos.prototype.acquireAlternateCredentials = function(user_name, password, domain) { + return this._native_kerberos.acquireAlternateCredentials(user_name, password, domain); +} + +Kerberos.prototype.prepareOutboundPackage = function(principal, inputdata) { + return this._native_kerberos.prepareOutboundPackage(principal, inputdata); +} + +Kerberos.prototype.decryptMessage = function(challenge) { + return this._native_kerberos.decryptMessage(challenge); +} + +Kerberos.prototype.encryptMessage = function(challenge) { + return this._native_kerberos.encryptMessage(challenge); +} + +Kerberos.prototype.queryContextAttribute = function(attribute) { + if(typeof attribute != 'number' && attribute != 0x00) throw new Error("Attribute not supported"); + return this._native_kerberos.queryContextAttribute(attribute); +} + +// Some useful result codes +Kerberos.AUTH_GSS_CONTINUE = 0; +Kerberos.AUTH_GSS_COMPLETE = 1; + +// Some useful gss flags +Kerberos.GSS_C_DELEG_FLAG = 1; +Kerberos.GSS_C_MUTUAL_FLAG = 2; +Kerberos.GSS_C_REPLAY_FLAG = 4; +Kerberos.GSS_C_SEQUENCE_FLAG = 8; +Kerberos.GSS_C_CONF_FLAG = 16; +Kerberos.GSS_C_INTEG_FLAG = 32; +Kerberos.GSS_C_ANON_FLAG = 64; +Kerberos.GSS_C_PROT_READY_FLAG = 128; +Kerberos.GSS_C_TRANS_FLAG = 256; + +// Export Kerberos class +exports.Kerberos = Kerberos; + +// If we have SSPI (windows) +if(kerberos.SecurityCredentials) { + // Put all SSPI classes in it's own namespace + exports.SSIP = { + SecurityCredentials: require('./win32/wrappers/security_credentials').SecurityCredentials + , SecurityContext: require('./win32/wrappers/security_context').SecurityContext + , SecurityBuffer: require('./win32/wrappers/security_buffer').SecurityBuffer + , SecurityBufferDescriptor: require('./win32/wrappers/security_buffer_descriptor').SecurityBufferDescriptor + } +} diff --git a/node_modules/mongodb/node_modules/kerberos/lib/kerberos_context.cc b/node_modules/mongodb/node_modules/kerberos/lib/kerberos_context.cc new file mode 100644 index 0000000..de32aad --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/lib/kerberos_context.cc @@ -0,0 +1,76 @@ +#include "kerberos_context.h" + +Persistent KerberosContext::constructor_template; + +KerberosContext::KerberosContext() : ObjectWrap() { +} + +KerberosContext::~KerberosContext() { +} + +KerberosContext* KerberosContext::New() { + NanScope(); + Local obj = NanNew(constructor_template)->GetFunction()->NewInstance(); + KerberosContext *kerberos_context = ObjectWrap::Unwrap(obj); + return kerberos_context; +} + +NAN_METHOD(KerberosContext::New) { + NanScope(); + // Create code object + KerberosContext *kerberos_context = new KerberosContext(); + // Wrap it + kerberos_context->Wrap(args.This()); + // Return the object + NanReturnValue(args.This()); +} + +void KerberosContext::Initialize(v8::Handle target) { + // Grab the scope of the call from Node + NanScope(); + + // Define a new function template + Local t = NanNew(New); + t->InstanceTemplate()->SetInternalFieldCount(1); + t->SetClassName(NanNew("KerberosContext")); + + // Get prototype + Local proto = t->PrototypeTemplate(); + + // Getter for the response + proto->SetAccessor(NanNew("response"), KerberosContext::ResponseGetter); + + // Set persistent + NanAssignPersistent(constructor_template, t); + + // Set the symbol + target->ForceSet(NanNew("KerberosContext"), t->GetFunction()); +} + +// +// Response Setter / Getter +NAN_GETTER(KerberosContext::ResponseGetter) { + NanScope(); + gss_client_state *state; + + // Unpack the object + KerberosContext *context = ObjectWrap::Unwrap(args.This()); + // Let's grab the response + state = context->state; + // No state no response + if(state == NULL || state->response == NULL) { + NanReturnValue(NanNull()); + } else { + // Return the response + NanReturnValue(NanNew(state->response)); + } +} + + + + + + + + + diff --git a/node_modules/mongodb/node_modules/kerberos/lib/kerberos_context.h b/node_modules/mongodb/node_modules/kerberos/lib/kerberos_context.h new file mode 100644 index 0000000..dd00f1d --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/lib/kerberos_context.h @@ -0,0 +1,48 @@ +#ifndef KERBEROS_CONTEXT_H +#define KERBEROS_CONTEXT_H + +#include +#include +#include +#include + +#include "nan.h" +#include +#include + +extern "C" { + #include "kerberosgss.h" +} + +using namespace v8; +using namespace node; + +class KerberosContext : public ObjectWrap { + +public: + KerberosContext(); + ~KerberosContext(); + + static inline bool HasInstance(Handle val) { + if (!val->IsObject()) return false; + Local obj = val->ToObject(); + return NanNew(constructor_template)->HasInstance(obj); + }; + + // Constructor used for creating new Kerberos objects from C++ + static Persistent constructor_template; + + // Initialize function for the object + static void Initialize(Handle target); + + // Public constructor + static KerberosContext* New(); + + // Handle to the kerberos context + gss_client_state *state; + +private: + static NAN_METHOD(New); + static NAN_GETTER(ResponseGetter); +}; +#endif \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/kerberosgss.c b/node_modules/mongodb/node_modules/kerberos/lib/kerberosgss.c new file mode 100644 index 0000000..8e55b62 --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/lib/kerberosgss.c @@ -0,0 +1,693 @@ +/** + * Copyright (c) 2006-2010 Apple Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +#include "kerberosgss.h" + +#include "base64.h" + +#include +#include +#include +#include +#include + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +void die1(const char *message) { + if(errno) { + perror(message); + } else { + printf("ERROR: %s\n", message); + } + + exit(1); +} + +static void set_gss_error(OM_uint32 err_maj, OM_uint32 err_min); + +/*extern PyObject *GssException_class; +extern PyObject *KrbException_class; + +char* server_principal_details(const char* service, const char* hostname) +{ + char match[1024]; + int match_len = 0; + char* result = NULL; + + int code; + krb5_context kcontext; + krb5_keytab kt = NULL; + krb5_kt_cursor cursor = NULL; + krb5_keytab_entry entry; + char* pname = NULL; + + // Generate the principal prefix we want to match + snprintf(match, 1024, "%s/%s@", service, hostname); + match_len = strlen(match); + + code = krb5_init_context(&kcontext); + if (code) + { + PyErr_SetObject(KrbException_class, Py_BuildValue("((s:i))", + "Cannot initialize Kerberos5 context", code)); + return NULL; + } + + if ((code = krb5_kt_default(kcontext, &kt))) + { + PyErr_SetObject(KrbException_class, Py_BuildValue("((s:i))", + "Cannot get default keytab", code)); + goto end; + } + + if ((code = krb5_kt_start_seq_get(kcontext, kt, &cursor))) + { + PyErr_SetObject(KrbException_class, Py_BuildValue("((s:i))", + "Cannot get sequence cursor from keytab", code)); + goto end; + } + + while ((code = krb5_kt_next_entry(kcontext, kt, &entry, &cursor)) == 0) + { + if ((code = krb5_unparse_name(kcontext, entry.principal, &pname))) + { + PyErr_SetObject(KrbException_class, Py_BuildValue("((s:i))", + "Cannot parse principal name from keytab", code)); + goto end; + } + + if (strncmp(pname, match, match_len) == 0) + { + result = malloc(strlen(pname) + 1); + strcpy(result, pname); + krb5_free_unparsed_name(kcontext, pname); + krb5_free_keytab_entry_contents(kcontext, &entry); + break; + } + + krb5_free_unparsed_name(kcontext, pname); + krb5_free_keytab_entry_contents(kcontext, &entry); + } + + if (result == NULL) + { + PyErr_SetObject(KrbException_class, Py_BuildValue("((s:i))", + "Principal not found in keytab", -1)); + } + +end: + if (cursor) + krb5_kt_end_seq_get(kcontext, kt, &cursor); + if (kt) + krb5_kt_close(kcontext, kt); + krb5_free_context(kcontext); + + return result; +} +*/ +gss_client_response *authenticate_gss_client_init(const char* service, long int gss_flags, gss_client_state* state) { + OM_uint32 maj_stat; + OM_uint32 min_stat; + gss_buffer_desc name_token = GSS_C_EMPTY_BUFFER; + gss_client_response *response = NULL; + int ret = AUTH_GSS_COMPLETE; + + state->server_name = GSS_C_NO_NAME; + state->context = GSS_C_NO_CONTEXT; + state->gss_flags = gss_flags; + state->username = NULL; + state->response = NULL; + + // Import server name first + name_token.length = strlen(service); + name_token.value = (char *)service; + + maj_stat = gss_import_name(&min_stat, &name_token, gss_krb5_nt_service_name, &state->server_name); + + if (GSS_ERROR(maj_stat)) { + response = gss_error(maj_stat, min_stat); + response->return_code = AUTH_GSS_ERROR; + goto end; + } + +end: + if(response == NULL) { + response = calloc(1, sizeof(gss_client_response)); + if(response == NULL) die1("Memory allocation failed"); + response->return_code = ret; + } + + return response; +} + +gss_client_response *authenticate_gss_client_clean(gss_client_state *state) { + OM_uint32 min_stat; + int ret = AUTH_GSS_COMPLETE; + gss_client_response *response = NULL; + + if(state->context != GSS_C_NO_CONTEXT) + gss_delete_sec_context(&min_stat, &state->context, GSS_C_NO_BUFFER); + + if(state->server_name != GSS_C_NO_NAME) + gss_release_name(&min_stat, &state->server_name); + + if(state->username != NULL) { + free(state->username); + state->username = NULL; + } + + if (state->response != NULL) { + free(state->response); + state->response = NULL; + } + + if(response == NULL) { + response = calloc(1, sizeof(gss_client_response)); + if(response == NULL) die1("Memory allocation failed"); + response->return_code = ret; + } + + return response; +} + +gss_client_response *authenticate_gss_client_step(gss_client_state* state, const char* challenge) { + OM_uint32 maj_stat; + OM_uint32 min_stat; + gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; + int ret = AUTH_GSS_CONTINUE; + gss_client_response *response = NULL; + + // Always clear out the old response + if (state->response != NULL) { + free(state->response); + state->response = NULL; + } + + // If there is a challenge (data from the server) we need to give it to GSS + if (challenge && *challenge) { + int len; + input_token.value = base64_decode(challenge, &len); + input_token.length = len; + } + + // Do GSSAPI step + maj_stat = gss_init_sec_context(&min_stat, + GSS_C_NO_CREDENTIAL, + &state->context, + state->server_name, + GSS_C_NO_OID, + (OM_uint32)state->gss_flags, + 0, + GSS_C_NO_CHANNEL_BINDINGS, + &input_token, + NULL, + &output_token, + NULL, + NULL); + + if ((maj_stat != GSS_S_COMPLETE) && (maj_stat != GSS_S_CONTINUE_NEEDED)) { + response = gss_error(maj_stat, min_stat); + response->return_code = AUTH_GSS_ERROR; + goto end; + } + + ret = (maj_stat == GSS_S_COMPLETE) ? AUTH_GSS_COMPLETE : AUTH_GSS_CONTINUE; + // Grab the client response to send back to the server + if(output_token.length) { + state->response = base64_encode((const unsigned char *)output_token.value, output_token.length); + maj_stat = gss_release_buffer(&min_stat, &output_token); + } + + // Try to get the user name if we have completed all GSS operations + if (ret == AUTH_GSS_COMPLETE) { + gss_name_t gssuser = GSS_C_NO_NAME; + maj_stat = gss_inquire_context(&min_stat, state->context, &gssuser, NULL, NULL, NULL, NULL, NULL, NULL); + + if(GSS_ERROR(maj_stat)) { + response = gss_error(maj_stat, min_stat); + response->return_code = AUTH_GSS_ERROR; + goto end; + } + + gss_buffer_desc name_token; + name_token.length = 0; + maj_stat = gss_display_name(&min_stat, gssuser, &name_token, NULL); + + if(GSS_ERROR(maj_stat)) { + if(name_token.value) + gss_release_buffer(&min_stat, &name_token); + gss_release_name(&min_stat, &gssuser); + + response = gss_error(maj_stat, min_stat); + response->return_code = AUTH_GSS_ERROR; + goto end; + } else { + state->username = (char *)malloc(name_token.length + 1); + if(state->username == NULL) die1("Memory allocation failed"); + strncpy(state->username, (char*) name_token.value, name_token.length); + state->username[name_token.length] = 0; + gss_release_buffer(&min_stat, &name_token); + gss_release_name(&min_stat, &gssuser); + } + } + +end: + if(output_token.value) + gss_release_buffer(&min_stat, &output_token); + if(input_token.value) + free(input_token.value); + + if(response == NULL) { + response = calloc(1, sizeof(gss_client_response)); + if(response == NULL) die1("Memory allocation failed"); + response->return_code = ret; + } + + // Return the response + return response; +} + +gss_client_response *authenticate_gss_client_unwrap(gss_client_state *state, const char *challenge) { + OM_uint32 maj_stat; + OM_uint32 min_stat; + gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; + gss_client_response *response = NULL; + int ret = AUTH_GSS_CONTINUE; + + // Always clear out the old response + if(state->response != NULL) { + free(state->response); + state->response = NULL; + } + + // If there is a challenge (data from the server) we need to give it to GSS + if(challenge && *challenge) { + int len; + input_token.value = base64_decode(challenge, &len); + input_token.length = len; + } + + // Do GSSAPI step + maj_stat = gss_unwrap(&min_stat, + state->context, + &input_token, + &output_token, + NULL, + NULL); + + if(maj_stat != GSS_S_COMPLETE) { + response = gss_error(maj_stat, min_stat); + response->return_code = AUTH_GSS_ERROR; + goto end; + } else { + ret = AUTH_GSS_COMPLETE; + } + + // Grab the client response + if(output_token.length) { + state->response = base64_encode((const unsigned char *)output_token.value, output_token.length); + gss_release_buffer(&min_stat, &output_token); + } +end: + if(output_token.value) + gss_release_buffer(&min_stat, &output_token); + if(input_token.value) + free(input_token.value); + + if(response == NULL) { + response = calloc(1, sizeof(gss_client_response)); + if(response == NULL) die1("Memory allocation failed"); + response->return_code = ret; + } + + // Return the response + return response; +} + +gss_client_response *authenticate_gss_client_wrap(gss_client_state* state, const char* challenge, const char* user) { + OM_uint32 maj_stat; + OM_uint32 min_stat; + gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; + int ret = AUTH_GSS_CONTINUE; + gss_client_response *response = NULL; + char buf[4096], server_conf_flags; + unsigned long buf_size; + + // Always clear out the old response + if(state->response != NULL) { + free(state->response); + state->response = NULL; + } + + if(challenge && *challenge) { + int len; + input_token.value = base64_decode(challenge, &len); + input_token.length = len; + } + + if(user) { + // get bufsize + server_conf_flags = ((char*) input_token.value)[0]; + ((char*) input_token.value)[0] = 0; + buf_size = ntohl(*((long *) input_token.value)); + free(input_token.value); +#ifdef PRINTFS + printf("User: %s, %c%c%c\n", user, + server_conf_flags & GSS_AUTH_P_NONE ? 'N' : '-', + server_conf_flags & GSS_AUTH_P_INTEGRITY ? 'I' : '-', + server_conf_flags & GSS_AUTH_P_PRIVACY ? 'P' : '-'); + printf("Maximum GSS token size is %ld\n", buf_size); +#endif + + // agree to terms (hack!) + buf_size = htonl(buf_size); // not relevant without integrity/privacy + memcpy(buf, &buf_size, 4); + buf[0] = GSS_AUTH_P_NONE; + // server decides if principal can log in as user + strncpy(buf + 4, user, sizeof(buf) - 4); + input_token.value = buf; + input_token.length = 4 + strlen(user); + } + + // Do GSSAPI wrap + maj_stat = gss_wrap(&min_stat, + state->context, + 0, + GSS_C_QOP_DEFAULT, + &input_token, + NULL, + &output_token); + + if (maj_stat != GSS_S_COMPLETE) { + response = gss_error(maj_stat, min_stat); + response->return_code = AUTH_GSS_ERROR; + goto end; + } else + ret = AUTH_GSS_COMPLETE; + // Grab the client response to send back to the server + if (output_token.length) { + state->response = base64_encode((const unsigned char *)output_token.value, output_token.length);; + gss_release_buffer(&min_stat, &output_token); + } +end: + if (output_token.value) + gss_release_buffer(&min_stat, &output_token); + + if(response == NULL) { + response = calloc(1, sizeof(gss_client_response)); + if(response == NULL) die1("Memory allocation failed"); + response->return_code = ret; + } + + // Return the response + return response; +} + +int authenticate_gss_server_init(const char *service, gss_server_state *state) +{ + OM_uint32 maj_stat; + OM_uint32 min_stat; + gss_buffer_desc name_token = GSS_C_EMPTY_BUFFER; + int ret = AUTH_GSS_COMPLETE; + + state->context = GSS_C_NO_CONTEXT; + state->server_name = GSS_C_NO_NAME; + state->client_name = GSS_C_NO_NAME; + state->server_creds = GSS_C_NO_CREDENTIAL; + state->client_creds = GSS_C_NO_CREDENTIAL; + state->username = NULL; + state->targetname = NULL; + state->response = NULL; + + // Server name may be empty which means we aren't going to create our own creds + size_t service_len = strlen(service); + if (service_len != 0) + { + // Import server name first + name_token.length = strlen(service); + name_token.value = (char *)service; + + maj_stat = gss_import_name(&min_stat, &name_token, GSS_C_NT_HOSTBASED_SERVICE, &state->server_name); + + if (GSS_ERROR(maj_stat)) + { + set_gss_error(maj_stat, min_stat); + ret = AUTH_GSS_ERROR; + goto end; + } + + // Get credentials + maj_stat = gss_acquire_cred(&min_stat, state->server_name, GSS_C_INDEFINITE, + GSS_C_NO_OID_SET, GSS_C_ACCEPT, &state->server_creds, NULL, NULL); + + if (GSS_ERROR(maj_stat)) + { + set_gss_error(maj_stat, min_stat); + ret = AUTH_GSS_ERROR; + goto end; + } + } + +end: + return ret; +} + +int authenticate_gss_server_clean(gss_server_state *state) +{ + OM_uint32 min_stat; + int ret = AUTH_GSS_COMPLETE; + + if (state->context != GSS_C_NO_CONTEXT) + gss_delete_sec_context(&min_stat, &state->context, GSS_C_NO_BUFFER); + if (state->server_name != GSS_C_NO_NAME) + gss_release_name(&min_stat, &state->server_name); + if (state->client_name != GSS_C_NO_NAME) + gss_release_name(&min_stat, &state->client_name); + if (state->server_creds != GSS_C_NO_CREDENTIAL) + gss_release_cred(&min_stat, &state->server_creds); + if (state->client_creds != GSS_C_NO_CREDENTIAL) + gss_release_cred(&min_stat, &state->client_creds); + if (state->username != NULL) + { + free(state->username); + state->username = NULL; + } + if (state->targetname != NULL) + { + free(state->targetname); + state->targetname = NULL; + } + if (state->response != NULL) + { + free(state->response); + state->response = NULL; + } + + return ret; +} + +/*int authenticate_gss_server_step(gss_server_state *state, const char *challenge) +{ + OM_uint32 maj_stat; + OM_uint32 min_stat; + gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; + int ret = AUTH_GSS_CONTINUE; + + // Always clear out the old response + if (state->response != NULL) + { + free(state->response); + state->response = NULL; + } + + // If there is a challenge (data from the server) we need to give it to GSS + if (challenge && *challenge) + { + int len; + input_token.value = base64_decode(challenge, &len); + input_token.length = len; + } + else + { + PyErr_SetString(KrbException_class, "No challenge parameter in request from client"); + ret = AUTH_GSS_ERROR; + goto end; + } + + maj_stat = gss_accept_sec_context(&min_stat, + &state->context, + state->server_creds, + &input_token, + GSS_C_NO_CHANNEL_BINDINGS, + &state->client_name, + NULL, + &output_token, + NULL, + NULL, + &state->client_creds); + + if (GSS_ERROR(maj_stat)) + { + set_gss_error(maj_stat, min_stat); + ret = AUTH_GSS_ERROR; + goto end; + } + + // Grab the server response to send back to the client + if (output_token.length) + { + state->response = base64_encode((const unsigned char *)output_token.value, output_token.length);; + maj_stat = gss_release_buffer(&min_stat, &output_token); + } + + // Get the user name + maj_stat = gss_display_name(&min_stat, state->client_name, &output_token, NULL); + if (GSS_ERROR(maj_stat)) + { + set_gss_error(maj_stat, min_stat); + ret = AUTH_GSS_ERROR; + goto end; + } + state->username = (char *)malloc(output_token.length + 1); + strncpy(state->username, (char*) output_token.value, output_token.length); + state->username[output_token.length] = 0; + + // Get the target name if no server creds were supplied + if (state->server_creds == GSS_C_NO_CREDENTIAL) + { + gss_name_t target_name = GSS_C_NO_NAME; + maj_stat = gss_inquire_context(&min_stat, state->context, NULL, &target_name, NULL, NULL, NULL, NULL, NULL); + if (GSS_ERROR(maj_stat)) + { + set_gss_error(maj_stat, min_stat); + ret = AUTH_GSS_ERROR; + goto end; + } + maj_stat = gss_display_name(&min_stat, target_name, &output_token, NULL); + if (GSS_ERROR(maj_stat)) + { + set_gss_error(maj_stat, min_stat); + ret = AUTH_GSS_ERROR; + goto end; + } + state->targetname = (char *)malloc(output_token.length + 1); + strncpy(state->targetname, (char*) output_token.value, output_token.length); + state->targetname[output_token.length] = 0; + } + + ret = AUTH_GSS_COMPLETE; + +end: + if (output_token.length) + gss_release_buffer(&min_stat, &output_token); + if (input_token.value) + free(input_token.value); + return ret; +} +*/ + +static void set_gss_error(OM_uint32 err_maj, OM_uint32 err_min) { + OM_uint32 maj_stat, min_stat; + OM_uint32 msg_ctx = 0; + gss_buffer_desc status_string; + char buf_maj[512]; + char buf_min[512]; + + do { + maj_stat = gss_display_status (&min_stat, + err_maj, + GSS_C_GSS_CODE, + GSS_C_NO_OID, + &msg_ctx, + &status_string); + if(GSS_ERROR(maj_stat)) + break; + + strncpy(buf_maj, (char*) status_string.value, sizeof(buf_maj)); + gss_release_buffer(&min_stat, &status_string); + + maj_stat = gss_display_status (&min_stat, + err_min, + GSS_C_MECH_CODE, + GSS_C_NULL_OID, + &msg_ctx, + &status_string); + if (!GSS_ERROR(maj_stat)) { + + strncpy(buf_min, (char*) status_string.value , sizeof(buf_min)); + gss_release_buffer(&min_stat, &status_string); + } + } while (!GSS_ERROR(maj_stat) && msg_ctx != 0); +} + +gss_client_response *gss_error(OM_uint32 err_maj, OM_uint32 err_min) { + OM_uint32 maj_stat, min_stat; + OM_uint32 msg_ctx = 0; + gss_buffer_desc status_string; + char *buf_maj = calloc(512, sizeof(char)); + if(buf_maj == NULL) die1("Memory allocation failed"); + char *buf_min = calloc(512, sizeof(char)); + if(buf_min == NULL) die1("Memory allocation failed"); + char *message = NULL; + gss_client_response *response = calloc(1, sizeof(gss_client_response)); + if(response == NULL) die1("Memory allocation failed"); + + do { + maj_stat = gss_display_status (&min_stat, + err_maj, + GSS_C_GSS_CODE, + GSS_C_NO_OID, + &msg_ctx, + &status_string); + if(GSS_ERROR(maj_stat)) + break; + + strncpy(buf_maj, (char*) status_string.value, 512); + gss_release_buffer(&min_stat, &status_string); + + maj_stat = gss_display_status (&min_stat, + err_min, + GSS_C_MECH_CODE, + GSS_C_NULL_OID, + &msg_ctx, + &status_string); + if(!GSS_ERROR(maj_stat)) { + strncpy(buf_min, (char*) status_string.value , 512); + gss_release_buffer(&min_stat, &status_string); + } + } while (!GSS_ERROR(maj_stat) && msg_ctx != 0); + + // Join the strings + message = calloc(1026, 1); + if(message == NULL) die1("Memory allocation failed"); + // Join the two messages + sprintf(message, "%s, %s", buf_maj, buf_min); + // Free data + free(buf_min); + free(buf_maj); + // Set the message + response->message = message; + // Return the message + return response; +} + +#pragma clang diagnostic pop + diff --git a/node_modules/mongodb/node_modules/kerberos/lib/kerberosgss.h b/node_modules/mongodb/node_modules/kerberos/lib/kerberosgss.h new file mode 100644 index 0000000..58ac0b7 --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/lib/kerberosgss.h @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2006-2009 Apple Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +#ifndef KERBEROS_GSS_H +#define KERBEROS_GSS_H + +#include +#include +#include + +#define krb5_get_err_text(context,code) error_message(code) + +#define AUTH_GSS_ERROR -1 +#define AUTH_GSS_COMPLETE 1 +#define AUTH_GSS_CONTINUE 0 + +#define GSS_AUTH_P_NONE 1 +#define GSS_AUTH_P_INTEGRITY 2 +#define GSS_AUTH_P_PRIVACY 4 + +typedef struct { + int return_code; + char *message; +} gss_client_response; + +typedef struct { + gss_ctx_id_t context; + gss_name_t server_name; + long int gss_flags; + char* username; + char* response; +} gss_client_state; + +typedef struct { + gss_ctx_id_t context; + gss_name_t server_name; + gss_name_t client_name; + gss_cred_id_t server_creds; + gss_cred_id_t client_creds; + char* username; + char* targetname; + char* response; +} gss_server_state; + +// char* server_principal_details(const char* service, const char* hostname); + +gss_client_response *authenticate_gss_client_init(const char* service, long int gss_flags, gss_client_state* state); +gss_client_response *authenticate_gss_client_clean(gss_client_state *state); +gss_client_response *authenticate_gss_client_step(gss_client_state *state, const char *challenge); +gss_client_response *authenticate_gss_client_unwrap(gss_client_state* state, const char* challenge); +gss_client_response *authenticate_gss_client_wrap(gss_client_state* state, const char* challenge, const char* user); + +int authenticate_gss_server_init(const char* service, gss_server_state* state); +int authenticate_gss_server_clean(gss_server_state *state); +// int authenticate_gss_server_step(gss_server_state *state, const char *challenge); + +gss_client_response *gss_error(OM_uint32 err_maj, OM_uint32 err_min); +#endif diff --git a/node_modules/mongodb/node_modules/kerberos/lib/sspi.js b/node_modules/mongodb/node_modules/kerberos/lib/sspi.js new file mode 100644 index 0000000..d9120fb --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/lib/sspi.js @@ -0,0 +1,15 @@ +// Load the native SSPI classes +var kerberos = require('../build/Release/kerberos') + , Kerberos = kerberos.Kerberos + , SecurityBuffer = require('./win32/wrappers/security_buffer').SecurityBuffer + , SecurityBufferDescriptor = require('./win32/wrappers/security_buffer_descriptor').SecurityBufferDescriptor + , SecurityCredentials = require('./win32/wrappers/security_credentials').SecurityCredentials + , SecurityContext = require('./win32/wrappers/security_context').SecurityContext; +var SSPI = function() { +} + +exports.SSPI = SSPI; +exports.SecurityBuffer = SecurityBuffer; +exports.SecurityBufferDescriptor = SecurityBufferDescriptor; +exports.SecurityCredentials = SecurityCredentials; +exports.SecurityContext = SecurityContext; \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/base64.c b/node_modules/mongodb/node_modules/kerberos/lib/win32/base64.c new file mode 100644 index 0000000..502a021 --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/lib/win32/base64.c @@ -0,0 +1,121 @@ +/** + * Copyright (c) 2006-2008 Apple Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +#include "base64.h" + +#include +#include + +// base64 tables +static char basis_64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static signed char index_64[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,62, -1,-1,-1,63, + 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, + 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, + -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, + 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1 +}; +#define CHAR64(c) (((c) < 0 || (c) > 127) ? -1 : index_64[(c)]) + +// base64_encode : base64 encode +// +// value : data to encode +// vlen : length of data +// (result) : new char[] - c-str of result +char *base64_encode(const unsigned char *value, int vlen) +{ + char *result = (char *)malloc((vlen * 4) / 3 + 5); + char *out = result; + unsigned char oval; + + while (vlen >= 3) + { + *out++ = basis_64[value[0] >> 2]; + *out++ = basis_64[((value[0] << 4) & 0x30) | (value[1] >> 4)]; + *out++ = basis_64[((value[1] << 2) & 0x3C) | (value[2] >> 6)]; + *out++ = basis_64[value[2] & 0x3F]; + value += 3; + vlen -= 3; + } + if (vlen > 0) + { + *out++ = basis_64[value[0] >> 2]; + oval = (value[0] << 4) & 0x30; + if (vlen > 1) oval |= value[1] >> 4; + *out++ = basis_64[oval]; + *out++ = (vlen < 2) ? '=' : basis_64[(value[1] << 2) & 0x3C]; + *out++ = '='; + } + *out = '\0'; + + return result; +} + +// base64_decode : base64 decode +// +// value : c-str to decode +// rlen : length of decoded result +// (result) : new unsigned char[] - decoded result +unsigned char *base64_decode(const char *value, int *rlen) +{ + int c1, c2, c3, c4; + int vlen = (int)strlen(value); + unsigned char *result =(unsigned char *)malloc((vlen * 3) / 4 + 1); + unsigned char *out = result; + *rlen = 0; + + while (1) + { + if (value[0]==0) + return result; + c1 = value[0]; + if (CHAR64(c1) == -1) + goto base64_decode_error;; + c2 = value[1]; + if (CHAR64(c2) == -1) + goto base64_decode_error;; + c3 = value[2]; + if ((c3 != '=') && (CHAR64(c3) == -1)) + goto base64_decode_error;; + c4 = value[3]; + if ((c4 != '=') && (CHAR64(c4) == -1)) + goto base64_decode_error;; + + value += 4; + *out++ = (CHAR64(c1) << 2) | (CHAR64(c2) >> 4); + *rlen += 1; + if (c3 != '=') + { + *out++ = ((CHAR64(c2) << 4) & 0xf0) | (CHAR64(c3) >> 2); + *rlen += 1; + if (c4 != '=') + { + *out++ = ((CHAR64(c3) << 6) & 0xc0) | CHAR64(c4); + *rlen += 1; + } + } + } + +base64_decode_error: + *result = 0; + *rlen = 0; + return result; +} diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/base64.h b/node_modules/mongodb/node_modules/kerberos/lib/win32/base64.h new file mode 100644 index 0000000..f0e1f06 --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/lib/win32/base64.h @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2006-2008 Apple Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +char *base64_encode(const unsigned char *value, int vlen); +unsigned char *base64_decode(const char *value, int *rlen); diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos.cc b/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos.cc new file mode 100644 index 0000000..c40be18 --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos.cc @@ -0,0 +1,53 @@ +#include "kerberos.h" +#include +#include +#include "base64.h" +#include "wrappers/security_buffer.h" +#include "wrappers/security_buffer_descriptor.h" +#include "wrappers/security_context.h" +#include "wrappers/security_credentials.h" + +Persistent Kerberos::constructor_template; + +Kerberos::Kerberos() : ObjectWrap() { +} + +void Kerberos::Initialize(v8::Handle target) { + // Grab the scope of the call from Node + NanScope(); + + // Define a new function template + Local t = NanNew(New); + t->InstanceTemplate()->SetInternalFieldCount(1); + t->SetClassName(NanNew("Kerberos")); + + // Set persistent + NanAssignPersistent(constructor_template, t); + + // Set the symbol + target->ForceSet(NanNew("Kerberos"), t->GetFunction()); +} + +NAN_METHOD(Kerberos::New) { + NanScope(); + // Load the security.dll library + load_library(); + // Create a Kerberos instance + Kerberos *kerberos = new Kerberos(); + // Return the kerberos object + kerberos->Wrap(args.This()); + // Return the object + NanReturnValue(args.This()); +} + +// Exporting function +extern "C" void init(Handle target) { + NanScope(); + Kerberos::Initialize(target); + SecurityContext::Initialize(target); + SecurityBuffer::Initialize(target); + SecurityBufferDescriptor::Initialize(target); + SecurityCredentials::Initialize(target); +} + +NODE_MODULE(kerberos, init); diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos.h b/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos.h new file mode 100644 index 0000000..579d04e --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos.h @@ -0,0 +1,60 @@ +#ifndef KERBEROS_H +#define KERBEROS_H + +#include +#include +#include +#include "nan.h" + +extern "C" { + #include "kerberos_sspi.h" + #include "base64.h" +} + +using namespace v8; +using namespace node; + +class Kerberos : public ObjectWrap { + +public: + Kerberos(); + ~Kerberos() {}; + + // Constructor used for creating new Kerberos objects from C++ + static Persistent constructor_template; + + // Initialize function for the object + static void Initialize(Handle target); + + // Method available + static NAN_METHOD(AcquireAlternateCredentials); + static NAN_METHOD(PrepareOutboundPackage); + static NAN_METHOD(DecryptMessage); + static NAN_METHOD(EncryptMessage); + static NAN_METHOD(QueryContextAttributes); + +private: + static NAN_METHOD(New); + + // Pointer to context object + SEC_WINNT_AUTH_IDENTITY m_Identity; + // credentials + CredHandle m_Credentials; + // Expiry time for ticket + TimeStamp Expiration; + // package info + SecPkgInfo m_PkgInfo; + // context + CtxtHandle m_Context; + // Do we have a context + bool m_HaveContext; + // Attributes + DWORD CtxtAttr; + + // Handles the uv calls + static void Process(uv_work_t* work_req); + // Called after work is done + static void After(uv_work_t* work_req); +}; + +#endif \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos_sspi.c b/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos_sspi.c new file mode 100644 index 0000000..d75c9ab --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos_sspi.c @@ -0,0 +1,244 @@ +#include "kerberos_sspi.h" +#include +#include + +static HINSTANCE _sspi_security_dll = NULL; +static HINSTANCE _sspi_secur32_dll = NULL; + +/** + * Encrypt A Message + */ +SECURITY_STATUS SEC_ENTRY _sspi_EncryptMessage(PCtxtHandle phContext, unsigned long fQOP, PSecBufferDesc pMessage, unsigned long MessageSeqNo) { + // Create function pointer instance + encryptMessage_fn pfn_encryptMessage = NULL; + + // Return error if library not loaded + if(_sspi_security_dll == NULL) return -1; + + // Map function to library method + pfn_encryptMessage = (encryptMessage_fn)GetProcAddress(_sspi_security_dll, "EncryptMessage"); + // Check if the we managed to map function pointer + if(!pfn_encryptMessage) { + printf("GetProcAddress failed.\n"); + return -2; + } + + // Call the function + return (*pfn_encryptMessage)(phContext, fQOP, pMessage, MessageSeqNo); +} + +/** + * Acquire Credentials + */ +SECURITY_STATUS SEC_ENTRY _sspi_AcquireCredentialsHandle( + LPSTR pszPrincipal, LPSTR pszPackage, unsigned long fCredentialUse, + void * pvLogonId, void * pAuthData, SEC_GET_KEY_FN pGetKeyFn, void * pvGetKeyArgument, + PCredHandle phCredential, PTimeStamp ptsExpiry +) { + SECURITY_STATUS status; + // Create function pointer instance + acquireCredentialsHandle_fn pfn_acquireCredentialsHandle = NULL; + + // Return error if library not loaded + if(_sspi_security_dll == NULL) return -1; + + // Map function + #ifdef _UNICODE + pfn_acquireCredentialsHandle = (acquireCredentialsHandle_fn)GetProcAddress(_sspi_security_dll, "AcquireCredentialsHandleW"); + #else + pfn_acquireCredentialsHandle = (acquireCredentialsHandle_fn)GetProcAddress(_sspi_security_dll, "AcquireCredentialsHandleA"); + #endif + + // Check if the we managed to map function pointer + if(!pfn_acquireCredentialsHandle) { + printf("GetProcAddress failed.\n"); + return -2; + } + + // Status + status = (*pfn_acquireCredentialsHandle)(pszPrincipal, pszPackage, fCredentialUse, + pvLogonId, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry + ); + + // Call the function + return status; +} + +/** + * Delete Security Context + */ +SECURITY_STATUS SEC_ENTRY _sspi_DeleteSecurityContext(PCtxtHandle phContext) { + // Create function pointer instance + deleteSecurityContext_fn pfn_deleteSecurityContext = NULL; + + // Return error if library not loaded + if(_sspi_security_dll == NULL) return -1; + // Map function + pfn_deleteSecurityContext = (deleteSecurityContext_fn)GetProcAddress(_sspi_security_dll, "DeleteSecurityContext"); + + // Check if the we managed to map function pointer + if(!pfn_deleteSecurityContext) { + printf("GetProcAddress failed.\n"); + return -2; + } + + // Call the function + return (*pfn_deleteSecurityContext)(phContext); +} + +/** + * Decrypt Message + */ +SECURITY_STATUS SEC_ENTRY _sspi_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, unsigned long MessageSeqNo, unsigned long pfQOP) { + // Create function pointer instance + decryptMessage_fn pfn_decryptMessage = NULL; + + // Return error if library not loaded + if(_sspi_security_dll == NULL) return -1; + // Map function + pfn_decryptMessage = (decryptMessage_fn)GetProcAddress(_sspi_security_dll, "DecryptMessage"); + + // Check if the we managed to map function pointer + if(!pfn_decryptMessage) { + printf("GetProcAddress failed.\n"); + return -2; + } + + // Call the function + return (*pfn_decryptMessage)(phContext, pMessage, MessageSeqNo, pfQOP); +} + +/** + * Initialize Security Context + */ +SECURITY_STATUS SEC_ENTRY _sspi_initializeSecurityContext( + PCredHandle phCredential, PCtxtHandle phContext, + LPSTR pszTargetName, unsigned long fContextReq, + unsigned long Reserved1, unsigned long TargetDataRep, + PSecBufferDesc pInput, unsigned long Reserved2, + PCtxtHandle phNewContext, PSecBufferDesc pOutput, + unsigned long * pfContextAttr, PTimeStamp ptsExpiry +) { + SECURITY_STATUS status; + // Create function pointer instance + initializeSecurityContext_fn pfn_initializeSecurityContext = NULL; + + // Return error if library not loaded + if(_sspi_security_dll == NULL) return -1; + + // Map function + #ifdef _UNICODE + pfn_initializeSecurityContext = (initializeSecurityContext_fn)GetProcAddress(_sspi_security_dll, "InitializeSecurityContextW"); + #else + pfn_initializeSecurityContext = (initializeSecurityContext_fn)GetProcAddress(_sspi_security_dll, "InitializeSecurityContextA"); + #endif + + // Check if the we managed to map function pointer + if(!pfn_initializeSecurityContext) { + printf("GetProcAddress failed.\n"); + return -2; + } + + // Execute intialize context + status = (*pfn_initializeSecurityContext)( + phCredential, phContext, pszTargetName, fContextReq, + Reserved1, TargetDataRep, pInput, Reserved2, + phNewContext, pOutput, pfContextAttr, ptsExpiry + ); + + // Call the function + return status; +} +/** + * Query Context Attributes + */ +SECURITY_STATUS SEC_ENTRY _sspi_QueryContextAttributes( + PCtxtHandle phContext, unsigned long ulAttribute, void * pBuffer +) { + // Create function pointer instance + queryContextAttributes_fn pfn_queryContextAttributes = NULL; + + // Return error if library not loaded + if(_sspi_security_dll == NULL) return -1; + + #ifdef _UNICODE + pfn_queryContextAttributes = (queryContextAttributes_fn)GetProcAddress(_sspi_security_dll, "QueryContextAttributesW"); + #else + pfn_queryContextAttributes = (queryContextAttributes_fn)GetProcAddress(_sspi_security_dll, "QueryContextAttributesA"); + #endif + + // Check if the we managed to map function pointer + if(!pfn_queryContextAttributes) { + printf("GetProcAddress failed.\n"); + return -2; + } + + // Call the function + return (*pfn_queryContextAttributes)( + phContext, ulAttribute, pBuffer + ); +} + +/** + * InitSecurityInterface + */ +PSecurityFunctionTable _ssip_InitSecurityInterface() { + INIT_SECURITY_INTERFACE InitSecurityInterface; + PSecurityFunctionTable pSecurityInterface = NULL; + + // Return error if library not loaded + if(_sspi_security_dll == NULL) return NULL; + + #ifdef _UNICODE + // Get the address of the InitSecurityInterface function. + InitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress ( + _sspi_secur32_dll, + TEXT("InitSecurityInterfaceW")); + #else + // Get the address of the InitSecurityInterface function. + InitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress ( + _sspi_secur32_dll, + TEXT("InitSecurityInterfaceA")); + #endif + + if(!InitSecurityInterface) { + printf (TEXT("Failed in getting the function address, Error: %x"), GetLastError ()); + return NULL; + } + + // Use InitSecurityInterface to get the function table. + pSecurityInterface = (*InitSecurityInterface)(); + + if(!pSecurityInterface) { + printf (TEXT("Failed in getting the function table, Error: %x"), GetLastError ()); + return NULL; + } + + return pSecurityInterface; +} + +/** + * Load security.dll dynamically + */ +int load_library() { + DWORD err; + // Load the library + _sspi_security_dll = LoadLibrary("security.dll"); + + // Check if the library loaded + if(_sspi_security_dll == NULL) { + err = GetLastError(); + return err; + } + + // Load the library + _sspi_secur32_dll = LoadLibrary("secur32.dll"); + + // Check if the library loaded + if(_sspi_secur32_dll == NULL) { + err = GetLastError(); + return err; + } + + return 0; +} \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos_sspi.h b/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos_sspi.h new file mode 100644 index 0000000..a3008dc --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos_sspi.h @@ -0,0 +1,106 @@ +#ifndef SSPI_C_H +#define SSPI_C_H + +#define SECURITY_WIN32 1 + +#include +#include + +/** + * Encrypt A Message + */ +SECURITY_STATUS SEC_ENTRY _sspi_EncryptMessage(PCtxtHandle phContext, unsigned long fQOP, PSecBufferDesc pMessage, unsigned long MessageSeqNo); + +typedef DWORD (WINAPI *encryptMessage_fn)(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo); + +/** + * Acquire Credentials + */ +SECURITY_STATUS SEC_ENTRY _sspi_AcquireCredentialsHandle( + LPSTR pszPrincipal, // Name of principal + LPSTR pszPackage, // Name of package + unsigned long fCredentialUse, // Flags indicating use + void * pvLogonId, // Pointer to logon ID + void * pAuthData, // Package specific data + SEC_GET_KEY_FN pGetKeyFn, // Pointer to GetKey() func + void * pvGetKeyArgument, // Value to pass to GetKey() + PCredHandle phCredential, // (out) Cred Handle + PTimeStamp ptsExpiry // (out) Lifetime (optional) +); + +typedef DWORD (WINAPI *acquireCredentialsHandle_fn)( + LPSTR pszPrincipal, LPSTR pszPackage, unsigned long fCredentialUse, + void * pvLogonId, void * pAuthData, SEC_GET_KEY_FN pGetKeyFn, void * pvGetKeyArgument, + PCredHandle phCredential, PTimeStamp ptsExpiry + ); + +/** + * Delete Security Context + */ +SECURITY_STATUS SEC_ENTRY _sspi_DeleteSecurityContext( + PCtxtHandle phContext // Context to delete +); + +typedef DWORD (WINAPI *deleteSecurityContext_fn)(PCtxtHandle phContext); + +/** + * Decrypt Message + */ +SECURITY_STATUS SEC_ENTRY _sspi_DecryptMessage( + PCtxtHandle phContext, + PSecBufferDesc pMessage, + unsigned long MessageSeqNo, + unsigned long pfQOP +); + +typedef DWORD (WINAPI *decryptMessage_fn)( + PCtxtHandle phContext, PSecBufferDesc pMessage, unsigned long MessageSeqNo, unsigned long pfQOP); + +/** + * Initialize Security Context + */ +SECURITY_STATUS SEC_ENTRY _sspi_initializeSecurityContext( + PCredHandle phCredential, // Cred to base context + PCtxtHandle phContext, // Existing context (OPT) + LPSTR pszTargetName, // Name of target + unsigned long fContextReq, // Context Requirements + unsigned long Reserved1, // Reserved, MBZ + unsigned long TargetDataRep, // Data rep of target + PSecBufferDesc pInput, // Input Buffers + unsigned long Reserved2, // Reserved, MBZ + PCtxtHandle phNewContext, // (out) New Context handle + PSecBufferDesc pOutput, // (inout) Output Buffers + unsigned long * pfContextAttr, // (out) Context attrs + PTimeStamp ptsExpiry // (out) Life span (OPT) +); + +typedef DWORD (WINAPI *initializeSecurityContext_fn)( + PCredHandle phCredential, PCtxtHandle phContext, LPSTR pszTargetName, unsigned long fContextReq, + unsigned long Reserved1, unsigned long TargetDataRep, PSecBufferDesc pInput, unsigned long Reserved2, + PCtxtHandle phNewContext, PSecBufferDesc pOutput, unsigned long * pfContextAttr, PTimeStamp ptsExpiry); + +/** + * Query Context Attributes + */ +SECURITY_STATUS SEC_ENTRY _sspi_QueryContextAttributes( + PCtxtHandle phContext, // Context to query + unsigned long ulAttribute, // Attribute to query + void * pBuffer // Buffer for attributes +); + +typedef DWORD (WINAPI *queryContextAttributes_fn)( + PCtxtHandle phContext, unsigned long ulAttribute, void * pBuffer); + +/** + * InitSecurityInterface + */ +PSecurityFunctionTable _ssip_InitSecurityInterface(); + +typedef DWORD (WINAPI *initSecurityInterface_fn) (); + +/** + * Load security.dll dynamically + */ +int load_library(); + +#endif \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/worker.cc b/node_modules/mongodb/node_modules/kerberos/lib/win32/worker.cc new file mode 100644 index 0000000..e7a472f --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/lib/win32/worker.cc @@ -0,0 +1,7 @@ +#include "worker.h" + +Worker::Worker() { +} + +Worker::~Worker() { +} \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/worker.h b/node_modules/mongodb/node_modules/kerberos/lib/win32/worker.h new file mode 100644 index 0000000..fb62b55 --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/lib/win32/worker.h @@ -0,0 +1,38 @@ +#ifndef WORKER_H_ +#define WORKER_H_ + +#include +#include +#include +#include "nan.h" + +using namespace node; +using namespace v8; + +class Worker { + public: + Worker(); + virtual ~Worker(); + + // libuv's request struct. + uv_work_t request; + // Callback + NanCallback *callback; + // Parameters + void *parameters; + // Results + void *return_value; + // Did we raise an error + bool error; + // The error message + char *error_message; + // Error code if not message + int error_code; + // Any return code + int return_code; + // Method we are going to fire + void (*execute)(Worker *worker); + Handle (*mapper)(Worker *worker); +}; + +#endif // WORKER_H_ diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.cc b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.cc new file mode 100644 index 0000000..6dea93a --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.cc @@ -0,0 +1,106 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "security_buffer.h" + +using namespace node; + +Persistent SecurityBuffer::constructor_template; + +SecurityBuffer::SecurityBuffer(uint32_t security_type, size_t size) : ObjectWrap() { + this->size = size; + this->data = calloc(size, sizeof(char)); + this->security_type = security_type; + // Set up the data in the sec_buffer + this->sec_buffer.BufferType = security_type; + this->sec_buffer.cbBuffer = (unsigned long)size; + this->sec_buffer.pvBuffer = this->data; +} + +SecurityBuffer::SecurityBuffer(uint32_t security_type, size_t size, void *data) : ObjectWrap() { + this->size = size; + this->data = data; + this->security_type = security_type; + // Set up the data in the sec_buffer + this->sec_buffer.BufferType = security_type; + this->sec_buffer.cbBuffer = (unsigned long)size; + this->sec_buffer.pvBuffer = this->data; +} + +SecurityBuffer::~SecurityBuffer() { + free(this->data); +} + +NAN_METHOD(SecurityBuffer::New) { + NanScope(); + SecurityBuffer *security_obj; + + if(args.Length() != 2) + return NanThrowError("Two parameters needed integer buffer type and [32 bit integer/Buffer] required"); + + if(!args[0]->IsInt32()) + return NanThrowError("Two parameters needed integer buffer type and [32 bit integer/Buffer] required"); + + if(!args[1]->IsInt32() && !Buffer::HasInstance(args[1])) + return NanThrowError("Two parameters needed integer buffer type and [32 bit integer/Buffer] required"); + + // Unpack buffer type + uint32_t buffer_type = args[0]->ToUint32()->Value(); + + // If we have an integer + if(args[1]->IsInt32()) { + security_obj = new SecurityBuffer(buffer_type, args[1]->ToUint32()->Value()); + } else { + // Get the length of the Buffer + size_t length = Buffer::Length(args[1]->ToObject()); + // Allocate space for the internal void data pointer + void *data = calloc(length, sizeof(char)); + // Write the data to out of V8 heap space + memcpy(data, Buffer::Data(args[1]->ToObject()), length); + // Create new SecurityBuffer + security_obj = new SecurityBuffer(buffer_type, length, data); + } + + // Wrap it + security_obj->Wrap(args.This()); + // Return the object + NanReturnValue(args.This()); +} + +NAN_METHOD(SecurityBuffer::ToBuffer) { + NanScope(); + // Unpack the Security Buffer object + SecurityBuffer *security_obj = ObjectWrap::Unwrap(args.This()); + // Create a Buffer + Local buffer = NanNewBufferHandle((char *)security_obj->data, (size_t)security_obj->size); + // Return the buffer + NanReturnValue(buffer); +} + +void SecurityBuffer::Initialize(Handle target) { + // Grab the scope of the call from Node + NanScope(); + + // Define a new function template + Local t = NanNew(New); + t->InstanceTemplate()->SetInternalFieldCount(1); + t->SetClassName(NanNew("SecurityBuffer")); + + // Class methods + NODE_SET_PROTOTYPE_METHOD(t, "toBuffer", ToBuffer); + + // Set persistent + NanAssignPersistent(constructor_template, t); + + // Set the symbol + target->ForceSet(NanNew("SecurityBuffer"), t->GetFunction()); +} diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.h b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.h new file mode 100644 index 0000000..8958820 --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.h @@ -0,0 +1,47 @@ +#ifndef SECURITY_BUFFER_H +#define SECURITY_BUFFER_H + +#include +#include +#include + +#define SECURITY_WIN32 1 + +#include +#include +#include "nan.h" + +using namespace v8; +using namespace node; + +class SecurityBuffer : public ObjectWrap { + public: + SecurityBuffer(uint32_t security_type, size_t size); + SecurityBuffer(uint32_t security_type, size_t size, void *data); + ~SecurityBuffer(); + + // Internal values + void *data; + size_t size; + uint32_t security_type; + SecBuffer sec_buffer; + + // Has instance check + static inline bool HasInstance(Handle val) { + if (!val->IsObject()) return false; + Local obj = val->ToObject(); + return NanNew(constructor_template)->HasInstance(obj); + }; + + // Functions available from V8 + static void Initialize(Handle target); + static NAN_METHOD(ToBuffer); + + // Constructor used for creating new Long objects from C++ + static Persistent constructor_template; + + private: + static NAN_METHOD(New); +}; + +#endif \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.js b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.js new file mode 100644 index 0000000..4996163 --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.js @@ -0,0 +1,12 @@ +var SecurityBufferNative = require('../../../build/Release/kerberos').SecurityBuffer; + +// Add some attributes +SecurityBufferNative.VERSION = 0; +SecurityBufferNative.EMPTY = 0; +SecurityBufferNative.DATA = 1; +SecurityBufferNative.TOKEN = 2; +SecurityBufferNative.PADDING = 9; +SecurityBufferNative.STREAM = 10; + +// Export the modified class +exports.SecurityBuffer = SecurityBufferNative; \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.cc b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.cc new file mode 100644 index 0000000..1c335df --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.cc @@ -0,0 +1,185 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SECURITY_WIN32 1 + +#include "security_buffer_descriptor.h" +#include "security_buffer.h" + +Persistent SecurityBufferDescriptor::constructor_template; + +SecurityBufferDescriptor::SecurityBufferDescriptor() : ObjectWrap() { +} + +SecurityBufferDescriptor::SecurityBufferDescriptor(Persistent arrayObjectPersistent) : ObjectWrap() { + SecurityBuffer *security_obj = NULL; + // Get the Local value + Local arrayObject = NanNew(arrayObjectPersistent); + + // Safe reference to array + this->arrayObject = arrayObject; + + // Unpack the array and ensure we have a valid descriptor + this->secBufferDesc.cBuffers = arrayObject->Length(); + this->secBufferDesc.ulVersion = SECBUFFER_VERSION; + + if(arrayObject->Length() == 1) { + // Unwrap the buffer + security_obj = ObjectWrap::Unwrap(arrayObject->Get(0)->ToObject()); + // Assign the buffer + this->secBufferDesc.pBuffers = &security_obj->sec_buffer; + } else { + this->secBufferDesc.pBuffers = new SecBuffer[arrayObject->Length()]; + this->secBufferDesc.cBuffers = arrayObject->Length(); + + // Assign the buffers + for(uint32_t i = 0; i < arrayObject->Length(); i++) { + security_obj = ObjectWrap::Unwrap(arrayObject->Get(i)->ToObject()); + this->secBufferDesc.pBuffers[i].BufferType = security_obj->sec_buffer.BufferType; + this->secBufferDesc.pBuffers[i].pvBuffer = security_obj->sec_buffer.pvBuffer; + this->secBufferDesc.pBuffers[i].cbBuffer = security_obj->sec_buffer.cbBuffer; + } + } +} + +SecurityBufferDescriptor::~SecurityBufferDescriptor() { +} + +size_t SecurityBufferDescriptor::bufferSize() { + SecurityBuffer *security_obj = NULL; + + if(this->secBufferDesc.cBuffers == 1) { + security_obj = ObjectWrap::Unwrap(arrayObject->Get(0)->ToObject()); + return security_obj->size; + } else { + int bytesToAllocate = 0; + + for(unsigned int i = 0; i < this->secBufferDesc.cBuffers; i++) { + bytesToAllocate += this->secBufferDesc.pBuffers[i].cbBuffer; + } + + // Return total size + return bytesToAllocate; + } +} + +char *SecurityBufferDescriptor::toBuffer() { + SecurityBuffer *security_obj = NULL; + char *data = NULL; + + if(this->secBufferDesc.cBuffers == 1) { + security_obj = ObjectWrap::Unwrap(arrayObject->Get(0)->ToObject()); + data = (char *)malloc(security_obj->size * sizeof(char)); + memcpy(data, security_obj->data, security_obj->size); + } else { + size_t bytesToAllocate = this->bufferSize(); + char *data = (char *)calloc(bytesToAllocate, sizeof(char)); + int offset = 0; + + for(unsigned int i = 0; i < this->secBufferDesc.cBuffers; i++) { + memcpy((data + offset), this->secBufferDesc.pBuffers[i].pvBuffer, this->secBufferDesc.pBuffers[i].cbBuffer); + offset +=this->secBufferDesc.pBuffers[i].cbBuffer; + } + + // Return the data + return data; + } + + return data; +} + +NAN_METHOD(SecurityBufferDescriptor::New) { + NanScope(); + SecurityBufferDescriptor *security_obj; + Persistent arrayObject; + + if(args.Length() != 1) + return NanThrowError("There must be 1 argument passed in where the first argument is a [int32 or an Array of SecurityBuffers]"); + + if(!args[0]->IsInt32() && !args[0]->IsArray()) + return NanThrowError("There must be 1 argument passed in where the first argument is a [int32 or an Array of SecurityBuffers]"); + + if(args[0]->IsArray()) { + Handle array = Handle::Cast(args[0]); + // Iterate over all items and ensure we the right type + for(uint32_t i = 0; i < array->Length(); i++) { + if(!SecurityBuffer::HasInstance(array->Get(i))) { + return NanThrowError("There must be 1 argument passed in where the first argument is a [int32 or an Array of SecurityBuffers]"); + } + } + } + + // We have a single integer + if(args[0]->IsInt32()) { + // Create new SecurityBuffer instance + Local argv[] = {NanNew(0x02), args[0]}; + Handle security_buffer = NanNew(SecurityBuffer::constructor_template)->GetFunction()->NewInstance(2, argv); + // Create a new array + Local array = NanNew(1); + // Set the first value + array->Set(0, security_buffer); + + // Create persistent handle + Persistent persistenHandler; + NanAssignPersistent(persistenHandler, array); + + // Create descriptor + security_obj = new SecurityBufferDescriptor(persistenHandler); + } else { + // Create a persistent handler + Persistent persistenHandler; + NanAssignPersistent(persistenHandler, Handle::Cast(args[0])); + // Create a descriptor + security_obj = new SecurityBufferDescriptor(persistenHandler); + } + + // Wrap it + security_obj->Wrap(args.This()); + // Return the object + NanReturnValue(args.This()); +} + +NAN_METHOD(SecurityBufferDescriptor::ToBuffer) { + NanScope(); + + // Unpack the Security Buffer object + SecurityBufferDescriptor *security_obj = ObjectWrap::Unwrap(args.This()); + + // Get the buffer + char *buffer_data = security_obj->toBuffer(); + size_t buffer_size = security_obj->bufferSize(); + + // Create a Buffer + Local buffer = NanNewBufferHandle(buffer_data, buffer_size); + + // Return the buffer + NanReturnValue(buffer); +} + +void SecurityBufferDescriptor::Initialize(Handle target) { + // Grab the scope of the call from Node + NanScope(); + + // Define a new function template + Local t = NanNew(New); + t->InstanceTemplate()->SetInternalFieldCount(1); + t->SetClassName(NanNew("SecurityBufferDescriptor")); + + // Class methods + NODE_SET_PROTOTYPE_METHOD(t, "toBuffer", ToBuffer); + + // Set persistent + NanAssignPersistent(constructor_template, t); + + // Set the symbol + target->ForceSet(NanNew("SecurityBufferDescriptor"), t->GetFunction()); +} diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.h b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.h new file mode 100644 index 0000000..cfe18cf --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.h @@ -0,0 +1,45 @@ +#ifndef SECURITY_BUFFER_DESCRIPTOR_H +#define SECURITY_BUFFER_DESCRIPTOR_H + +#include +#include +#include + +#include +#include +#include "nan.h" + +using namespace v8; +using namespace node; + +class SecurityBufferDescriptor : public ObjectWrap { + public: + Local arrayObject; + SecBufferDesc secBufferDesc; + + SecurityBufferDescriptor(); + SecurityBufferDescriptor(Persistent arrayObjectPersistent); + ~SecurityBufferDescriptor(); + + // Has instance check + static inline bool HasInstance(Handle val) { + if (!val->IsObject()) return false; + Local obj = val->ToObject(); + return NanNew(constructor_template)->HasInstance(obj); + }; + + char *toBuffer(); + size_t bufferSize(); + + // Functions available from V8 + static void Initialize(Handle target); + static NAN_METHOD(ToBuffer); + + // Constructor used for creating new Long objects from C++ + static Persistent constructor_template; + + private: + static NAN_METHOD(New); +}; + +#endif \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.js b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.js new file mode 100644 index 0000000..9421392 --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.js @@ -0,0 +1,3 @@ +var SecurityBufferDescriptorNative = require('../../../build/Release/kerberos').SecurityBufferDescriptor; +// Export the modified class +exports.SecurityBufferDescriptor = SecurityBufferDescriptorNative; \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.cc b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.cc new file mode 100644 index 0000000..7ff9ae5 --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.cc @@ -0,0 +1,871 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "security_context.h" +#include "security_buffer_descriptor.h" + +#ifndef ARRAY_SIZE +# define ARRAY_SIZE(a) (sizeof((a)) / sizeof((a)[0])) +#endif + +static LPSTR DisplaySECError(DWORD ErrCode); + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// UV Lib callbacks +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +static void Process(uv_work_t* work_req) { + // Grab the worker + Worker *worker = static_cast(work_req->data); + // Execute the worker code + worker->execute(worker); +} + +static void After(uv_work_t* work_req) { + // Grab the scope of the call from Node + NanScope(); + + // Get the worker reference + Worker *worker = static_cast(work_req->data); + + // If we have an error + if(worker->error) { + Local err = v8::Exception::Error(NanNew(worker->error_message)); + Local obj = err->ToObject(); + obj->Set(NanNew("code"), NanNew(worker->error_code)); + Local args[2] = { err, NanNull() }; + // Execute the error + v8::TryCatch try_catch; + + // Call the callback + worker->callback->Call(ARRAY_SIZE(args), args); + + // If we have an exception handle it as a fatalexception + if (try_catch.HasCaught()) { + node::FatalException(try_catch); + } + } else { + // // Map the data + Handle result = worker->mapper(worker); + // Set up the callback with a null first + Handle args[2] = { NanNull(), result}; + // Wrap the callback function call in a TryCatch so that we can call + // node's FatalException afterwards. This makes it possible to catch + // the exception from JavaScript land using the + // process.on('uncaughtException') event. + v8::TryCatch try_catch; + + // Call the callback + worker->callback->Call(ARRAY_SIZE(args), args); + + // If we have an exception handle it as a fatalexception + if (try_catch.HasCaught()) { + node::FatalException(try_catch); + } + } + + // Clean up the memory + delete worker->callback; + delete worker; +} + +Persistent SecurityContext::constructor_template; + +SecurityContext::SecurityContext() : ObjectWrap() { +} + +SecurityContext::~SecurityContext() { + if(this->hasContext) { + _sspi_DeleteSecurityContext(&this->m_Context); + } +} + +NAN_METHOD(SecurityContext::New) { + NanScope(); + + PSecurityFunctionTable pSecurityInterface = NULL; + DWORD dwNumOfPkgs; + SECURITY_STATUS status; + + // Create code object + SecurityContext *security_obj = new SecurityContext(); + // Get security table interface + pSecurityInterface = _ssip_InitSecurityInterface(); + // Call the security interface + status = (*pSecurityInterface->EnumerateSecurityPackages)( + &dwNumOfPkgs, + &security_obj->m_PkgInfo); + if(status != SEC_E_OK) { + printf(TEXT("Failed in retrieving security packages, Error: %x"), GetLastError()); + return NanThrowError("Failed in retrieving security packages"); + } + + // Wrap it + security_obj->Wrap(args.This()); + // Return the object + NanReturnValue(args.This()); +} + +// +// Async InitializeContext +// +typedef struct SecurityContextStaticInitializeCall { + char *service_principal_name_str; + char *decoded_input_str; + int decoded_input_str_length; + SecurityContext *context; +} SecurityContextStaticInitializeCall; + +static void _initializeContext(Worker *worker) { + // Status of operation + SECURITY_STATUS status; + BYTE *out_bound_data_str = NULL; + SecurityContextStaticInitializeCall *call = (SecurityContextStaticInitializeCall *)worker->parameters; + + // Structures used for c calls + SecBufferDesc ibd, obd; + SecBuffer ib, ob; + + // + // Prepare data structure for returned data from SSPI + ob.BufferType = SECBUFFER_TOKEN; + ob.cbBuffer = call->context->m_PkgInfo->cbMaxToken; + // Allocate space for return data + out_bound_data_str = new BYTE[ob.cbBuffer + sizeof(DWORD)]; + ob.pvBuffer = out_bound_data_str; + // prepare buffer description + obd.cBuffers = 1; + obd.ulVersion = SECBUFFER_VERSION; + obd.pBuffers = &ob; + + // + // Prepare the data we are passing to the SSPI method + if(call->decoded_input_str_length > 0) { + ib.BufferType = SECBUFFER_TOKEN; + ib.cbBuffer = call->decoded_input_str_length; + ib.pvBuffer = call->decoded_input_str; + // prepare buffer description + ibd.cBuffers = 1; + ibd.ulVersion = SECBUFFER_VERSION; + ibd.pBuffers = &ib; + } + + // Perform initialization step + status = _sspi_initializeSecurityContext( + &call->context->security_credentials->m_Credentials + , NULL + , const_cast(call->service_principal_name_str) + , 0x02 // MUTUAL + , 0 + , 0 // Network + , call->decoded_input_str_length > 0 ? &ibd : NULL + , 0 + , &call->context->m_Context + , &obd + , &call->context->CtxtAttr + , &call->context->Expiration + ); + + // If we have a ok or continue let's prepare the result + if(status == SEC_E_OK + || status == SEC_I_COMPLETE_NEEDED + || status == SEC_I_CONTINUE_NEEDED + || status == SEC_I_COMPLETE_AND_CONTINUE + ) { + call->context->hasContext = true; + call->context->payload = base64_encode((const unsigned char *)ob.pvBuffer, ob.cbBuffer); + + // Set the context + worker->return_code = status; + worker->return_value = call->context; + } else if(status == SEC_E_INSUFFICIENT_MEMORY) { + worker->error = TRUE; + worker->error_code = status; + worker->error_message = "SEC_E_INSUFFICIENT_MEMORY There is not enough memory available to complete the requested action."; + } else if(status == SEC_E_INTERNAL_ERROR) { + worker->error = TRUE; + worker->error_code = status; + worker->error_message = "SEC_E_INTERNAL_ERROR An error occurred that did not map to an SSPI error code."; + } else if(status == SEC_E_INVALID_HANDLE) { + worker->error = TRUE; + worker->error_code = status; + worker->error_message = "SEC_E_INVALID_HANDLE The handle passed to the function is not valid."; + } else if(status == SEC_E_INVALID_TOKEN) { + worker->error = TRUE; + worker->error_code = status; + worker->error_message = "SEC_E_INVALID_TOKEN The error is due to a malformed input token, such as a token corrupted in transit, a token of incorrect size, or a token passed into the wrong security package. Passing a token to the wrong package can happen if the client and server did not negotiate the proper security package."; + } else if(status == SEC_E_LOGON_DENIED) { + worker->error = TRUE; + worker->error_code = status; + worker->error_message = "SEC_E_LOGON_DENIED The logon failed."; + } else if(status == SEC_E_NO_AUTHENTICATING_AUTHORITY) { + worker->error = TRUE; + worker->error_code = status; + worker->error_message = "SEC_E_NO_AUTHENTICATING_AUTHORITY No authority could be contacted for authentication. The domain name of the authenticating party could be wrong, the domain could be unreachable, or there might have been a trust relationship failure."; + } else if(status == SEC_E_NO_CREDENTIALS) { + worker->error = TRUE; + worker->error_code = status; + worker->error_message = "SEC_E_NO_CREDENTIALS No credentials are available in the security package."; + } else if(status == SEC_E_TARGET_UNKNOWN) { + worker->error = TRUE; + worker->error_code = status; + worker->error_message = "SEC_E_TARGET_UNKNOWN The target was not recognized."; + } else if(status == SEC_E_UNSUPPORTED_FUNCTION) { + worker->error = TRUE; + worker->error_code = status; + worker->error_message = "SEC_E_UNSUPPORTED_FUNCTION A context attribute flag that is not valid (ISC_REQ_DELEGATE or ISC_REQ_PROMPT_FOR_CREDS) was specified in the fContextReq parameter."; + } else if(status == SEC_E_WRONG_PRINCIPAL) { + worker->error = TRUE; + worker->error_code = status; + worker->error_message = "SEC_E_WRONG_PRINCIPAL The principal that received the authentication request is not the same as the one passed into the pszTargetName parameter. This indicates a failure in mutual authentication."; + } else { + worker->error = TRUE; + worker->error_code = status; + worker->error_message = DisplaySECError(status); + } + + // Clean up data + if(call->decoded_input_str != NULL) free(call->decoded_input_str); + if(call->service_principal_name_str != NULL) free(call->service_principal_name_str); +} + +static Handle _map_initializeContext(Worker *worker) { + // Unwrap the security context + SecurityContext *context = (SecurityContext *)worker->return_value; + // Return the value + return NanObjectWrapHandle(context); +} + +NAN_METHOD(SecurityContext::InitializeContext) { + NanScope(); + char *service_principal_name_str = NULL, *input_str = NULL, *decoded_input_str = NULL; + int decoded_input_str_length = NULL; + // Store reference to security credentials + SecurityCredentials *security_credentials = NULL; + + // We need 3 parameters + if(args.Length() != 4) + return NanThrowError("Initialize must be called with [credential:SecurityCredential, servicePrincipalName:string, input:string, callback:function]"); + + // First parameter must be an instance of SecurityCredentials + if(!SecurityCredentials::HasInstance(args[0])) + return NanThrowError("First parameter for Initialize must be an instance of SecurityCredentials"); + + // Second parameter must be a string + if(!args[1]->IsString()) + return NanThrowError("Second parameter for Initialize must be a string"); + + // Third parameter must be a base64 encoded string + if(!args[2]->IsString()) + return NanThrowError("Second parameter for Initialize must be a string"); + + // Third parameter must be a callback + if(!args[3]->IsFunction()) + return NanThrowError("Third parameter for Initialize must be a callback function"); + + // Let's unpack the values + Local service_principal_name = args[1]->ToString(); + service_principal_name_str = (char *)calloc(service_principal_name->Utf8Length() + 1, sizeof(char)); + service_principal_name->WriteUtf8(service_principal_name_str); + + // Unpack the user name + Local input = args[2]->ToString(); + + if(input->Utf8Length() > 0) { + input_str = (char *)calloc(input->Utf8Length() + 1, sizeof(char)); + input->WriteUtf8(input_str); + + // Now let's get the base64 decoded string + decoded_input_str = (char *)base64_decode(input_str, &decoded_input_str_length); + // Free original allocation + free(input_str); + } + + // Unpack the Security credentials + security_credentials = ObjectWrap::Unwrap(args[0]->ToObject()); + // Create Security context instance + Local security_context_value = constructor_template->GetFunction()->NewInstance(); + // Unwrap the security context + SecurityContext *security_context = ObjectWrap::Unwrap(security_context_value); + // Add a reference to the security_credentials + security_context->security_credentials = security_credentials; + + // Build the call function + SecurityContextStaticInitializeCall *call = (SecurityContextStaticInitializeCall *)calloc(1, sizeof(SecurityContextStaticInitializeCall)); + call->context = security_context; + call->decoded_input_str = decoded_input_str; + call->decoded_input_str_length = decoded_input_str_length; + call->service_principal_name_str = service_principal_name_str; + + // Callback + Local callback = Local::Cast(args[3]); + + // Let's allocate some space + Worker *worker = new Worker(); + worker->error = false; + worker->request.data = worker; + worker->callback = new NanCallback(callback); + worker->parameters = call; + worker->execute = _initializeContext; + worker->mapper = _map_initializeContext; + + // Schedule the worker with lib_uv + uv_queue_work(uv_default_loop(), &worker->request, Process, (uv_after_work_cb)After); + + // Return no value as it's callback based + NanReturnValue(NanUndefined()); +} + +NAN_GETTER(SecurityContext::PayloadGetter) { + NanScope(); + // Unpack the context object + SecurityContext *context = ObjectWrap::Unwrap(args.This()); + // Return the low bits + NanReturnValue(NanNew(context->payload)); +} + +NAN_GETTER(SecurityContext::HasContextGetter) { + NanScope(); + // Unpack the context object + SecurityContext *context = ObjectWrap::Unwrap(args.This()); + // Return the low bits + NanReturnValue(NanNew(context->hasContext)); +} + +// +// Async InitializeContextStep +// +typedef struct SecurityContextStepStaticInitializeCall { + char *service_principal_name_str; + char *decoded_input_str; + int decoded_input_str_length; + SecurityContext *context; +} SecurityContextStepStaticInitializeCall; + +static void _initializeContextStep(Worker *worker) { + // Outbound data array + BYTE *out_bound_data_str = NULL; + // Status of operation + SECURITY_STATUS status; + // Unpack data + SecurityContextStepStaticInitializeCall *call = (SecurityContextStepStaticInitializeCall *)worker->parameters; + SecurityContext *context = call->context; + // Structures used for c calls + SecBufferDesc ibd, obd; + SecBuffer ib, ob; + + // + // Prepare data structure for returned data from SSPI + ob.BufferType = SECBUFFER_TOKEN; + ob.cbBuffer = context->m_PkgInfo->cbMaxToken; + // Allocate space for return data + out_bound_data_str = new BYTE[ob.cbBuffer + sizeof(DWORD)]; + ob.pvBuffer = out_bound_data_str; + // prepare buffer description + obd.cBuffers = 1; + obd.ulVersion = SECBUFFER_VERSION; + obd.pBuffers = &ob; + + // + // Prepare the data we are passing to the SSPI method + if(call->decoded_input_str_length > 0) { + ib.BufferType = SECBUFFER_TOKEN; + ib.cbBuffer = call->decoded_input_str_length; + ib.pvBuffer = call->decoded_input_str; + // prepare buffer description + ibd.cBuffers = 1; + ibd.ulVersion = SECBUFFER_VERSION; + ibd.pBuffers = &ib; + } + + // Perform initialization step + status = _sspi_initializeSecurityContext( + &context->security_credentials->m_Credentials + , context->hasContext == true ? &context->m_Context : NULL + , const_cast(call->service_principal_name_str) + , 0x02 // MUTUAL + , 0 + , 0 // Network + , call->decoded_input_str_length ? &ibd : NULL + , 0 + , &context->m_Context + , &obd + , &context->CtxtAttr + , &context->Expiration + ); + + // If we have a ok or continue let's prepare the result + if(status == SEC_E_OK + || status == SEC_I_COMPLETE_NEEDED + || status == SEC_I_CONTINUE_NEEDED + || status == SEC_I_COMPLETE_AND_CONTINUE + ) { + // Set the new payload + if(context->payload != NULL) free(context->payload); + context->payload = base64_encode((const unsigned char *)ob.pvBuffer, ob.cbBuffer); + worker->return_code = status; + worker->return_value = context; + } else { + worker->error = TRUE; + worker->error_code = status; + worker->error_message = DisplaySECError(status); + } + + // Clean up data + if(call->decoded_input_str != NULL) free(call->decoded_input_str); + if(call->service_principal_name_str != NULL) free(call->service_principal_name_str); +} + +static Handle _map_initializeContextStep(Worker *worker) { + // Unwrap the security context + SecurityContext *context = (SecurityContext *)worker->return_value; + // Return the value + return NanObjectWrapHandle(context); +} + +NAN_METHOD(SecurityContext::InitalizeStep) { + NanScope(); + + char *service_principal_name_str = NULL, *input_str = NULL, *decoded_input_str = NULL; + int decoded_input_str_length = NULL; + + // We need 3 parameters + if(args.Length() != 3) + return NanThrowError("Initialize must be called with [servicePrincipalName:string, input:string, callback:function]"); + + // Second parameter must be a string + if(!args[0]->IsString()) + return NanThrowError("First parameter for Initialize must be a string"); + + // Third parameter must be a base64 encoded string + if(!args[1]->IsString()) + return NanThrowError("Second parameter for Initialize must be a string"); + + // Third parameter must be a base64 encoded string + if(!args[2]->IsFunction()) + return NanThrowError("Third parameter for Initialize must be a callback function"); + + // Let's unpack the values + Local service_principal_name = args[0]->ToString(); + service_principal_name_str = (char *)calloc(service_principal_name->Utf8Length() + 1, sizeof(char)); + service_principal_name->WriteUtf8(service_principal_name_str); + + // Unpack the user name + Local input = args[1]->ToString(); + + if(input->Utf8Length() > 0) { + input_str = (char *)calloc(input->Utf8Length() + 1, sizeof(char)); + input->WriteUtf8(input_str); + // Now let's get the base64 decoded string + decoded_input_str = (char *)base64_decode(input_str, &decoded_input_str_length); + // Free input string + free(input_str); + } + + // Unwrap the security context + SecurityContext *security_context = ObjectWrap::Unwrap(args.This()); + + // Create call structure + SecurityContextStepStaticInitializeCall *call = (SecurityContextStepStaticInitializeCall *)calloc(1, sizeof(SecurityContextStepStaticInitializeCall)); + call->context = security_context; + call->decoded_input_str = decoded_input_str; + call->decoded_input_str_length = decoded_input_str_length; + call->service_principal_name_str = service_principal_name_str; + + // Callback + Local callback = Local::Cast(args[2]); + + // Let's allocate some space + Worker *worker = new Worker(); + worker->error = false; + worker->request.data = worker; + worker->callback = new NanCallback(callback); + worker->parameters = call; + worker->execute = _initializeContextStep; + worker->mapper = _map_initializeContextStep; + + // Schedule the worker with lib_uv + uv_queue_work(uv_default_loop(), &worker->request, Process, (uv_after_work_cb)After); + + // Return no value as it's callback based + NanReturnValue(NanUndefined()); +} + +// +// Async EncryptMessage +// +typedef struct SecurityContextEncryptMessageCall { + SecurityContext *context; + SecurityBufferDescriptor *descriptor; + unsigned long flags; +} SecurityContextEncryptMessageCall; + +static void _encryptMessage(Worker *worker) { + SECURITY_STATUS status; + // Unpack call + SecurityContextEncryptMessageCall *call = (SecurityContextEncryptMessageCall *)worker->parameters; + // Unpack the security context + SecurityContext *context = call->context; + SecurityBufferDescriptor *descriptor = call->descriptor; + + // Let's execute encryption + status = _sspi_EncryptMessage( + &context->m_Context + , call->flags + , &descriptor->secBufferDesc + , 0 + ); + + // We've got ok + if(status == SEC_E_OK) { + int bytesToAllocate = (int)descriptor->bufferSize(); + // Free up existing payload + if(context->payload != NULL) free(context->payload); + // Save the payload + context->payload = base64_encode((unsigned char *)descriptor->toBuffer(), bytesToAllocate); + // Set result + worker->return_code = status; + worker->return_value = context; + } else { + worker->error = TRUE; + worker->error_code = status; + worker->error_message = DisplaySECError(status); + } +} + +static Handle _map_encryptMessage(Worker *worker) { + // Unwrap the security context + SecurityContext *context = (SecurityContext *)worker->return_value; + // Return the value + return NanObjectWrapHandle(context); +} + +NAN_METHOD(SecurityContext::EncryptMessage) { + NanScope(); + + if(args.Length() != 3) + return NanThrowError("EncryptMessage takes an instance of SecurityBufferDescriptor, an integer flag and a callback function"); + if(!SecurityBufferDescriptor::HasInstance(args[0])) + return NanThrowError("EncryptMessage takes an instance of SecurityBufferDescriptor, an integer flag and a callback function"); + if(!args[1]->IsUint32()) + return NanThrowError("EncryptMessage takes an instance of SecurityBufferDescriptor, an integer flag and a callback function"); + if(!args[2]->IsFunction()) + return NanThrowError("EncryptMessage takes an instance of SecurityBufferDescriptor, an integer flag and a callback function"); + + // Unpack the security context + SecurityContext *security_context = ObjectWrap::Unwrap(args.This()); + + // Unpack the descriptor + SecurityBufferDescriptor *descriptor = ObjectWrap::Unwrap(args[0]->ToObject()); + + // Create call structure + SecurityContextEncryptMessageCall *call = (SecurityContextEncryptMessageCall *)calloc(1, sizeof(SecurityContextEncryptMessageCall)); + call->context = security_context; + call->descriptor = descriptor; + call->flags = (unsigned long)args[1]->ToInteger()->Value(); + + // Callback + Local callback = Local::Cast(args[2]); + + // Let's allocate some space + Worker *worker = new Worker(); + worker->error = false; + worker->request.data = worker; + worker->callback = new NanCallback(callback); + worker->parameters = call; + worker->execute = _encryptMessage; + worker->mapper = _map_encryptMessage; + + // Schedule the worker with lib_uv + uv_queue_work(uv_default_loop(), &worker->request, Process, (uv_after_work_cb)After); + + // Return no value as it's callback based + NanReturnValue(NanUndefined()); +} + +// +// Async DecryptMessage +// +typedef struct SecurityContextDecryptMessageCall { + SecurityContext *context; + SecurityBufferDescriptor *descriptor; +} SecurityContextDecryptMessageCall; + +static void _decryptMessage(Worker *worker) { + unsigned long quality = 0; + SECURITY_STATUS status; + + // Unpack parameters + SecurityContextDecryptMessageCall *call = (SecurityContextDecryptMessageCall *)worker->parameters; + SecurityContext *context = call->context; + SecurityBufferDescriptor *descriptor = call->descriptor; + + // Let's execute encryption + status = _sspi_DecryptMessage( + &context->m_Context + , &descriptor->secBufferDesc + , 0 + , (unsigned long)&quality + ); + + // We've got ok + if(status == SEC_E_OK) { + int bytesToAllocate = (int)descriptor->bufferSize(); + // Free up existing payload + if(context->payload != NULL) free(context->payload); + // Save the payload + context->payload = base64_encode((unsigned char *)descriptor->toBuffer(), bytesToAllocate); + // Set return values + worker->return_code = status; + worker->return_value = context; + } else { + worker->error = TRUE; + worker->error_code = status; + worker->error_message = DisplaySECError(status); + } +} + +static Handle _map_decryptMessage(Worker *worker) { + // Unwrap the security context + SecurityContext *context = (SecurityContext *)worker->return_value; + // Return the value + return NanObjectWrapHandle(context); +} + +NAN_METHOD(SecurityContext::DecryptMessage) { + NanScope(); + + if(args.Length() != 2) + return NanThrowError("DecryptMessage takes an instance of SecurityBufferDescriptor and a callback function"); + if(!SecurityBufferDescriptor::HasInstance(args[0])) + return NanThrowError("DecryptMessage takes an instance of SecurityBufferDescriptor and a callback function"); + if(!args[1]->IsFunction()) + return NanThrowError("DecryptMessage takes an instance of SecurityBufferDescriptor and a callback function"); + + // Unpack the security context + SecurityContext *security_context = ObjectWrap::Unwrap(args.This()); + // Unpack the descriptor + SecurityBufferDescriptor *descriptor = ObjectWrap::Unwrap(args[0]->ToObject()); + // Create call structure + SecurityContextDecryptMessageCall *call = (SecurityContextDecryptMessageCall *)calloc(1, sizeof(SecurityContextDecryptMessageCall)); + call->context = security_context; + call->descriptor = descriptor; + + // Callback + Local callback = Local::Cast(args[1]); + + // Let's allocate some space + Worker *worker = new Worker(); + worker->error = false; + worker->request.data = worker; + worker->callback = new NanCallback(callback); + worker->parameters = call; + worker->execute = _decryptMessage; + worker->mapper = _map_decryptMessage; + + // Schedule the worker with lib_uv + uv_queue_work(uv_default_loop(), &worker->request, Process, (uv_after_work_cb)After); + + // Return no value as it's callback based + NanReturnValue(NanUndefined()); +} + +// +// Async QueryContextAttributes +// +typedef struct SecurityContextQueryContextAttributesCall { + SecurityContext *context; + uint32_t attribute; +} SecurityContextQueryContextAttributesCall; + +static void _queryContextAttributes(Worker *worker) { + SECURITY_STATUS status; + + // Cast to data structure + SecurityContextQueryContextAttributesCall *call = (SecurityContextQueryContextAttributesCall *)worker->parameters; + + // Allocate some space + SecPkgContext_Sizes *sizes = (SecPkgContext_Sizes *)calloc(1, sizeof(SecPkgContext_Sizes)); + // Let's grab the query context attribute + status = _sspi_QueryContextAttributes( + &call->context->m_Context, + call->attribute, + sizes + ); + + if(status == SEC_E_OK) { + worker->return_code = status; + worker->return_value = sizes; + } else { + worker->error = TRUE; + worker->error_code = status; + worker->error_message = DisplaySECError(status); + } +} + +static Handle _map_queryContextAttributes(Worker *worker) { + NanScope(); + + // Cast to data structure + SecurityContextQueryContextAttributesCall *call = (SecurityContextQueryContextAttributesCall *)worker->parameters; + // Unpack the attribute + uint32_t attribute = call->attribute; + + // Convert data + if(attribute == SECPKG_ATTR_SIZES) { + SecPkgContext_Sizes *sizes = (SecPkgContext_Sizes *)worker->return_value; + // Create object + Local value = Object::New(); + value->Set(String::New("maxToken"), Integer::New(sizes->cbMaxToken)); + value->Set(String::New("maxSignature"), Integer::New(sizes->cbMaxSignature)); + value->Set(String::New("blockSize"), Integer::New(sizes->cbBlockSize)); + value->Set(String::New("securityTrailer"), Integer::New(sizes->cbSecurityTrailer)); + NanReturnValue(value); + } + + // Return the value + NanReturnValue(NanNull()); +} + +NAN_METHOD(SecurityContext::QueryContextAttributes) { + NanScope(); + + if(args.Length() != 2) + return NanThrowError("QueryContextAttributes method takes a an integer Attribute specifier and a callback function"); + if(!args[0]->IsInt32()) + return NanThrowError("QueryContextAttributes method takes a an integer Attribute specifier and a callback function"); + if(!args[1]->IsFunction()) + return NanThrowError("QueryContextAttributes method takes a an integer Attribute specifier and a callback function"); + + // Unpack the security context + SecurityContext *security_context = ObjectWrap::Unwrap(args.This()); + + // Unpack the int value + uint32_t attribute = args[0]->ToInt32()->Value(); + + // Check that we have a supported attribute + if(attribute != SECPKG_ATTR_SIZES) + return NanThrowError("QueryContextAttributes only supports the SECPKG_ATTR_SIZES attribute"); + + // Create call structure + SecurityContextQueryContextAttributesCall *call = (SecurityContextQueryContextAttributesCall *)calloc(1, sizeof(SecurityContextQueryContextAttributesCall)); + call->attribute = attribute; + call->context = security_context; + + // Callback + Local callback = Local::Cast(args[1]); + + // Let's allocate some space + Worker *worker = new Worker(); + worker->error = false; + worker->request.data = worker; + worker->callback = new NanCallback(callback); + worker->parameters = call; + worker->execute = _queryContextAttributes; + worker->mapper = _map_queryContextAttributes; + + // Schedule the worker with lib_uv + uv_queue_work(uv_default_loop(), &worker->request, Process, (uv_after_work_cb)After); + + // Return no value as it's callback based + NanReturnValue(NanUndefined()); +} + +void SecurityContext::Initialize(Handle target) { + // Grab the scope of the call from Node + NanScope(); + + // Define a new function template + Local t = NanNew(New); + t->InstanceTemplate()->SetInternalFieldCount(1); + t->SetClassName(NanNew("SecurityContext")); + + // Class methods + NODE_SET_METHOD(t, "initialize", InitializeContext); + + // Set up method for the instance + NODE_SET_PROTOTYPE_METHOD(t, "initialize", InitalizeStep); + NODE_SET_PROTOTYPE_METHOD(t, "decryptMessage", DecryptMessage); + NODE_SET_PROTOTYPE_METHOD(t, "queryContextAttributes", QueryContextAttributes); + NODE_SET_PROTOTYPE_METHOD(t, "encryptMessage", EncryptMessage); + + // Get prototype + Local proto = t->PrototypeTemplate(); + + // Getter for the response + proto->SetAccessor(NanNew("payload"), SecurityContext::PayloadGetter); + proto->SetAccessor(NanNew("hasContext"), SecurityContext::HasContextGetter); + + // Set persistent + NanAssignPersistent(constructor_template, t); + + // Set the symbol + target->ForceSet(NanNew("SecurityContext"), t->GetFunction()); +} + +static LPSTR DisplaySECError(DWORD ErrCode) { + LPSTR pszName = NULL; // WinError.h + + switch(ErrCode) { + case SEC_E_BUFFER_TOO_SMALL: + pszName = "SEC_E_BUFFER_TOO_SMALL - The message buffer is too small. Used with the Digest SSP."; + break; + + case SEC_E_CRYPTO_SYSTEM_INVALID: + pszName = "SEC_E_CRYPTO_SYSTEM_INVALID - The cipher chosen for the security context is not supported. Used with the Digest SSP."; + break; + case SEC_E_INCOMPLETE_MESSAGE: + pszName = "SEC_E_INCOMPLETE_MESSAGE - The data in the input buffer is incomplete. The application needs to read more data from the server and call DecryptMessageSync (General) again."; + break; + + case SEC_E_INVALID_HANDLE: + pszName = "SEC_E_INVALID_HANDLE - A context handle that is not valid was specified in the phContext parameter. Used with the Digest and Schannel SSPs."; + break; + + case SEC_E_INVALID_TOKEN: + pszName = "SEC_E_INVALID_TOKEN - The buffers are of the wrong type or no buffer of type SECBUFFER_DATA was found. Used with the Schannel SSP."; + break; + + case SEC_E_MESSAGE_ALTERED: + pszName = "SEC_E_MESSAGE_ALTERED - The message has been altered. Used with the Digest and Schannel SSPs."; + break; + + case SEC_E_OUT_OF_SEQUENCE: + pszName = "SEC_E_OUT_OF_SEQUENCE - The message was not received in the correct sequence."; + break; + + case SEC_E_QOP_NOT_SUPPORTED: + pszName = "SEC_E_QOP_NOT_SUPPORTED - Neither confidentiality nor integrity are supported by the security context. Used with the Digest SSP."; + break; + + case SEC_I_CONTEXT_EXPIRED: + pszName = "SEC_I_CONTEXT_EXPIRED - The message sender has finished using the connection and has initiated a shutdown."; + break; + + case SEC_I_RENEGOTIATE: + pszName = "SEC_I_RENEGOTIATE - The remote party requires a new handshake sequence or the application has just initiated a shutdown."; + break; + + case SEC_E_ENCRYPT_FAILURE: + pszName = "SEC_E_ENCRYPT_FAILURE - The specified data could not be encrypted."; + break; + + case SEC_E_DECRYPT_FAILURE: + pszName = "SEC_E_DECRYPT_FAILURE - The specified data could not be decrypted."; + break; + case -1: + pszName = "Failed to load security.dll library"; + break; + } + + return pszName; +} + diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.h b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.h new file mode 100644 index 0000000..cb7f331 --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.h @@ -0,0 +1,72 @@ +#ifndef SECURITY_CONTEXT_H +#define SECURITY_CONTEXT_H + +#include +#include +#include + +#define SECURITY_WIN32 1 + +#include +#include +#include "security_credentials.h" +#include "../worker.h" +#include "nan.h" + +extern "C" { + #include "../kerberos_sspi.h" + #include "../base64.h" +} + +using namespace v8; +using namespace node; + +class SecurityContext : public ObjectWrap { + public: + SecurityContext(); + ~SecurityContext(); + + // Security info package + PSecPkgInfo m_PkgInfo; + // Do we have a context + bool hasContext; + // Reference to security credentials + SecurityCredentials *security_credentials; + // Security context + CtxtHandle m_Context; + // Attributes + DWORD CtxtAttr; + // Expiry time for ticket + TimeStamp Expiration; + // Payload + char *payload; + + // Has instance check + static inline bool HasInstance(Handle val) { + if (!val->IsObject()) return false; + Local obj = val->ToObject(); + return NanNew(constructor_template)->HasInstance(obj); + }; + + // Functions available from V8 + static void Initialize(Handle target); + static NAN_METHOD(InitializeContext); + static NAN_METHOD(InitalizeStep); + static NAN_METHOD(DecryptMessage); + static NAN_METHOD(QueryContextAttributes); + static NAN_METHOD(EncryptMessage); + + // Payload getter + static NAN_GETTER(PayloadGetter); + // hasContext getter + static NAN_GETTER(HasContextGetter); + + // Constructor used for creating new Long objects from C++ + static Persistent constructor_template; + + private: + // Create a new instance + static NAN_METHOD(New); +}; + +#endif diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.js b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.js new file mode 100644 index 0000000..ef04e92 --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.js @@ -0,0 +1,3 @@ +var SecurityContextNative = require('../../../build/Release/kerberos').SecurityContext; +// Export the modified class +exports.SecurityContext = SecurityContextNative; \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.cc b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.cc new file mode 100644 index 0000000..fc2a3d8 --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.cc @@ -0,0 +1,351 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "security_credentials.h" + +#ifndef ARRAY_SIZE +# define ARRAY_SIZE(a) (sizeof((a)) / sizeof((a)[0])) +#endif + +static LPSTR DisplaySECError(DWORD ErrCode); + +Persistent SecurityCredentials::constructor_template; + +SecurityCredentials::SecurityCredentials() : ObjectWrap() { +} + +SecurityCredentials::~SecurityCredentials() { +} + +NAN_METHOD(SecurityCredentials::New) { + NanScope(); + // Create security credentials instance + SecurityCredentials *security_credentials = new SecurityCredentials(); + // Wrap it + security_credentials->Wrap(args.This()); + // Return the object + NanReturnValue(args.This()); +} + +// Call structs +typedef struct SecurityCredentialCall { + char *package_str; + char *username_str; + char *password_str; + char *domain_str; + SecurityCredentials *credentials; +} SecurityCredentialCall; + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// authGSSClientInit +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +static void _authSSPIAquire(Worker *worker) { + // Status of operation + SECURITY_STATUS status; + + // Unpack data + SecurityCredentialCall *call = (SecurityCredentialCall *)worker->parameters; + + // // Unwrap the credentials + // SecurityCredentials *security_credentials = (SecurityCredentials *)call->credentials; + SecurityCredentials *security_credentials = new SecurityCredentials(); + + // If we have domain string + if(call->domain_str != NULL) { + security_credentials->m_Identity.Domain = USTR(_tcsdup(call->domain_str)); + security_credentials->m_Identity.DomainLength = (unsigned long)_tcslen(call->domain_str); + } else { + security_credentials->m_Identity.Domain = NULL; + security_credentials->m_Identity.DomainLength = 0; + } + + // Set up the user + security_credentials->m_Identity.User = USTR(_tcsdup(call->username_str)); + security_credentials->m_Identity.UserLength = (unsigned long)_tcslen(call->username_str); + + // If we have a password string + if(call->password_str != NULL) { + // Set up the password + security_credentials->m_Identity.Password = USTR(_tcsdup(call->password_str)); + security_credentials->m_Identity.PasswordLength = (unsigned long)_tcslen(call->password_str); + } + + #ifdef _UNICODE + security_credentials->m_Identity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; + #else + security_credentials->m_Identity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; + #endif + + // Attempt to acquire credentials + status = _sspi_AcquireCredentialsHandle( + NULL, + call->package_str, + SECPKG_CRED_OUTBOUND, + NULL, + call->password_str != NULL ? &security_credentials->m_Identity : NULL, + NULL, NULL, + &security_credentials->m_Credentials, + &security_credentials->Expiration + ); + + // We have an error + if(status != SEC_E_OK) { + worker->error = TRUE; + worker->error_code = status; + worker->error_message = DisplaySECError(status); + } else { + worker->return_code = status; + worker->return_value = security_credentials; + } + + // Free up parameter structure + if(call->package_str != NULL) free(call->package_str); + if(call->domain_str != NULL) free(call->domain_str); + if(call->password_str != NULL) free(call->password_str); + if(call->username_str != NULL) free(call->username_str); + free(call); +} + +static Handle _map_authSSPIAquire(Worker *worker) { + return NanNull(); +} + +NAN_METHOD(SecurityCredentials::Aquire) { + NanScope(); + + char *package_str = NULL, *username_str = NULL, *password_str = NULL, *domain_str = NULL; + // Unpack the variables + if(args.Length() != 2 && args.Length() != 3 && args.Length() != 4 && args.Length() != 5) + return NanThrowError("Aquire must be called with either [package:string, username:string, [password:string, domain:string], callback:function]"); + + if(!args[0]->IsString()) + return NanThrowError("Aquire must be called with either [package:string, username:string, [password:string, domain:string], callback:function]"); + + if(!args[1]->IsString()) + return NanThrowError("Aquire must be called with either [package:string, username:string, [password:string, domain:string], callback:function]"); + + if(args.Length() == 3 && (!args[2]->IsString() && !args[2]->IsFunction())) + return NanThrowError("Aquire must be called with either [package:string, username:string, [password:string, domain:string], callback:function]"); + + if(args.Length() == 4 && (!args[3]->IsString() && !args[3]->IsUndefined() && !args[3]->IsNull()) && !args[3]->IsFunction()) + return NanThrowError("Aquire must be called with either [package:string, username:string, [password:string, domain:string], callback:function]"); + + if(args.Length() == 5 && !args[4]->IsFunction()) + return NanThrowError("Aquire must be called with either [package:string, username:string, [password:string, domain:string], callback:function]"); + + Local callbackHandle; + + // Figure out which parameter is the callback + if(args.Length() == 5) { + callbackHandle = Local::Cast(args[4]); + } else if(args.Length() == 4) { + callbackHandle = Local::Cast(args[3]); + } else if(args.Length() == 3) { + callbackHandle = Local::Cast(args[2]); + } + + // Unpack the package + Local package = args[0]->ToString(); + package_str = (char *)calloc(package->Utf8Length() + 1, sizeof(char)); + package->WriteUtf8(package_str); + + // Unpack the user name + Local username = args[1]->ToString(); + username_str = (char *)calloc(username->Utf8Length() + 1, sizeof(char)); + username->WriteUtf8(username_str); + + // If we have a password + if(args.Length() == 3 || args.Length() == 4 || args.Length() == 5) { + Local password = args[2]->ToString(); + password_str = (char *)calloc(password->Utf8Length() + 1, sizeof(char)); + password->WriteUtf8(password_str); + } + + // If we have a domain + if((args.Length() == 4 || args.Length() == 5) && args[3]->IsString()) { + Local domain = args[3]->ToString(); + domain_str = (char *)calloc(domain->Utf8Length() + 1, sizeof(char)); + domain->WriteUtf8(domain_str); + } + + // Allocate call structure + SecurityCredentialCall *call = (SecurityCredentialCall *)calloc(1, sizeof(SecurityCredentialCall)); + call->domain_str = domain_str; + call->package_str = package_str; + call->password_str = password_str; + call->username_str = username_str; + + // Unpack the callback + NanCallback *callback = new NanCallback(callbackHandle); + + // Let's allocate some space + Worker *worker = new Worker(); + worker->error = false; + worker->request.data = worker; + worker->callback = callback; + worker->parameters = call; + worker->execute = _authSSPIAquire; + worker->mapper = _map_authSSPIAquire; + + // Schedule the worker with lib_uv + uv_queue_work(uv_default_loop(), &worker->request, SecurityCredentials::Process, (uv_after_work_cb)SecurityCredentials::After); + + // Return no value as it's callback based + NanReturnValue(NanUndefined()); +} + +void SecurityCredentials::Initialize(Handle target) { + // Grab the scope of the call from Node + NanScope(); + + // Define a new function template + Local t = NanNew(New); + t->InstanceTemplate()->SetInternalFieldCount(1); + t->SetClassName(NanNew("SecurityCredentials")); + + // Class methods + NODE_SET_METHOD(t, "aquire", Aquire); + + // Set persistent + NanAssignPersistent(constructor_template, t); + + // Set the symbol + target->ForceSet(NanNew("SecurityCredentials"), t->GetFunction()); + + // Attempt to load the security.dll library + load_library(); +} + +static LPSTR DisplaySECError(DWORD ErrCode) { + LPSTR pszName = NULL; // WinError.h + + switch(ErrCode) { + case SEC_E_BUFFER_TOO_SMALL: + pszName = "SEC_E_BUFFER_TOO_SMALL - The message buffer is too small. Used with the Digest SSP."; + break; + + case SEC_E_CRYPTO_SYSTEM_INVALID: + pszName = "SEC_E_CRYPTO_SYSTEM_INVALID - The cipher chosen for the security context is not supported. Used with the Digest SSP."; + break; + case SEC_E_INCOMPLETE_MESSAGE: + pszName = "SEC_E_INCOMPLETE_MESSAGE - The data in the input buffer is incomplete. The application needs to read more data from the server and call DecryptMessage (General) again."; + break; + + case SEC_E_INVALID_HANDLE: + pszName = "SEC_E_INVALID_HANDLE - A context handle that is not valid was specified in the phContext parameter. Used with the Digest and Schannel SSPs."; + break; + + case SEC_E_INVALID_TOKEN: + pszName = "SEC_E_INVALID_TOKEN - The buffers are of the wrong type or no buffer of type SECBUFFER_DATA was found. Used with the Schannel SSP."; + break; + + case SEC_E_MESSAGE_ALTERED: + pszName = "SEC_E_MESSAGE_ALTERED - The message has been altered. Used with the Digest and Schannel SSPs."; + break; + + case SEC_E_OUT_OF_SEQUENCE: + pszName = "SEC_E_OUT_OF_SEQUENCE - The message was not received in the correct sequence."; + break; + + case SEC_E_QOP_NOT_SUPPORTED: + pszName = "SEC_E_QOP_NOT_SUPPORTED - Neither confidentiality nor integrity are supported by the security context. Used with the Digest SSP."; + break; + + case SEC_I_CONTEXT_EXPIRED: + pszName = "SEC_I_CONTEXT_EXPIRED - The message sender has finished using the connection and has initiated a shutdown."; + break; + + case SEC_I_RENEGOTIATE: + pszName = "SEC_I_RENEGOTIATE - The remote party requires a new handshake sequence or the application has just initiated a shutdown."; + break; + + case SEC_E_ENCRYPT_FAILURE: + pszName = "SEC_E_ENCRYPT_FAILURE - The specified data could not be encrypted."; + break; + + case SEC_E_DECRYPT_FAILURE: + pszName = "SEC_E_DECRYPT_FAILURE - The specified data could not be decrypted."; + break; + case -1: + pszName = "Failed to load security.dll library"; + break; + + } + + return pszName; +} + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// UV Lib callbacks +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +void SecurityCredentials::Process(uv_work_t* work_req) { + // Grab the worker + Worker *worker = static_cast(work_req->data); + // Execute the worker code + worker->execute(worker); +} + +void SecurityCredentials::After(uv_work_t* work_req) { + // Grab the scope of the call from Node + NanScope(); + + // Get the worker reference + Worker *worker = static_cast(work_req->data); + + // If we have an error + if(worker->error) { + Local err = v8::Exception::Error(NanNew(worker->error_message)); + Local obj = err->ToObject(); + obj->Set(NanNew("code"), NanNew(worker->error_code)); + Local args[2] = { err, NanNull() }; + // Execute the error + v8::TryCatch try_catch; + + // Call the callback + worker->callback->Call(ARRAY_SIZE(args), args); + + // If we have an exception handle it as a fatalexception + if (try_catch.HasCaught()) { + node::FatalException(try_catch); + } + } else { + SecurityCredentials *return_value = (SecurityCredentials *)worker->return_value; + // Create a new instance + Local result = NanNew(constructor_template)->GetFunction()->NewInstance(); + // Unwrap the credentials + SecurityCredentials *security_credentials = ObjectWrap::Unwrap(result); + // Set the values + security_credentials->m_Identity = return_value->m_Identity; + security_credentials->m_Credentials = return_value->m_Credentials; + security_credentials->Expiration = return_value->Expiration; + // Set up the callback with a null first + Handle args[2] = { NanNull(), result}; + // Wrap the callback function call in a TryCatch so that we can call + // node's FatalException afterwards. This makes it possible to catch + // the exception from JavaScript land using the + // process.on('uncaughtException') event. + v8::TryCatch try_catch; + + // Call the callback + worker->callback->Call(ARRAY_SIZE(args), args); + + // If we have an exception handle it as a fatalexception + if (try_catch.HasCaught()) { + node::FatalException(try_catch); + } + } + + // Clean up the memory + delete worker->callback; + delete worker; +} + diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.h b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.h new file mode 100644 index 0000000..41f4327 --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.h @@ -0,0 +1,67 @@ +#ifndef SECURITY_CREDENTIALS_H +#define SECURITY_CREDENTIALS_H + +#include +#include +#include + +#define SECURITY_WIN32 1 + +#include +#include +#include +#include "nan.h" +#include "../worker.h" +#include + +extern "C" { + #include "../kerberos_sspi.h" +} + +// SEC_WINNT_AUTH_IDENTITY makes it unusually hard +// to compile for both Unicode and ansi, so I use this macro: +#ifdef _UNICODE +#define USTR(str) (str) +#else +#define USTR(str) ((unsigned char*)(str)) +#endif + +using namespace v8; +using namespace node; + +class SecurityCredentials : public ObjectWrap { + public: + SecurityCredentials(); + ~SecurityCredentials(); + + // Pointer to context object + SEC_WINNT_AUTH_IDENTITY m_Identity; + // credentials + CredHandle m_Credentials; + // Expiry time for ticket + TimeStamp Expiration; + + // Has instance check + static inline bool HasInstance(Handle val) { + if (!val->IsObject()) return false; + Local obj = val->ToObject(); + return NanNew(constructor_template)->HasInstance(obj); + }; + + // Functions available from V8 + static void Initialize(Handle target); + static NAN_METHOD(Aquire); + + // Constructor used for creating new Long objects from C++ + static Persistent constructor_template; + + private: + // Create a new instance + static NAN_METHOD(New); + // Handles the uv calls + static void Process(uv_work_t* work_req); + // Called after work is done + static void After(uv_work_t* work_req); +}; + +#endif \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.js b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.js new file mode 100644 index 0000000..4215c92 --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.js @@ -0,0 +1,22 @@ +var SecurityCredentialsNative = require('../../../build/Release/kerberos').SecurityCredentials; + +// Add simple kebros helper +SecurityCredentialsNative.aquire_kerberos = function(username, password, domain, callback) { + if(typeof password == 'function') { + callback = password; + password = null; + } else if(typeof domain == 'function') { + callback = domain; + domain = null; + } + + // We are going to use the async version + if(typeof callback == 'function') { + return SecurityCredentialsNative.aquire('Kerberos', username, password, domain, callback); + } else { + return SecurityCredentialsNative.aquireSync('Kerberos', username, password, domain); + } +} + +// Export the modified class +exports.SecurityCredentials = SecurityCredentialsNative; \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/worker.cc b/node_modules/mongodb/node_modules/kerberos/lib/worker.cc new file mode 100644 index 0000000..e7a472f --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/lib/worker.cc @@ -0,0 +1,7 @@ +#include "worker.h" + +Worker::Worker() { +} + +Worker::~Worker() { +} \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/worker.h b/node_modules/mongodb/node_modules/kerberos/lib/worker.h new file mode 100644 index 0000000..cbc7f6a --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/lib/worker.h @@ -0,0 +1,38 @@ +#ifndef WORKER_H_ +#define WORKER_H_ + +#include +#include +#include +#include + +using namespace node; +using namespace v8; + +class Worker { + public: + Worker(); + virtual ~Worker(); + + // libuv's request struct. + uv_work_t request; + // Callback + NanCallback *callback; + // Parameters + void *parameters; + // Results + void *return_value; + // Did we raise an error + bool error; + // The error message + char *error_message; + // Error code if not message + int error_code; + // Any return code + int return_code; + // Method we are going to fire + void (*execute)(Worker *worker); + Handle (*mapper)(Worker *worker); +}; + +#endif // WORKER_H_ diff --git a/node_modules/mongodb/node_modules/kerberos/node_modules/nan/.dntrc b/node_modules/mongodb/node_modules/kerberos/node_modules/nan/.dntrc new file mode 100644 index 0000000..47971da --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/node_modules/nan/.dntrc @@ -0,0 +1,30 @@ +## DNT config file +## see https://github.com/rvagg/dnt + +NODE_VERSIONS="\ + master \ + v0.11.13 \ + v0.10.30 \ + v0.10.29 \ + v0.10.28 \ + v0.10.26 \ + v0.10.25 \ + v0.10.24 \ + v0.10.23 \ + v0.10.22 \ + v0.10.21 \ + v0.10.20 \ + v0.10.19 \ + v0.8.28 \ + v0.8.27 \ + v0.8.26 \ + v0.8.24 \ +" +OUTPUT_PREFIX="nan-" +TEST_CMD=" \ + cd /dnt/ && \ + npm install && \ + node_modules/.bin/node-gyp --nodedir /usr/src/node/ rebuild --directory test && \ + node_modules/.bin/tap --gc test/js/*-test.js \ +" + diff --git a/node_modules/mongodb/node_modules/kerberos/node_modules/nan/CHANGELOG.md b/node_modules/mongodb/node_modules/kerberos/node_modules/nan/CHANGELOG.md new file mode 100644 index 0000000..146cbb5 --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/node_modules/nan/CHANGELOG.md @@ -0,0 +1,200 @@ +# NAN ChangeLog + +### Version 1.3.0: current Node unstable: 0.11.13, Node stable: 0.10.30 + + +**1.3.0 Aug 2 2014** + + - Added NanNew(std::string) + - Added NanNew(std::string&) + - Added NanAsciiString helper class + - Added NanUtf8String helper class + - Added NanUcs2String helper class + - Deprecated NanRawString() + - Deprecated NanCString() + - Added NanGetIsolateData(v8::Isolate *isolate) + - Added NanMakeCallback(v8::Handle target, v8::Handle func, int argc, v8::Handle* argv) + - Added NanMakeCallback(v8::Handle target, v8::Handle symbol, int argc, v8::Handle* argv) + - Added NanMakeCallback(v8::Handle target, const char* method, int argc, v8::Handle* argv) + - Added NanSetTemplate(v8::Handle templ, v8::Handle name , v8::Handle value, v8::PropertyAttribute attributes) + - Added NanSetPrototypeTemplate(v8::Local templ, v8::Handle name, v8::Handle value, v8::PropertyAttribute attributes) + - Added NanSetInstanceTemplate(v8::Local templ, const char *name, v8::Handle value) + - Added NanSetInstanceTemplate(v8::Local templ, v8::Handle name, v8::Handle value, v8::PropertyAttribute attributes) + +**1.2.0 Jun 5 2014** + + - Add NanSetPrototypeTemplate + - Changed NAN_WEAK_CALLBACK internals, switched _NanWeakCallbackData to class, + introduced _NanWeakCallbackDispatcher + - Removed -Wno-unused-local-typedefs from test builds + - Made test builds Windows compatible ('Sleep()') + +**1.1.2 May 28 2014** + + - Release to fix more stuff-ups in 1.1.1 + +**1.1.1 May 28 2014** + + - Release to fix version mismatch in nan.h and lack of changelog entry for 1.1.0 + +**1.1.0 May 25 2014** + + - Remove nan_isolate, use v8::Isolate::GetCurrent() internally instead + - Additional explicit overloads for NanNew(): (char*,int), (uint8_t*[,int]), + (uint16_t*[,int), double, int, unsigned int, bool, v8::String::ExternalStringResource*, + v8::String::ExternalAsciiStringResource* + - Deprecate NanSymbol() + - Added SetErrorMessage() and ErrorMessage() to NanAsyncWorker + +**1.0.0 May 4 2014** + + - Heavy API changes for V8 3.25 / Node 0.11.13 + - Use cpplint.py + - Removed NanInitPersistent + - Removed NanPersistentToLocal + - Removed NanFromV8String + - Removed NanMakeWeak + - Removed NanNewLocal + - Removed NAN_WEAK_CALLBACK_OBJECT + - Removed NAN_WEAK_CALLBACK_DATA + - Introduce NanNew, replaces NanNewLocal, NanPersistentToLocal, adds many overloaded typed versions + - Introduce NanUndefined, NanNull, NanTrue and NanFalse + - Introduce NanEscapableScope and NanEscapeScope + - Introduce NanMakeWeakPersistent (requires a special callback to work on both old and new node) + - Introduce NanMakeCallback for node::MakeCallback + - Introduce NanSetTemplate + - Introduce NanGetCurrentContext + - Introduce NanCompileScript and NanRunScript + - Introduce NanAdjustExternalMemory + - Introduce NanAddGCEpilogueCallback, NanAddGCPrologueCallback, NanRemoveGCEpilogueCallback, NanRemoveGCPrologueCallback + - Introduce NanGetHeapStatistics + - Rename NanAsyncWorker#SavePersistent() to SaveToPersistent() + +**0.8.0 Jan 9 2014** + + - NanDispose -> NanDisposePersistent, deprecate NanDispose + - Extract _NAN_*_RETURN_TYPE, pull up NAN_*() + +**0.7.1 Jan 9 2014** + + - Fixes to work against debug builds of Node + - Safer NanPersistentToLocal (avoid reinterpret_cast) + - Speed up common NanRawString case by only extracting flattened string when necessary + +**0.7.0 Dec 17 2013** + + - New no-arg form of NanCallback() constructor. + - NanCallback#Call takes Handle rather than Local + - Removed deprecated NanCallback#Run method, use NanCallback#Call instead + - Split off _NAN_*_ARGS_TYPE from _NAN_*_ARGS + - Restore (unofficial) Node 0.6 compatibility at NanCallback#Call() + - Introduce NanRawString() for char* (or appropriate void*) from v8::String + (replacement for NanFromV8String) + - Introduce NanCString() for null-terminated char* from v8::String + +**0.6.0 Nov 21 2013** + + - Introduce NanNewLocal(v8::Handle value) for use in place of + v8::Local::New(...) since v8 started requiring isolate in Node 0.11.9 + +**0.5.2 Nov 16 2013** + + - Convert SavePersistent and GetFromPersistent in NanAsyncWorker from protected and public + +**0.5.1 Nov 12 2013** + + - Use node::MakeCallback() instead of direct v8::Function::Call() + +**0.5.0 Nov 11 2013** + + - Added @TooTallNate as collaborator + - New, much simpler, "include_dirs" for binding.gyp + - Added full range of NAN_INDEX_* macros to match NAN_PROPERTY_* macros + +**0.4.4 Nov 2 2013** + + - Isolate argument from v8::Persistent::MakeWeak removed for 0.11.8+ + +**0.4.3 Nov 2 2013** + + - Include node_object_wrap.h, removed from node.h for Node 0.11.8. + +**0.4.2 Nov 2 2013** + + - Handle deprecation of v8::Persistent::Dispose(v8::Isolate* isolate)) for + Node 0.11.8 release. + +**0.4.1 Sep 16 2013** + + - Added explicit `#include ` as it was removed from node.h for v0.11.8 + +**0.4.0 Sep 2 2013** + + - Added NAN_INLINE and NAN_DEPRECATED and made use of them + - Added NanError, NanTypeError and NanRangeError + - Cleaned up code + +**0.3.2 Aug 30 2013** + + - Fix missing scope declaration in GetFromPersistent() and SaveToPersistent + in NanAsyncWorker + +**0.3.1 Aug 20 2013** + + - fix "not all control paths return a value" compile warning on some platforms + +**0.3.0 Aug 19 2013** + + - Made NAN work with NPM + - Lots of fixes to NanFromV8String, pulling in features from new Node core + - Changed node::encoding to Nan::Encoding in NanFromV8String to unify the API + - Added optional error number argument for NanThrowError() + - Added NanInitPersistent() + - Added NanReturnNull() and NanReturnEmptyString() + - Added NanLocker and NanUnlocker + - Added missing scopes + - Made sure to clear disposed Persistent handles + - Changed NanAsyncWorker to allocate error messages on the heap + - Changed NanThrowError(Local) to NanThrowError(Handle) + - Fixed leak in NanAsyncWorker when errmsg is used + +**0.2.2 Aug 5 2013** + + - Fixed usage of undefined variable with node::BASE64 in NanFromV8String() + +**0.2.1 Aug 5 2013** + + - Fixed 0.8 breakage, node::BUFFER encoding type not available in 0.8 for + NanFromV8String() + +**0.2.0 Aug 5 2013** + + - Added NAN_PROPERTY_GETTER, NAN_PROPERTY_SETTER, NAN_PROPERTY_ENUMERATOR, + NAN_PROPERTY_DELETER, NAN_PROPERTY_QUERY + - Extracted _NAN_METHOD_ARGS, _NAN_GETTER_ARGS, _NAN_SETTER_ARGS, + _NAN_PROPERTY_GETTER_ARGS, _NAN_PROPERTY_SETTER_ARGS, + _NAN_PROPERTY_ENUMERATOR_ARGS, _NAN_PROPERTY_DELETER_ARGS, + _NAN_PROPERTY_QUERY_ARGS + - Added NanGetInternalFieldPointer, NanSetInternalFieldPointer + - Added NAN_WEAK_CALLBACK, NAN_WEAK_CALLBACK_OBJECT, + NAN_WEAK_CALLBACK_DATA, NanMakeWeak + - Renamed THROW_ERROR to _NAN_THROW_ERROR + - Added NanNewBufferHandle(char*, size_t, node::smalloc::FreeCallback, void*) + - Added NanBufferUse(char*, uint32_t) + - Added NanNewContextHandle(v8::ExtensionConfiguration*, + v8::Handle, v8::Handle) + - Fixed broken NanCallback#GetFunction() + - Added optional encoding and size arguments to NanFromV8String() + - Added NanGetPointerSafe() and NanSetPointerSafe() + - Added initial test suite (to be expanded) + - Allow NanUInt32OptionValue to convert any Number object + +**0.1.0 Jul 21 2013** + + - Added `NAN_GETTER`, `NAN_SETTER` + - Added `NanThrowError` with single Local argument + - Added `NanNewBufferHandle` with single uint32_t argument + - Added `NanHasInstance(Persistent&, Handle)` + - Added `Local NanCallback#GetFunction()` + - Added `NanCallback#Call(int, Local[])` + - Deprecated `NanCallback#Run(int, Local[])` in favour of Call diff --git a/node_modules/mongodb/node_modules/kerberos/node_modules/nan/LICENSE b/node_modules/mongodb/node_modules/kerberos/node_modules/nan/LICENSE new file mode 100644 index 0000000..d502e18 --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/node_modules/nan/LICENSE @@ -0,0 +1,46 @@ +Copyright 2013, NAN contributors: + - Rod Vagg + - Benjamin Byholm + - Trevor Norris + - Nathan Rajlich + - Brett Lawson + - Ben Noordhuis +(the "Original Author") +All rights reserved. + +MIT +no-false-attribs 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. + +Distributions of all or part of the Software intended to be used +by the recipients as they would use the unmodified Software, +containing modifications that substantially alter, remove, or +disable functionality of the Software, outside of the documented +configuration mechanisms provided by the Software, shall be +modified such that the Original Author's bug reporting email +addresses and urls are either replaced with the contact information +of the parties responsible for the changes, or removed entirely. + +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. + + +Except where noted, this license applies to any and all software +programs and associated documentation files created by the +Original Author, when distributed with the Software. diff --git a/node_modules/mongodb/node_modules/kerberos/node_modules/nan/README.md b/node_modules/mongodb/node_modules/kerberos/node_modules/nan/README.md new file mode 100644 index 0000000..2904a38 --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/node_modules/nan/README.md @@ -0,0 +1,1054 @@ +Native Abstractions for Node.js +=============================== + +**A header file filled with macro and utility goodness for making add-on development for Node.js easier across versions 0.8, 0.10 and 0.11, and eventually 0.12.** + +***Current version: 1.3.0*** + +*(See [nan.h](https://github.com/rvagg/nan/blob/master/CHANGELOG.md) for complete ChangeLog)* + +[![NPM](https://nodei.co/npm/nan.png?downloads=true)](https://nodei.co/npm/nan/) [![NPM](https://nodei.co/npm-dl/nan.png?months=6)](https://nodei.co/npm/nan/) + +[![Build Status](https://secure.travis-ci.org/rvagg/nan.png)](http://travis-ci.org/rvagg/nan) +[![Build status](https://ci.appveyor.com/api/projects/status/kh73pbm9dsju7fgh)](https://ci.appveyor.com/project/RodVagg/nan) + +Thanks to the crazy changes in V8 (and some in Node core), keeping native addons compiling happily across versions, particularly 0.10 to 0.11/0.12, is a minor nightmare. The goal of this project is to store all logic necessary to develop native Node.js addons without having to inspect `NODE_MODULE_VERSION` and get yourself into a macro-tangle. + +This project also contains some helper utilities that make addon development a bit more pleasant. + + * **[News & Updates](#news)** + * **[Usage](#usage)** + * **[Example](#example)** + * **[API](#api)** + + +## News & Updates + +### Aug-2014: 1.3.0 release + +* `NanCString()` and `NanRawString()` have been deprecated in favour of new NanAsciiString, NanUtf8String and NanUcs2String. These classes manage the underlying memory for you in a safer way than just handing off an allocated array. You should now `*NanAsciiString(handle)` to access the raw `char` data, you can also allocate on the heap if you need to keep a reference. +* Two more NanMakeCallback overloads have been added to for parity with Node core. +* You can now `NanNew(std::string)` (use `NanNew(std::string&)` to pass by reference) +* NanSetTemplate, NanSetPrototypeTemplate and NanSetInstanceTemplate have been added. + +### May-2014: 1.1.0 release + +* We've deprecated `NanSymbol()`, you should just use `NanNew()` now. +* `NanNull()`, `NanUndefined()`, `NanTrue()`, `NanFalse()` all return `Local`s now. +* `nan_isolate` is gone, it was intended to be internal-only but if you were using it then you should switch to `v8::Isolate::GetCurrent()`. +* `NanNew()` has received some additional overload-love so you should be able to give it many kinds of values without specifying the ``. +* Lots of small fixes and additions to expand the V8 API coverage, *use the source, Luke*. + + +### May-2014: Major changes for V8 3.25 / Node 0.11.13 + +Node 0.11.11 and 0.11.12 were both broken releases for native add-ons, you simply can't properly compile against either of them for different reasons. But we now have a 0.11.13 release that jumps a couple of versions of V8 ahead and includes some more, major (traumatic) API changes. + +Because we are now nearing Node 0.12 and estimate that the version of V8 we are using in Node 0.11.13 will be close to the API we get for 0.12, we have taken the opportunity to not only *fix* NAN for 0.11.13 but make some major changes to improve the NAN API. + +We have **removed support for Node 0.11 versions prior to 0.11.13**. As usual, our tests are run against (and pass) the last 5 versions of Node 0.8 and Node 0.10. We also include Node 0.11.13 obviously. + +The major change is something that [Benjamin Byholm](kkoopa) has put many hours in to. We now have a fantastic new `NanNew(args)` interface for creating new `Local`s, this replaces `NanNewLocal()` and much more. If you look in [./nan.h](nan.h) you'll see a large number of overloaded versions of this method. In general you should be able to `NanNew(arguments)` for any type you want to make a `Local` from. This includes `Persistent` types, so we now have a `Local NanNew(const Persistent arg)` to replace `NanPersistentToLocal()`. + +We also now have `NanUndefined()`, `NanNull()`, `NanTrue()` and `NanFalse()`. Mainly because of the new requirement for an `Isolate` argument for each of the native V8 versions of this. + +V8 has now introduced an `EscapableHandleScope` from which you `scope.Escape(Local value)` to *return* a value from a one scope to another. This replaces the standard `HandleScope` and `scope.Close(Local value)`, although `HandleScope` still exists for when you don't need to return a handle to the caller. For NAN we are exposing it as `NanEscapableScope()` and `NanEscapeScope()`, while `NanScope()` is still how you create a new scope that doesn't need to return handles. For older versions of Node/V8, it'll still map to the older `HandleScope` functionality. + +`NanFromV8String()` was deprecated and has now been removed. You should use `NanCString()` or `NanRawString()` instead. + +Because `node::MakeCallback()` now takes an `Isolate`, and because it doesn't exist in older versions of Node, we've introduced `NanMakeCallback()`. You should *always* use this when calling a JavaScript function from C++. + +There's lots more, check out the Changelog in nan.h or look through [#86](https://github.com/rvagg/nan/pull/86) for all the gory details. + +### Dec-2013: NanCString and NanRawString + +Two new functions have been introduced to replace the functionality that's been provided by `NanFromV8String` until now. NanCString has sensible defaults so it's super easy to fetch a null-terminated c-style string out of a `v8::String`. `NanFromV8String` is still around and has defaults that allow you to pass a single handle to fetch a `char*` while `NanRawString` requires a little more attention to arguments. + +### Nov-2013: Node 0.11.9+ breaking V8 change + +The version of V8 that's shipping with Node 0.11.9+ has changed the signature for new `Local`s to: `v8::Local::New(isolate, value)`, i.e. introducing the `isolate` argument and therefore breaking all new `Local` declarations for previous versions. NAN 0.6+ now includes a `NanNewLocal(value)` that can be used in place to work around this incompatibility and maintain compatibility with 0.8->0.11.9+ (minus a few early 0.11 releases). + +For example, if you wanted to return a `null` on a callback you will have to change the argument from `v8::Local::New(v8::Null())` to `NanNewLocal(v8::Null())`. + +### Nov-2013: Change to binding.gyp `"include_dirs"` for NAN + +Inclusion of NAN in a project's binding.gyp is now greatly simplified. You can now just use `" +## Usage + +Simply add **NAN** as a dependency in the *package.json* of your Node addon: + +``` bash +$ npm install --save nan +``` + +Pull in the path to **NAN** in your *binding.gyp* so that you can use `#include ` in your *.cpp* files: + +``` python +"include_dirs" : [ + "` when compiling your addon. + + +## Example + +See **[LevelDOWN](https://github.com/rvagg/node-leveldown/pull/48)** for a full example of **NAN** in use. + +For a simpler example, see the **[async pi estimation example](https://github.com/rvagg/nan/tree/master/examples/async_pi_estimate)** in the examples directory for full code and an explanation of what this Monte Carlo Pi estimation example does. Below are just some parts of the full example that illustrate the use of **NAN**. + +Compare to the current 0.10 version of this example, found in the [node-addon-examples](https://github.com/rvagg/node-addon-examples/tree/master/9_async_work) repository and also a 0.11 version of the same found [here](https://github.com/kkoopa/node-addon-examples/tree/5c01f58fc993377a567812597e54a83af69686d7/9_async_work). + +Note that there is no embedded version sniffing going on here and also the async work is made much simpler, see below for details on the `NanAsyncWorker` class. + +```c++ +// addon.cc +#include +#include +// ... + +using v8::FunctionTemplate; +using v8::Handle; +using v8::Object; +using v8::String; + +void InitAll(Handle exports) { + exports->Set(NanNew("calculateSync"), + NanNew(CalculateSync)->GetFunction()); + + exports->Set(NanNew("calculateAsync"), + NanNew(CalculateAsync)->GetFunction()); +} + +NODE_MODULE(addon, InitAll) +``` + +```c++ +// sync.h +#include +#include + +NAN_METHOD(CalculateSync); +``` + +```c++ +// sync.cc +#include +#include +#include "./sync.h" +// ... + +using v8::Number; + +// Simple synchronous access to the `Estimate()` function +NAN_METHOD(CalculateSync) { + NanScope(); + + // expect a number as the first argument + int points = args[0]->Uint32Value(); + double est = Estimate(points); + + NanReturnValue(NanNew(est)); +} +``` + +```c++ +// async.h +#include +#include + +NAN_METHOD(CalculateAsync); +``` + +```c++ +// async.cc +#include +#include +#include "./async.h" + +// ... + +using v8::Function; +using v8::Local; +using v8::Null; +using v8::Number; +using v8::Value; + +class PiWorker : public NanAsyncWorker { + public: + PiWorker(NanCallback *callback, int points) + : NanAsyncWorker(callback), points(points) {} + ~PiWorker() {} + + // Executed inside the worker-thread. + // It is not safe to access V8, or V8 data structures + // here, so everything we need for input and output + // should go on `this`. + void Execute () { + estimate = Estimate(points); + } + + // Executed when the async work is complete + // this function will be run inside the main event loop + // so it is safe to use V8 again + void HandleOKCallback () { + NanScope(); + + Local argv[] = { + NanNull() + , NanNew(estimate) + }; + + callback->Call(2, argv); + }; + + private: + int points; + double estimate; +}; + +// Asynchronous access to the `Estimate()` function +NAN_METHOD(CalculateAsync) { + NanScope(); + + int points = args[0]->Uint32Value(); + NanCallback *callback = new NanCallback(args[1].As()); + + NanAsyncQueueWorker(new PiWorker(callback, points)); + NanReturnUndefined(); +} +``` + + +## API + + * NAN_METHOD + * NAN_GETTER + * NAN_SETTER + * NAN_PROPERTY_GETTER + * NAN_PROPERTY_SETTER + * NAN_PROPERTY_ENUMERATOR + * NAN_PROPERTY_DELETER + * NAN_PROPERTY_QUERY + * NAN_INDEX_GETTER + * NAN_INDEX_SETTER + * NAN_INDEX_ENUMERATOR + * NAN_INDEX_DELETER + * NAN_INDEX_QUERY + * NAN_WEAK_CALLBACK + * NAN_DEPRECATED + * NAN_INLINE + * NanNew + * NanUndefined + * NanNull + * NanTrue + * NanFalse + * NanReturnValue + * NanReturnUndefined + * NanReturnNull + * NanReturnEmptyString + * NanScope + * NanEscapableScope + * NanEscapeScope + * NanLocker + * NanUnlocker + * NanGetInternalFieldPointer + * NanSetInternalFieldPointer + * NanObjectWrapHandle + * NanSymbol + * NanGetPointerSafe + * NanSetPointerSafe + * NanRawString + * NanCString + * NanAsciiString + * NanUtf8String + * NanUcs2String + * NanBooleanOptionValue + * NanUInt32OptionValue + * NanError, NanTypeError, NanRangeError + * NanThrowError, NanThrowTypeError, NanThrowRangeError, NanThrowError(Handle), NanThrowError(Handle, int) + * NanNewBufferHandle(char *, size_t, FreeCallback, void *), NanNewBufferHandle(char *, uint32_t), NanNewBufferHandle(uint32_t) + * NanBufferUse(char *, uint32_t) + * NanNewContextHandle + * NanGetCurrentContext + * NanHasInstance + * NanDisposePersistent + * NanAssignPersistent + * NanMakeWeakPersistent + * NanSetTemplate + * NanSetPrototypeTemplate + * NanSetInstanceTemplate + * NanMakeCallback + * NanCompileScript + * NanRunScript + * NanAdjustExternalMemory + * NanAddGCEpilogueCallback + * NanAddGCPrologueCallback + * NanRemoveGCEpilogueCallback + * NanRemoveGCPrologueCallback + * NanGetHeapStatistics + * NanCallback + * NanAsyncWorker + * NanAsyncQueueWorker + + +### NAN_METHOD(methodname) + +Use `NAN_METHOD` to define your V8 accessible methods: + +```c++ +// .h: +class Foo : public node::ObjectWrap { + ... + + static NAN_METHOD(Bar); + static NAN_METHOD(Baz); +} + + +// .cc: +NAN_METHOD(Foo::Bar) { + ... +} + +NAN_METHOD(Foo::Baz) { + ... +} +``` + +The reason for this macro is because of the method signature change in 0.11: + +```c++ +// 0.10 and below: +Handle name(const Arguments& args) + +// 0.11 and above +void name(const FunctionCallbackInfo& args) +``` + +The introduction of `FunctionCallbackInfo` brings additional complications: + + +### NAN_GETTER(methodname) + +Use `NAN_GETTER` to declare your V8 accessible getters. You get a `Local` `property` and an appropriately typed `args` object that can act like the `args` argument to a `NAN_METHOD` call. + +You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_GETTER`. + + +### NAN_SETTER(methodname) + +Use `NAN_SETTER` to declare your V8 accessible setters. Same as `NAN_GETTER` but you also get a `Local` `value` object to work with. + + +### NAN_PROPERTY_GETTER(cbname) +Use `NAN_PROPERTY_GETTER` to declare your V8 accessible property getters. You get a `Local` `property` and an appropriately typed `args` object that can act similar to the `args` argument to a `NAN_METHOD` call. + +You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_PROPERTY_GETTER`. + + +### NAN_PROPERTY_SETTER(cbname) +Use `NAN_PROPERTY_SETTER` to declare your V8 accessible property setters. Same as `NAN_PROPERTY_GETTER` but you also get a `Local` `value` object to work with. + + +### NAN_PROPERTY_ENUMERATOR(cbname) +Use `NAN_PROPERTY_ENUMERATOR` to declare your V8 accessible property enumerators. You get an appropriately typed `args` object like the `args` argument to a `NAN_PROPERTY_GETTER` call. + +You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_PROPERTY_ENUMERATOR`. + + +### NAN_PROPERTY_DELETER(cbname) +Use `NAN_PROPERTY_DELETER` to declare your V8 accessible property deleters. Same as `NAN_PROPERTY_GETTER`. + +You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_PROPERTY_DELETER`. + + +### NAN_PROPERTY_QUERY(cbname) +Use `NAN_PROPERTY_QUERY` to declare your V8 accessible property queries. Same as `NAN_PROPERTY_GETTER`. + +You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_PROPERTY_QUERY`. + + +### NAN_INDEX_GETTER(cbname) +Use `NAN_INDEX_GETTER` to declare your V8 accessible index getters. You get a `uint32_t` `index` and an appropriately typed `args` object that can act similar to the `args` argument to a `NAN_METHOD` call. + +You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_INDEX_GETTER`. + + +### NAN_INDEX_SETTER(cbname) +Use `NAN_INDEX_SETTER` to declare your V8 accessible index setters. Same as `NAN_INDEX_GETTER` but you also get a `Local` `value` object to work with. + + +### NAN_INDEX_ENUMERATOR(cbname) +Use `NAN_INDEX_ENUMERATOR` to declare your V8 accessible index enumerators. You get an appropriately typed `args` object like the `args` argument to a `NAN_INDEX_GETTER` call. + +You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_INDEX_ENUMERATOR`. + + +### NAN_INDEX_DELETER(cbname) +Use `NAN_INDEX_DELETER` to declare your V8 accessible index deleters. Same as `NAN_INDEX_GETTER`. + +You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_INDEX_DELETER`. + + +### NAN_INDEX_QUERY(cbname) +Use `NAN_INDEX_QUERY` to declare your V8 accessible index queries. Same as `NAN_INDEX_GETTER`. + +You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_INDEX_QUERY`. + + +### NAN_WEAK_CALLBACK(cbname) + +Use `NAN_WEAK_CALLBACK` to define your V8 WeakReference callbacks. There is an argument object `const _NanWeakCallbackData &data` allowing access to the weak object and the supplied parameter through its `GetValue` and `GetParameter` methods. You can even access the weak callback info object through the `GetCallbackInfo()`method, but you probably should not. `Revive()` keeps the weak object alive until the next GC round. + +```c++ +NAN_WEAK_CALLBACK(weakCallback) { + int *parameter = data.GetParameter(); + NanMakeCallback(NanGetCurrentContext()->Global(), data.GetValue(), 0, NULL); + if ((*parameter)++ == 0) { + data.Revive(); + } else { + delete parameter; + } +} +``` + + +### NAN_DEPRECATED +Declares a function as deprecated. + +```c++ +static NAN_DEPRECATED NAN_METHOD(foo) { + ... +} +``` + + +### NAN_INLINE +Inlines a function. + +```c++ +NAN_INLINE int foo(int bar) { + ... +} +``` + + +### Local<T> NanNew<T>( ... ) + +Use `NanNew` to construct almost all v8 objects and make new local handles. + +Note: Using NanNew with an std::string is possible, however, you should ensure +to use the overload version (`NanNew(stdString)`) rather than the template +version (`NanNew(stdString)`) as there is an unnecessary +performance penalty to using the template version because of the inability for +compilers to appropriately deduce to reference types on template specialization. + +```c++ +Local s = NanNew("value"); + +... + +Persistent o; + +... + +Local lo = NanNew(o); + +``` + + +### Local<Primitive> NanUndefined() + +Use instead of `Undefined()` + + +### Local<Primitive> NanNull() + +Use instead of `Null()` + + +### Local<Boolean> NanTrue() + +Use instead of `True()` + + +### Local<Boolean> NanFalse() + +Use instead of `False()` + + +### NanReturnValue(Handle<Value>) + +Use `NanReturnValue` when you want to return a value from your V8 accessible method: + +```c++ +NAN_METHOD(Foo::Bar) { + ... + + NanReturnValue(NanNew("FooBar!")); +} +``` + +No `return` statement required. + + +### NanReturnUndefined() + +Use `NanReturnUndefined` when you don't want to return anything from your V8 accessible method: + +```c++ +NAN_METHOD(Foo::Baz) { + ... + + NanReturnUndefined(); +} +``` + + +### NanReturnNull() + +Use `NanReturnNull` when you want to return `Null` from your V8 accessible method: + +```c++ +NAN_METHOD(Foo::Baz) { + ... + + NanReturnNull(); +} +``` + + +### NanReturnEmptyString() + +Use `NanReturnEmptyString` when you want to return an empty `String` from your V8 accessible method: + +```c++ +NAN_METHOD(Foo::Baz) { + ... + + NanReturnEmptyString(); +} +``` + + +### NanScope() + +The introduction of `isolate` references for many V8 calls in Node 0.11 makes `NanScope()` necessary, use it in place of `HandleScope scope` when you do not wish to return handles (`Handle` or `Local`) to the surrounding scope (or in functions directly exposed to V8, as they do not return values in the normal sense): + +```c++ +NAN_METHOD(Foo::Bar) { + NanScope(); + + NanReturnValue(NanNew("FooBar!")); +} +``` + +This method is not directly exposed to V8, nor does it return a handle, so it uses an unescapable scope: + +```c++ +bool Foo::Bar() { + NanScope(); + + Local val = NanFalse(); + ... + return val->Value(); +} +``` + + +### NanEscapableScope() + +The separation of handle scopes into escapable and inescapable scopes makes `NanEscapableScope()` necessary, use it in place of `HandleScope scope` when you later wish to return a handle (`Handle` or `Local`) from the scope, this is for internal functions not directly exposed to V8: + +```c++ +Handle Foo::Bar() { + NanEscapableScope(); + + return NanEscapeScope(NanNew("FooBar!")); +} +``` + + +### Local<T> NanEscapeScope(Handle<T> value); +Use together with `NanEscapableScope` to escape the scope. Corresponds to `HandleScope::Close` or `EscapableHandleScope::Escape`. + + +### NanLocker() + +The introduction of `isolate` references for many V8 calls in Node 0.11 makes `NanLocker()` necessary, use it in place of `Locker locker`: + +```c++ +NAN_METHOD(Foo::Bar) { + NanLocker(); + ... + NanUnlocker(); +} +``` + + +### NanUnlocker() + +The introduction of `isolate` references for many V8 calls in Node 0.11 makes `NanUnlocker()` necessary, use it in place of `Unlocker unlocker`: + +```c++ +NAN_METHOD(Foo::Bar) { + NanLocker(); + ... + NanUnlocker(); +} +``` + + +### void * NanGetInternalFieldPointer(Handle<Object>, int) + +Gets a pointer to the internal field with at `index` from a V8 `Object` handle. + +```c++ +Local obj; +... +NanGetInternalFieldPointer(obj, 0); +``` + +### void NanSetInternalFieldPointer(Handle<Object>, int, void *) + +Sets the value of the internal field at `index` on a V8 `Object` handle. + +```c++ +static Persistent dataWrapperCtor; +... +Local wrapper = NanNew(dataWrapperCtor)->NewInstance(); +NanSetInternalFieldPointer(wrapper, 0, this); +``` + + +### Local<Object> NanObjectWrapHandle(Object) + +When you want to fetch the V8 object handle from a native object you've wrapped with Node's `ObjectWrap`, you should use `NanObjectWrapHandle`: + +```c++ +NanObjectWrapHandle(iterator)->Get(NanNew("end")) +``` + + +### Local<String> NanSymbol(const char *) + +Deprecated. Use `NanNew` instead. +Use to create string symbol objects (i.e. `v8::String::NewSymbol(x)`), for getting and setting object properties, or names of objects. + +```c++ +bool foo = false; +if (obj->Has(NanNew("foo"))) + foo = optionsObj->Get(NanNew("foo"))->BooleanValue() +``` + + +### Type NanGetPointerSafe(Type *[, Type]) + +A helper for getting values from optional pointers. If the pointer is `NULL`, the function returns the optional default value, which defaults to `0`. Otherwise, the function returns the value the pointer points to. + +```c++ +char *plugh(uint32_t *optional) { + char res[] = "xyzzy"; + uint32_t param = NanGetPointerSafe(optional, 0x1337); + switch (param) { + ... + } + NanSetPointerSafe(optional, 0xDEADBEEF); +} +``` + + +### bool NanSetPointerSafe(Type *, Type) + +A helper for setting optional argument pointers. If the pointer is `NULL`, the function simply returns `false`. Otherwise, the value is assigned to the variable the pointer points to. + +```c++ +const char *plugh(size_t *outputsize) { + char res[] = "xyzzy"; + if !(NanSetPointerSafe(outputsize, strlen(res) + 1)) { + ... + } + + ... +} +``` + + +### void* NanRawString(Handle<Value>, enum Nan::Encoding, size_t *, void *, size_t, int) + +Deprecated. Use something else. + +When you want to convert a V8 `String` to a `char*` buffer, use `NanRawString`. You have to supply an encoding as well as a pointer to a variable that will be assigned the number of bytes in the returned string. It is also possible to supply a buffer and its length to the function in order not to have a new buffer allocated. The final argument allows setting `String::WriteOptions`. +Just remember that you'll end up with an object that you'll need to `delete[]` at some point unless you supply your own buffer: + +```c++ +size_t count; +void* decoded = NanRawString(args[1], Nan::BASE64, &count, NULL, 0, String::HINT_MANY_WRITES_EXPECTED); +... +delete[] reinterpret_cast(decoded); +``` + + +### char* NanCString(Handle<Value>, size_t *[, char *, size_t, int]) + +Deprecated. Use `NanUtf8String` instead. + +When you want to convert a V8 `String` to a null-terminated C `char*` use `NanCString`. The resulting `char*` will be UTF-8-encoded, and you need to supply a pointer to a variable that will be assigned the number of bytes in the returned string. It is also possible to supply a buffer and its length to the function in order not to have a new buffer allocated. The final argument allows optionally setting `String::WriteOptions`, which default to `v8::String::NO_OPTIONS`. +Just remember that you'll end up with an object that you'll need to `delete[]` at some point unless you supply your own buffer: + +```c++ +size_t count; +char* name = NanCString(args[0], &count); +... +delete[] name; +``` + + +### NanAsciiString + +Convert a `String` to zero-terminated, Ascii-encoded `char *`. + +```c++ +NAN_METHOD(foo) { + NanScope(); + NanReturnValue(NanNew(*NanAsciiString(arg[0]))); +} +``` + + +### NanUtf8String + +Convert a `String` to zero-terminated, Utf8-encoded `char *`. + +```c++ +NAN_METHOD(foo) { + NanScope(); + NanReturnValue(NanNew(*NanUtf8String(arg[0]))); +} +``` + + +### NanUcs2String + +Convert a `String` to zero-terminated, Ucs2-encoded `uint16_t *`. + +```c++ +NAN_METHOD(foo) { + NanScope(); + NanReturnValue(NanNew(*NanUcs2String(arg[0]))); +} +``` + + +### bool NanBooleanOptionValue(Handle<Value>, Handle<String>[, bool]) + +When you have an "options" object that you need to fetch properties from, boolean options can be fetched with this pair. They check first if the object exists (`IsEmpty`), then if the object has the given property (`Has`) then they get and convert/coerce the property to a `bool`. + +The optional last parameter is the *default* value, which is `false` if left off: + +```c++ +// `foo` is false unless the user supplies a truthy value for it +bool foo = NanBooleanOptionValue(optionsObj, NanNew("foo")); +// `bar` is true unless the user supplies a falsy value for it +bool bar = NanBooleanOptionValueDefTrue(optionsObj, NanNew("bar"), true); +``` + + +### uint32_t NanUInt32OptionValue(Handle<Value>, Handle<String>, uint32_t) + +Similar to `NanBooleanOptionValue`, use `NanUInt32OptionValue` to fetch an integer option from your options object. Can be any kind of JavaScript `Number` and it will be coerced to an unsigned 32-bit integer. + +Requires all 3 arguments as a default is not optional: + +```c++ +uint32_t count = NanUInt32OptionValue(optionsObj, NanNew("count"), 1024); +``` + + +### NanError(message), NanTypeError(message), NanRangeError(message) + +For making `Error`, `TypeError` and `RangeError` objects. + +```c++ +Local res = NanError("you must supply a callback argument"); +``` + + +### NanThrowError(message), NanThrowTypeError(message), NanThrowRangeError(message), NanThrowError(Local<Value>), NanThrowError(Local<Value>, int) + +For throwing `Error`, `TypeError` and `RangeError` objects. + +```c++ +NanThrowError("you must supply a callback argument"); +``` + +Can also handle any custom object you may want to throw. If used with the error code argument, it will add the supplied error code to the error object as a property called `code`. + + +### Local<Object> NanNewBufferHandle(char *, uint32_t), Local<Object> NanNewBufferHandle(uint32_t) + +The `Buffer` API has changed a little in Node 0.11, this helper provides consistent access to `Buffer` creation: + +```c++ +NanNewBufferHandle((char*)value.data(), value.size()); +``` + +Can also be used to initialize a `Buffer` with just a `size` argument. + +Can also be supplied with a `NanFreeCallback` and a hint for the garbage collector. + + +### Local<Object> NanBufferUse(char*, uint32_t) + +`Buffer::New(char*, uint32_t)` prior to 0.11 would make a copy of the data. +While it was possible to get around this, it required a shim by passing a +callback. So the new API `Buffer::Use(char*, uint32_t)` was introduced to remove +needing to use this shim. + +`NanBufferUse` uses the `char*` passed as the backing data, and will free the +memory automatically when the weak callback is called. Keep this in mind, as +careless use can lead to "double free or corruption" and other cryptic failures. + + +### bool NanHasInstance(Persistent<FunctionTemplate>&, Handle<Value>) + +Can be used to check the type of an object to determine it is of a particular class you have already defined and have a `Persistent` handle for. + + +### Local<Context> NanNewContextHandle([ExtensionConfiguration*, Handle<ObjectTemplate>, Handle<Value>]) +Creates a new `Local` handle. + +```c++ +Local ftmpl = NanNew(); +Local otmpl = ftmpl->InstanceTemplate(); +Local ctx = NanNewContextHandle(NULL, otmpl); +``` + + +### Local<Context> NanGetCurrentContext() + +Gets the current context. + +```c++ +Local ctx = NanGetCurrentContext(); +``` + + +### void NanDisposePersistent(Persistent<T> &) + +Use `NanDisposePersistent` to dispose a `Persistent` handle. + +```c++ +NanDisposePersistent(persistentHandle); +``` + + +### NanAssignPersistent(handle, object) + +Use `NanAssignPersistent` to assign a non-`Persistent` handle to a `Persistent` one. You can no longer just declare a `Persistent` handle and assign directly to it later, you have to `Reset` it in Node 0.11, so this makes it easier. + +In general it is now better to place anything you want to protect from V8's garbage collector as properties of a generic `Object` and then assign that to a `Persistent`. This works in older versions of Node also if you use `NanAssignPersistent`: + +```c++ +Persistent persistentHandle; + +... + +Local obj = NanNew(); +obj->Set(NanNew("key"), keyHandle); // where keyHandle might be a Local +NanAssignPersistent(persistentHandle, obj) +``` + + +### _NanWeakCallbackInfo<T, P>* NanMakeWeakPersistent(Handle<T>, P*, _NanWeakCallbackInfo<T, P>::Callback) + +Creates a weak persistent handle with the supplied parameter and `NAN_WEAK_CALLBACK`. + +```c++ +NAN_WEAK_CALLBACK(weakCallback) { + +... + +} + +Local func; + +... + +int *parameter = new int(0); +NanMakeWeakPersistent(func, parameter, &weakCallback); +``` + + +### NanSetTemplate(templ, name, value [, attributes]) + +Use to add properties on object and function templates. + + +### NanSetPrototypeTemplate(templ, name, value [, attributes]) + +Use to add prototype properties on function templates. + + +### NanSetInstanceTemplate(templ, name, value [, attributes]) + +Use to add instance properties on function templates. + + +### NanMakeCallback(target, func, argc, argv) + +Use instead of `node::MakeCallback` to call javascript functions. This is the only proper way of calling functions. + + +### NanCompileScript(Handle s [, const ScriptOrigin& origin]) + +Use to create new scripts bound to the current context. + + +### NanRunScript(script) + +Use to run both bound and unbound scripts. + + +### NanAdjustExternalMemory(int change_in_bytes) + +Simply does `AdjustAmountOfExternalAllocatedMemory`, note that the argument and returned value have type `int`. + + +### NanAddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type_filter=kGCTypeAll) + +Simply does `AddGCEpilogueCallback` + + +### NanAddGCPrologueCallback(GCPrologueCallback callback, GCType gc_type_filter=kGCTypeAll) + +Simply does `AddGCPrologueCallback` + + +### NanRemoveGCEpilogueCallback(GCEpilogueCallback callback) + +Simply does `RemoveGCEpilogueCallback` + + +### NanRemoveGCPrologueCallback(GCPrologueCallback callback) + +Simply does `RemoveGCPrologueCallback` + + +### NanGetHeapStatistics(HeapStatistics *heap_statistics) + +Simply does `GetHeapStatistics` + + +### NanCallback + +Because of the difficulties imposed by the changes to `Persistent` handles in V8 in Node 0.11, creating `Persistent` versions of your `Handle` is annoyingly tricky. `NanCallback` makes it easier by taking your handle, making it persistent until the `NanCallback` is deleted and even providing a handy `Call()` method to fetch and execute the callback `Function`. + +```c++ +Local callbackHandle = args[0].As(); +NanCallback *callback = new NanCallback(callbackHandle); +// pass `callback` around and it's safe from GC until you: +delete callback; +``` + +You can execute the callback like so: + +```c++ +// no arguments: +callback->Call(0, NULL); + +// an error argument: +Handle argv[] = { + NanError(NanNew("fail!")) +}; +callback->Call(1, argv); + +// a success argument: +Handle argv[] = { + NanNull(), + NanNew("w00t!") +}; +callback->Call(2, argv); +``` + +`NanCallback` also has a `Local GetCallback()` method that you can use +to fetch a local handle to the underlying callback function, as well as a +`void SetFunction(Handle)` for setting the callback on the +`NanCallback`. You can check if a `NanCallback` is empty with the `bool IsEmpty()` method. Additionally a generic constructor is available for using +`NanCallback` without performing heap allocations. + + +### NanAsyncWorker + +`NanAsyncWorker` is an abstract class that you can subclass to have much of the annoying async queuing and handling taken care of for you. It can even store arbitrary V8 objects for you and have them persist while the async work is in progress. + +See a rough outline of the implementation: + +```c++ +class NanAsyncWorker { +public: + NanAsyncWorker (NanCallback *callback); + + // Clean up persistent handles and delete the *callback + virtual ~NanAsyncWorker (); + + // Check the `ErrorMessage()` and call HandleOKCallback() + // or HandleErrorCallback depending on whether it has been set or not + virtual void WorkComplete (); + + // You must implement this to do some async work. If there is an + // error then use `SetErrorMessage()` to set an error message and the callback will + // be passed that string in an Error object + virtual void Execute (); + + // Save a V8 object in a Persistent handle to protect it from GC + void SaveToPersistent(const char *key, Local &obj); + + // Fetch a stored V8 object (don't call from within `Execute()`) + Local GetFromPersistent(const char *key); + + // Get the error message (or NULL) + const char *ErrorMessage(); + + // Set an error message + void SetErrorMessage(const char *msg); + +protected: + // Default implementation calls the callback function with no arguments. + // Override this to return meaningful data + virtual void HandleOKCallback (); + + // Default implementation calls the callback function with an Error object + // wrapping the `errmsg` string + virtual void HandleErrorCallback (); +}; +``` + + +### NanAsyncQueueWorker(NanAsyncWorker *) + +`NanAsyncQueueWorker` will run a `NanAsyncWorker` asynchronously via libuv. Both the *execute* and *after_work* steps are taken care of for you—most of the logic for this is embedded in `NanAsyncWorker`. + +### Contributors + +NAN is only possible due to the excellent work of the following contributors: + + + + + + + + +
Rod VaggGitHub/rvaggTwitter/@rvagg
Benjamin ByholmGitHub/kkoopa-
Trevor NorrisGitHub/trevnorrisTwitter/@trevnorris
Nathan RajlichGitHub/TooTallNateTwitter/@TooTallNate
Brett LawsonGitHub/brett19Twitter/@brett19x
Ben NoordhuisGitHub/bnoordhuisTwitter/@bnoordhuis
+ +Licence & copyright +----------------------- + +Copyright (c) 2014 NAN contributors (listed above). + +Native Abstractions for Node.js is licensed under an MIT +no-false-attribs license. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE file for more details. diff --git a/node_modules/mongodb/node_modules/kerberos/node_modules/nan/appveyor.yml b/node_modules/mongodb/node_modules/kerberos/node_modules/nan/appveyor.yml new file mode 100644 index 0000000..657eed6 --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/node_modules/nan/appveyor.yml @@ -0,0 +1,32 @@ +# http://www.appveyor.com/docs/appveyor-yml + +# Test against these versions of Node.js. +environment: + matrix: + - nodejs_version: "0.8" + - nodejs_version: "0.10" + - nodejs_version: "0.11" + +# Install scripts. (runs after repo cloning) +install: + # Get the latest stable version of Node 0.STABLE.latest + - npm install npm + - move node_modules npm + - ps: Update-NodeJsInstallation (Get-NodeJsLatestBuild $env:nodejs_version) + # Typical npm stuff. + - npm/.bin/npm install + - npm/.bin/npm run rebuild-tests + +# Post-install test scripts. +test_script: + # Output useful info for debugging. + - node --version + - npm --version + - cmd: npm test + +# Don't actually build. +build: off + +# Set build version format here instead of in the admin panel. +version: "{build}" + diff --git a/node_modules/mongodb/node_modules/kerberos/node_modules/nan/include_dirs.js b/node_modules/mongodb/node_modules/kerberos/node_modules/nan/include_dirs.js new file mode 100644 index 0000000..4f1dfb4 --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/node_modules/nan/include_dirs.js @@ -0,0 +1 @@ +console.log(require('path').relative('.', __dirname)); diff --git a/node_modules/mongodb/node_modules/kerberos/node_modules/nan/nan.h b/node_modules/mongodb/node_modules/kerberos/node_modules/nan/nan.h new file mode 100644 index 0000000..063de4e --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/node_modules/nan/nan.h @@ -0,0 +1,2331 @@ +/********************************************************************************** + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2014 NAN contributors: + * - Rod Vagg + * - Benjamin Byholm + * - Trevor Norris + * - Nathan Rajlich + * - Brett Lawson + * - Ben Noordhuis + * + * MIT +no-false-attribs License + * + * Version 1.3.0: current Node unstable: 0.11.13, Node stable: 0.10.30 + * + * See https://github.com/rvagg/nan for the latest update to this file + **********************************************************************************/ + +#ifndef NAN_H_ +#define NAN_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(__GNUC__) && !defined(DEBUG) +# define NAN_INLINE inline __attribute__((always_inline)) +#elif defined(_MSC_VER) && !defined(DEBUG) +# define NAN_INLINE __forceinline +#else +# define NAN_INLINE inline +#endif + +#if defined(__GNUC__) && !V8_DISABLE_DEPRECATIONS +# define NAN_DEPRECATED __attribute__((deprecated)) +#elif defined(_MSC_VER) && !V8_DISABLE_DEPRECATIONS +# define NAN_DEPRECATED __declspec(deprecated) +#else +# define NAN_DEPRECATED +#endif + +// some generic helpers + +template NAN_INLINE bool NanSetPointerSafe( + T *var + , T val +) { + if (var) { + *var = val; + return true; + } else { + return false; + } +} + +template NAN_INLINE T NanGetPointerSafe( + T *var + , T fallback = reinterpret_cast(0) +) { + if (var) { + return *var; + } else { + return fallback; + } +} + +NAN_INLINE bool NanBooleanOptionValue( + v8::Local optionsObj + , v8::Handle opt, bool def +) { + if (def) { + return optionsObj.IsEmpty() + || !optionsObj->Has(opt) + || optionsObj->Get(opt)->BooleanValue(); + } else { + return !optionsObj.IsEmpty() + && optionsObj->Has(opt) + && optionsObj->Get(opt)->BooleanValue(); + } +} + +NAN_INLINE bool NanBooleanOptionValue( + v8::Local optionsObj + , v8::Handle opt +) { + return NanBooleanOptionValue(optionsObj, opt, false); +} + +NAN_INLINE uint32_t NanUInt32OptionValue( + v8::Local optionsObj + , v8::Handle opt + , uint32_t def +) { + return !optionsObj.IsEmpty() + && optionsObj->Has(opt) + && optionsObj->Get(opt)->IsNumber() + ? optionsObj->Get(opt)->Uint32Value() + : def; +} + +#if (NODE_MODULE_VERSION > 0x000B) +// Node 0.11+ (0.11.3 and below won't compile with these) + +# define _NAN_METHOD_ARGS_TYPE const v8::FunctionCallbackInfo& +# define _NAN_METHOD_ARGS _NAN_METHOD_ARGS_TYPE args +# define _NAN_METHOD_RETURN_TYPE void + +# define _NAN_GETTER_ARGS_TYPE const v8::PropertyCallbackInfo& +# define _NAN_GETTER_ARGS _NAN_GETTER_ARGS_TYPE args +# define _NAN_GETTER_RETURN_TYPE void + +# define _NAN_SETTER_ARGS_TYPE const v8::PropertyCallbackInfo& +# define _NAN_SETTER_ARGS _NAN_SETTER_ARGS_TYPE args +# define _NAN_SETTER_RETURN_TYPE void + +# define _NAN_PROPERTY_GETTER_ARGS_TYPE \ + const v8::PropertyCallbackInfo& +# define _NAN_PROPERTY_GETTER_ARGS _NAN_PROPERTY_GETTER_ARGS_TYPE args +# define _NAN_PROPERTY_GETTER_RETURN_TYPE void + +# define _NAN_PROPERTY_SETTER_ARGS_TYPE \ + const v8::PropertyCallbackInfo& +# define _NAN_PROPERTY_SETTER_ARGS _NAN_PROPERTY_SETTER_ARGS_TYPE args +# define _NAN_PROPERTY_SETTER_RETURN_TYPE void + +# define _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE \ + const v8::PropertyCallbackInfo& +# define _NAN_PROPERTY_ENUMERATOR_ARGS _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE args +# define _NAN_PROPERTY_ENUMERATOR_RETURN_TYPE void + +# define _NAN_PROPERTY_DELETER_ARGS_TYPE \ + const v8::PropertyCallbackInfo& +# define _NAN_PROPERTY_DELETER_ARGS \ + _NAN_PROPERTY_DELETER_ARGS_TYPE args +# define _NAN_PROPERTY_DELETER_RETURN_TYPE void + +# define _NAN_PROPERTY_QUERY_ARGS_TYPE \ + const v8::PropertyCallbackInfo& +# define _NAN_PROPERTY_QUERY_ARGS _NAN_PROPERTY_QUERY_ARGS_TYPE args +# define _NAN_PROPERTY_QUERY_RETURN_TYPE void + +# define _NAN_INDEX_GETTER_ARGS_TYPE \ + const v8::PropertyCallbackInfo& +# define _NAN_INDEX_GETTER_ARGS _NAN_INDEX_GETTER_ARGS_TYPE args +# define _NAN_INDEX_GETTER_RETURN_TYPE void + +# define _NAN_INDEX_SETTER_ARGS_TYPE \ + const v8::PropertyCallbackInfo& +# define _NAN_INDEX_SETTER_ARGS _NAN_INDEX_SETTER_ARGS_TYPE args +# define _NAN_INDEX_SETTER_RETURN_TYPE void + +# define _NAN_INDEX_ENUMERATOR_ARGS_TYPE \ + const v8::PropertyCallbackInfo& +# define _NAN_INDEX_ENUMERATOR_ARGS _NAN_INDEX_ENUMERATOR_ARGS_TYPE args +# define _NAN_INDEX_ENUMERATOR_RETURN_TYPE void + +# define _NAN_INDEX_DELETER_ARGS_TYPE \ + const v8::PropertyCallbackInfo& +# define _NAN_INDEX_DELETER_ARGS _NAN_INDEX_DELETER_ARGS_TYPE args +# define _NAN_INDEX_DELETER_RETURN_TYPE void + +# define _NAN_INDEX_QUERY_ARGS_TYPE \ + const v8::PropertyCallbackInfo& +# define _NAN_INDEX_QUERY_ARGS _NAN_INDEX_QUERY_ARGS_TYPE args +# define _NAN_INDEX_QUERY_RETURN_TYPE void + + typedef v8::FunctionCallback NanFunctionCallback; + + template + NAN_INLINE v8::Local NanNew() { + return T::New(v8::Isolate::GetCurrent()); + } + + template + NAN_INLINE v8::Local NanNew(P arg1) { + return T::New(v8::Isolate::GetCurrent(), arg1); + } + + template + NAN_INLINE v8::Local NanNew( + v8::Handle receiver + , int argc + , v8::Handle argv[] = 0) { + return v8::Signature::New(v8::Isolate::GetCurrent(), receiver, argc, argv); + } + + template + NAN_INLINE v8::Local NanNew( + NanFunctionCallback callback + , v8::Handle data = v8::Handle() + , v8::Handle signature = v8::Handle()) { + return T::New(v8::Isolate::GetCurrent(), callback, data, signature); + } + + template + NAN_INLINE v8::Local NanNew(v8::Handle arg1) { + return v8::Local::New(v8::Isolate::GetCurrent(), arg1); + } + + template + NAN_INLINE v8::Local NanNew(const v8::Persistent &arg1) { + return v8::Local::New(v8::Isolate::GetCurrent(), arg1); + } + + template + NAN_INLINE v8::Local NanNew(P arg1, int arg2) { + return T::New(v8::Isolate::GetCurrent(), arg1, arg2); + } + + template<> + NAN_INLINE v8::Local NanNew() { + return v8::Array::New(v8::Isolate::GetCurrent()); + } + + template<> + NAN_INLINE v8::Local NanNew(int length) { + return v8::Array::New(v8::Isolate::GetCurrent(), length); + } + + template<> + NAN_INLINE v8::Local NanNew(double time) { + return v8::Date::New(v8::Isolate::GetCurrent(), time).As(); + } + + template<> + NAN_INLINE v8::Local NanNew(int time) { + return v8::Date::New(v8::Isolate::GetCurrent(), time).As(); + } + + typedef v8::UnboundScript NanUnboundScript; + typedef v8::Script NanBoundScript; + + template + NAN_INLINE v8::Local NanNew( + P s + , const v8::ScriptOrigin& origin + ) { + v8::ScriptCompiler::Source source(s, origin); + return v8::ScriptCompiler::CompileUnbound( + v8::Isolate::GetCurrent(), &source); + } + + template<> + NAN_INLINE v8::Local NanNew( + v8::Local s + ) { + v8::ScriptCompiler::Source source(s); + return v8::ScriptCompiler::CompileUnbound( + v8::Isolate::GetCurrent(), &source); + } + + template<> + NAN_INLINE v8::Local NanNew(bool value) { + return v8::BooleanObject::New(value).As(); + } + + template<> + NAN_INLINE v8::Local + NanNew >( + v8::Local value) { + return v8::StringObject::New(value).As(); + } + + template<> + NAN_INLINE v8::Local + NanNew >( + v8::Handle value) { + return v8::StringObject::New(value).As(); + } + + template<> + NAN_INLINE v8::Local NanNew(double val) { + return v8::NumberObject::New( + v8::Isolate::GetCurrent(), val).As(); + } + + template + NAN_INLINE v8::Local NanNew( + v8::Handle pattern, v8::RegExp::Flags flags) { + return v8::RegExp::New(pattern, flags); + } + + template + NAN_INLINE v8::Local NanNew( + v8::Local pattern, v8::RegExp::Flags flags) { + return v8::RegExp::New(pattern, flags); + } + + template + NAN_INLINE v8::Local NanNew( + v8::Handle pattern, v8::RegExp::Flags flags) { + return v8::RegExp::New(pattern, flags); + } + + template + NAN_INLINE v8::Local NanNew( + v8::Local pattern, v8::RegExp::Flags flags) { + return v8::RegExp::New(pattern, flags); + } + + template<> + NAN_INLINE v8::Local NanNew(int32_t val) { + return v8::Uint32::NewFromUnsigned( + v8::Isolate::GetCurrent(), val)->ToUint32(); + } + + template<> + NAN_INLINE v8::Local NanNew(uint32_t val) { + return v8::Uint32::NewFromUnsigned( + v8::Isolate::GetCurrent(), val)->ToUint32(); + } + + template<> + NAN_INLINE v8::Local NanNew(int32_t val) { + return v8::Int32::New(v8::Isolate::GetCurrent(), val)->ToInt32(); + } + + template<> + NAN_INLINE v8::Local NanNew(uint32_t val) { + return v8::Int32::New(v8::Isolate::GetCurrent(), val)->ToInt32(); + } + + template<> + NAN_INLINE v8::Local NanNew( + char *arg + , int length) { + return v8::String::NewFromUtf8( + v8::Isolate::GetCurrent() + , arg + , v8::String::kNormalString + , length); + } + + template<> + NAN_INLINE v8::Local NanNew( + const char *arg + , int length) { + return v8::String::NewFromUtf8( + v8::Isolate::GetCurrent() + , arg + , v8::String::kNormalString + , length); + } + + template<> + NAN_INLINE v8::Local NanNew(char *arg) { + return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), arg); + } + + template<> + NAN_INLINE v8::Local NanNew( + const char *arg) { + return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), arg); + } + + template<> + NAN_INLINE v8::Local NanNew( + uint8_t *arg + , int length) { + return v8::String::NewFromOneByte( + v8::Isolate::GetCurrent() + , arg + , v8::String::kNormalString + , length); + } + + template<> + NAN_INLINE v8::Local NanNew( + const uint8_t *arg + , int length) { + return v8::String::NewFromOneByte( + v8::Isolate::GetCurrent() + , arg + , v8::String::kNormalString + , length); + } + + template<> + NAN_INLINE v8::Local NanNew(uint8_t *arg) { + return v8::String::NewFromOneByte(v8::Isolate::GetCurrent(), arg); + } + + template<> + NAN_INLINE v8::Local NanNew( + const uint8_t *arg) { + return v8::String::NewFromOneByte(v8::Isolate::GetCurrent(), arg); + } + + template<> + NAN_INLINE v8::Local NanNew( + uint16_t *arg + , int length) { + return v8::String::NewFromTwoByte( + v8::Isolate::GetCurrent() + , arg + , v8::String::kNormalString + , length); + } + + template<> + NAN_INLINE v8::Local NanNew( + const uint16_t *arg + , int length) { + return v8::String::NewFromTwoByte( + v8::Isolate::GetCurrent() + , arg + , v8::String::kNormalString + , length); + } + template<> + NAN_INLINE v8::Local NanNew( + uint16_t *arg) { + return v8::String::NewFromTwoByte(v8::Isolate::GetCurrent(), arg); + } + + template<> + NAN_INLINE v8::Local NanNew( + const uint16_t *arg) { + return v8::String::NewFromTwoByte(v8::Isolate::GetCurrent(), arg); + } + + template<> + NAN_INLINE v8::Local NanNew( + std::string arg) { + return NanNew(arg.c_str(), arg.size()); + } + + template<> + NAN_INLINE v8::Local NanNew() { + return v8::String::Empty(v8::Isolate::GetCurrent()); + } + + NAN_INLINE v8::Local NanNew(const char* arg, int length = -1) { + return NanNew(arg, length); + } + + NAN_INLINE v8::Local NanNew( + const uint8_t* arg + , int length = -1) { + return NanNew(arg, length); + } + + NAN_INLINE v8::Local NanNew( + const uint16_t* arg + , int length = -1) { + return NanNew(arg, length); + } + + NAN_INLINE v8::Local NanNew( + const std::string& arg) { + return NanNew(arg.c_str(), arg.size()); + } + + NAN_INLINE v8::Local NanNew(double val) { + return NanNew(val); + } + + NAN_INLINE v8::Local NanNew(int val) { + return NanNew(val); + } + + NAN_INLINE v8::Local NanNew(unsigned int val) { + return NanNew(val); + } + + NAN_INLINE v8::Local NanNew(bool val) { + return NanNew(val); + } + + NAN_INLINE v8::Local NanNew( + v8::String::ExternalStringResource *resource) { + return v8::String::NewExternal(v8::Isolate::GetCurrent(), resource); + } + + NAN_INLINE v8::Local NanNew( + v8::String::ExternalAsciiStringResource *resource) { + return v8::String::NewExternal(v8::Isolate::GetCurrent(), resource); + } + +# define NanScope() v8::HandleScope scope(v8::Isolate::GetCurrent()) +# define NanEscapableScope() \ + v8::EscapableHandleScope scope(v8::Isolate::GetCurrent()) + + template + NAN_INLINE v8::Local _NanEscapeScopeHelper(v8::Handle val) { + return NanNew(val); + } + + template + NAN_INLINE v8::Local _NanEscapeScopeHelper(v8::Local val) { + return val; + } + +# define NanEscapeScope(val) scope.Escape(_NanEscapeScopeHelper(val)) +# define NanLocker() v8::Locker locker(v8::Isolate::GetCurrent()) +# define NanUnlocker() v8::Unlocker unlocker(v8::Isolate::GetCurrent()) +# define NanReturnValue(value) return args.GetReturnValue().Set(value) +# define NanReturnUndefined() return +# define NanReturnNull() return args.GetReturnValue().SetNull() +# define NanReturnEmptyString() return args.GetReturnValue().SetEmptyString() + +# define NanObjectWrapHandle(obj) obj->handle() + + NAN_INLINE v8::Local NanUndefined() { + NanEscapableScope(); + return NanEscapeScope(NanNew(v8::Undefined(v8::Isolate::GetCurrent()))); + } + + NAN_INLINE v8::Local NanNull() { + NanEscapableScope(); + return NanEscapeScope(NanNew(v8::Null(v8::Isolate::GetCurrent()))); + } + + NAN_INLINE v8::Local NanTrue() { + NanEscapableScope(); + return NanEscapeScope(NanNew(v8::True(v8::Isolate::GetCurrent()))); + } + + NAN_INLINE v8::Local NanFalse() { + NanEscapableScope(); + return NanEscapeScope(NanNew(v8::False(v8::Isolate::GetCurrent()))); + } + + NAN_INLINE int NanAdjustExternalMemory(int bc) { + return static_cast( + v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(bc)); + } + + NAN_INLINE void NanSetTemplate( + v8::Handle templ + , const char *name + , v8::Handle value) { + templ->Set(v8::Isolate::GetCurrent(), name, value); + } + + NAN_INLINE void NanSetTemplate( + v8::Handle templ + , v8::Handle name + , v8::Handle value + , v8::PropertyAttribute attributes) { + templ->Set(name, value, attributes); + } + + NAN_INLINE v8::Local NanGetCurrentContext() { + return v8::Isolate::GetCurrent()->GetCurrentContext(); + } + + NAN_INLINE void* NanGetInternalFieldPointer( + v8::Handle object + , int index) { + return object->GetAlignedPointerFromInternalField(index); + } + + NAN_INLINE void NanSetInternalFieldPointer( + v8::Handle object + , int index + , void* value) { + object->SetAlignedPointerInInternalField(index, value); + } + + NAN_INLINE void NanAddGCEpilogueCallback( + v8::Isolate::GCEpilogueCallback callback + , v8::GCType gc_type_filter = v8::kGCTypeAll) { + v8::Isolate::GetCurrent()->AddGCEpilogueCallback(callback, gc_type_filter); + } + + NAN_INLINE void NanRemoveGCEpilogueCallback( + v8::Isolate::GCEpilogueCallback callback) { + v8::Isolate::GetCurrent()->RemoveGCEpilogueCallback(callback); + } + + NAN_INLINE void NanAddGCPrologueCallback( + v8::Isolate::GCPrologueCallback callback + , v8::GCType gc_type_filter = v8::kGCTypeAll) { + v8::Isolate::GetCurrent()->AddGCPrologueCallback(callback, gc_type_filter); + } + + NAN_INLINE void NanRemoveGCPrologueCallback( + v8::Isolate::GCPrologueCallback callback) { + v8::Isolate::GetCurrent()->RemoveGCPrologueCallback(callback); + } + + NAN_INLINE void NanGetHeapStatistics( + v8::HeapStatistics *heap_statistics) { + v8::Isolate::GetCurrent()->GetHeapStatistics(heap_statistics); + } + + NAN_DEPRECATED NAN_INLINE v8::Local NanSymbol( + const char* data, int length = -1) { + return NanNew(data, length); + } + + template + NAN_INLINE void NanAssignPersistent( + v8::Persistent& handle + , v8::Handle obj) { + handle.Reset(v8::Isolate::GetCurrent(), obj); + } + + template + NAN_INLINE void NanAssignPersistent( + v8::Persistent& handle + , const v8::Persistent& obj) { + handle.Reset(v8::Isolate::GetCurrent(), obj); + } + + template + class _NanWeakCallbackData; + + template + struct _NanWeakCallbackInfo { + typedef void (*Callback)(const _NanWeakCallbackData& data); + NAN_INLINE _NanWeakCallbackInfo(v8::Handle handle, P* param, Callback cb) + : parameter(param), callback(cb) { + NanAssignPersistent(persistent, handle); + } + + NAN_INLINE ~_NanWeakCallbackInfo() { + persistent.Reset(); + } + + P* const parameter; + Callback const callback; + v8::Persistent persistent; + }; + + template + class _NanWeakCallbackData { + public: + NAN_INLINE _NanWeakCallbackData(_NanWeakCallbackInfo *info) + : info_(info) { } + + NAN_INLINE v8::Local GetValue() const { + return NanNew(info_->persistent); + } + + NAN_INLINE P* GetParameter() const { return info_->parameter; } + + NAN_INLINE bool IsNearDeath() const { + return info_->persistent.IsNearDeath(); + } + + NAN_INLINE void Revive() const; + + NAN_INLINE _NanWeakCallbackInfo* GetCallbackInfo() const { + return info_; + } + + NAN_DEPRECATED NAN_INLINE void Dispose() const { + } + + private: + _NanWeakCallbackInfo* info_; + }; + + template + static void _NanWeakCallbackDispatcher( + const v8::WeakCallbackData > &data) { + _NanWeakCallbackInfo *info = data.GetParameter(); + _NanWeakCallbackData wcbd(info); + info->callback(wcbd); + if (wcbd.IsNearDeath()) { + delete wcbd.GetCallbackInfo(); + } + } + + template + NAN_INLINE void _NanWeakCallbackData::Revive() const { + info_->persistent.SetWeak(info_, &_NanWeakCallbackDispatcher); + } + +template +NAN_INLINE _NanWeakCallbackInfo* NanMakeWeakPersistent( + v8::Handle handle + , P* parameter + , typename _NanWeakCallbackInfo::Callback callback) { + _NanWeakCallbackInfo *cbinfo = + new _NanWeakCallbackInfo(handle, parameter, callback); + cbinfo->persistent.SetWeak(cbinfo, &_NanWeakCallbackDispatcher); + return cbinfo; +} + +# define NAN_WEAK_CALLBACK(name) \ + template \ + static void name(const _NanWeakCallbackData &data) + +# define _NAN_ERROR(fun, errmsg) fun(NanNew(errmsg)) + +# define _NAN_THROW_ERROR(fun, errmsg) \ + do { \ + NanScope(); \ + v8::Isolate::GetCurrent()->ThrowException(_NAN_ERROR(fun, errmsg)); \ + } while (0); + + NAN_INLINE v8::Local NanError(const char* errmsg) { + return _NAN_ERROR(v8::Exception::Error, errmsg); + } + + NAN_INLINE void NanThrowError(const char* errmsg) { + _NAN_THROW_ERROR(v8::Exception::Error, errmsg); + } + + NAN_INLINE void NanThrowError(v8::Handle error) { + NanScope(); + v8::Isolate::GetCurrent()->ThrowException(error); + } + + NAN_INLINE v8::Local NanError( + const char *msg + , const int errorNumber + ) { + v8::Local err = v8::Exception::Error(NanNew(msg)); + v8::Local obj = err.As(); + obj->Set(NanNew("code"), NanNew(errorNumber)); + return err; + } + + NAN_INLINE void NanThrowError( + const char *msg + , const int errorNumber + ) { + NanThrowError(NanError(msg, errorNumber)); + } + + NAN_INLINE v8::Local NanTypeError(const char* errmsg) { + return _NAN_ERROR(v8::Exception::TypeError, errmsg); + } + + NAN_INLINE void NanThrowTypeError(const char* errmsg) { + _NAN_THROW_ERROR(v8::Exception::TypeError, errmsg); + } + + NAN_INLINE v8::Local NanRangeError(const char* errmsg) { + return _NAN_ERROR(v8::Exception::RangeError, errmsg); + } + + NAN_INLINE void NanThrowRangeError(const char* errmsg) { + _NAN_THROW_ERROR(v8::Exception::RangeError, errmsg); + } + + template NAN_INLINE void NanDisposePersistent( + v8::Persistent &handle + ) { + handle.Reset(); + } + + NAN_INLINE v8::Local NanNewBufferHandle ( + char *data + , size_t length + , node::smalloc::FreeCallback callback + , void *hint + ) { + return node::Buffer::New( + v8::Isolate::GetCurrent(), data, length, callback, hint); + } + + NAN_INLINE v8::Local NanNewBufferHandle ( + const char *data + , uint32_t size + ) { + return node::Buffer::New(v8::Isolate::GetCurrent(), data, size); + } + + NAN_INLINE v8::Local NanNewBufferHandle (uint32_t size) { + return node::Buffer::New(v8::Isolate::GetCurrent(), size); + } + + NAN_INLINE v8::Local NanBufferUse( + char* data + , uint32_t size + ) { + return node::Buffer::Use(v8::Isolate::GetCurrent(), data, size); + } + + NAN_INLINE bool NanHasInstance( + v8::Persistent& function_template + , v8::Handle value + ) { + return NanNew(function_template)->HasInstance(value); + } + + NAN_INLINE v8::Local NanNewContextHandle( + v8::ExtensionConfiguration* extensions = NULL + , v8::Handle tmpl = v8::Handle() + , v8::Handle obj = v8::Handle() + ) { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + return v8::Local::New( + isolate + , v8::Context::New(isolate, extensions, tmpl, obj) + ); + } + + NAN_INLINE v8::Local NanCompileScript( + v8::Local s + , const v8::ScriptOrigin& origin + ) { + v8::ScriptCompiler::Source source(s, origin); + return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &source); + } + + NAN_INLINE v8::Local NanCompileScript( + v8::Local s + ) { + v8::ScriptCompiler::Source source(s); + return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &source); + } + + NAN_INLINE v8::Local NanRunScript( + v8::Handle script + ) { + return script->BindToCurrentContext()->Run(); + } + + NAN_INLINE v8::Local NanRunScript( + v8::Handle script + ) { + return script->Run(); + } + + NAN_INLINE v8::Local NanMakeCallback( + v8::Handle target + , v8::Handle func + , int argc + , v8::Handle* argv) { + return NanNew(node::MakeCallback( + v8::Isolate::GetCurrent(), target, func, argc, argv)); + } + + NAN_INLINE v8::Local NanMakeCallback( + v8::Handle target + , v8::Handle symbol + , int argc + , v8::Handle* argv) { + return NanNew(node::MakeCallback( + v8::Isolate::GetCurrent(), target, symbol, argc, argv)); + } + + NAN_INLINE v8::Local NanMakeCallback( + v8::Handle target + , const char* method + , int argc + , v8::Handle* argv) { + return NanNew(node::MakeCallback( + v8::Isolate::GetCurrent(), target, method, argc, argv)); + } + + template + NAN_INLINE void NanSetIsolateData( + v8::Isolate *isolate + , T *data + ) { + isolate->SetData(0, data); + } + + template + NAN_INLINE T *NanGetIsolateData( + v8::Isolate *isolate + ) { + return static_cast(isolate->GetData(0)); + } + + class NanAsciiString { + public: + NAN_INLINE explicit NanAsciiString(v8::Handle from) { + v8::Local toStr = from->ToString(); + int buf_size = toStr->Length() + 1; + buf = new char[buf_size]; + size = toStr->WriteOneByte( + reinterpret_cast(buf), 0, buf_size); + } + + NAN_INLINE int Size() const { + return size; + } + + NAN_INLINE char* operator*() { return buf; } + + NAN_INLINE ~NanAsciiString() { + delete[] buf; + } + + private: + char *buf; + int size; + }; + + class NanUtf8String { + public: + NAN_INLINE explicit NanUtf8String(v8::Handle from) { + v8::Local toStr = from->ToString(); + int buf_size = toStr->Utf8Length() + 1; + buf = new char[buf_size]; + size = toStr->WriteUtf8(buf, buf_size); + } + + NAN_INLINE int Size() const { + return size; + } + + NAN_INLINE char* operator*() { return buf; } + + NAN_INLINE ~NanUtf8String() { + delete[] buf; + } + + private: + char *buf; + int size; + }; + + class NanUcs2String { + public: + NAN_INLINE explicit NanUcs2String(v8::Handle from) { + v8::Local toStr = from->ToString(); + int buf_size = toStr->Length() + 1; + buf = new uint16_t[buf_size]; + size = toStr->Write(buf, 0, buf_size); + } + + NAN_INLINE int Size() const { + return size; + } + + NAN_INLINE uint16_t* operator*() { return buf; } + + NAN_INLINE ~NanUcs2String() { + delete[] buf; + } + + private: + uint16_t *buf; + int size; + }; + +#else +// Node 0.8 and 0.10 + +# define _NAN_METHOD_ARGS_TYPE const v8::Arguments& +# define _NAN_METHOD_ARGS _NAN_METHOD_ARGS_TYPE args +# define _NAN_METHOD_RETURN_TYPE v8::Handle + +# define _NAN_GETTER_ARGS_TYPE const v8::AccessorInfo & +# define _NAN_GETTER_ARGS _NAN_GETTER_ARGS_TYPE args +# define _NAN_GETTER_RETURN_TYPE v8::Handle + +# define _NAN_SETTER_ARGS_TYPE const v8::AccessorInfo & +# define _NAN_SETTER_ARGS _NAN_SETTER_ARGS_TYPE args +# define _NAN_SETTER_RETURN_TYPE void + +# define _NAN_PROPERTY_GETTER_ARGS_TYPE const v8::AccessorInfo& +# define _NAN_PROPERTY_GETTER_ARGS _NAN_PROPERTY_GETTER_ARGS_TYPE args +# define _NAN_PROPERTY_GETTER_RETURN_TYPE v8::Handle + +# define _NAN_PROPERTY_SETTER_ARGS_TYPE const v8::AccessorInfo& +# define _NAN_PROPERTY_SETTER_ARGS _NAN_PROPERTY_SETTER_ARGS_TYPE args +# define _NAN_PROPERTY_SETTER_RETURN_TYPE v8::Handle + +# define _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE const v8::AccessorInfo& +# define _NAN_PROPERTY_ENUMERATOR_ARGS _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE args +# define _NAN_PROPERTY_ENUMERATOR_RETURN_TYPE v8::Handle + +# define _NAN_PROPERTY_DELETER_ARGS_TYPE const v8::AccessorInfo& +# define _NAN_PROPERTY_DELETER_ARGS _NAN_PROPERTY_DELETER_ARGS_TYPE args +# define _NAN_PROPERTY_DELETER_RETURN_TYPE v8::Handle + +# define _NAN_PROPERTY_QUERY_ARGS_TYPE const v8::AccessorInfo& +# define _NAN_PROPERTY_QUERY_ARGS _NAN_PROPERTY_QUERY_ARGS_TYPE args +# define _NAN_PROPERTY_QUERY_RETURN_TYPE v8::Handle + +# define _NAN_INDEX_GETTER_ARGS_TYPE const v8::AccessorInfo& +# define _NAN_INDEX_GETTER_ARGS _NAN_INDEX_GETTER_ARGS_TYPE args +# define _NAN_INDEX_GETTER_RETURN_TYPE v8::Handle + +# define _NAN_INDEX_SETTER_ARGS_TYPE const v8::AccessorInfo& +# define _NAN_INDEX_SETTER_ARGS _NAN_INDEX_SETTER_ARGS_TYPE args +# define _NAN_INDEX_SETTER_RETURN_TYPE v8::Handle + +# define _NAN_INDEX_ENUMERATOR_ARGS_TYPE const v8::AccessorInfo& +# define _NAN_INDEX_ENUMERATOR_ARGS _NAN_INDEX_ENUMERATOR_ARGS_TYPE args +# define _NAN_INDEX_ENUMERATOR_RETURN_TYPE v8::Handle + +# define _NAN_INDEX_DELETER_ARGS_TYPE const v8::AccessorInfo& +# define _NAN_INDEX_DELETER_ARGS _NAN_INDEX_DELETER_ARGS_TYPE args +# define _NAN_INDEX_DELETER_RETURN_TYPE v8::Handle + +# define _NAN_INDEX_QUERY_ARGS_TYPE const v8::AccessorInfo& +# define _NAN_INDEX_QUERY_ARGS _NAN_INDEX_QUERY_ARGS_TYPE args +# define _NAN_INDEX_QUERY_RETURN_TYPE v8::Handle + + typedef v8::InvocationCallback NanFunctionCallback; + + NAN_DEPRECATED NAN_INLINE v8::Local NanSymbol( + const char* data, int length = -1) { + return v8::String::NewSymbol(data, length); + } + + template + NAN_INLINE v8::Local NanNew() { + return v8::Local::New(T::New()); + } + + template + NAN_INLINE v8::Local NanNew(v8::Handle arg) { + return v8::Local::New(arg); + } + + template + NAN_INLINE v8::Local NanNew( + v8::Handle receiver + , int argc + , v8::Handle argv[] = 0) { + return v8::Signature::New(receiver, argc, argv); + } + + template + NAN_INLINE v8::Local NanNew( + NanFunctionCallback callback + , v8::Handle data = v8::Handle() + , v8::Handle signature = v8::Handle()) { + return T::New(callback, data, signature); + } + + template + NAN_INLINE v8::Local NanNew(const v8::Persistent &arg) { + return v8::Local::New(arg); + } + + template + NAN_INLINE v8::Local NanNew(P arg) { + return v8::Local::New(T::New(arg)); + } + + template + NAN_INLINE v8::Local NanNew(P arg, int length) { + return v8::Local::New(T::New(arg, length)); + } + + template + NAN_INLINE v8::Local NanNew( + v8::Handle pattern, v8::RegExp::Flags flags) { + return v8::RegExp::New(pattern, flags); + } + + template + NAN_INLINE v8::Local NanNew( + v8::Local pattern, v8::RegExp::Flags flags) { + return v8::RegExp::New(pattern, flags); + } + + template + NAN_INLINE v8::Local NanNew( + v8::Handle pattern, v8::RegExp::Flags flags) { + return v8::RegExp::New(pattern, flags); + } + + template + NAN_INLINE v8::Local NanNew( + v8::Local pattern, v8::RegExp::Flags flags) { + return v8::RegExp::New(pattern, flags); + } + + template<> + NAN_INLINE v8::Local NanNew() { + return v8::Array::New(); + } + + template<> + NAN_INLINE v8::Local NanNew(int length) { + return v8::Array::New(length); + } + + template<> + NAN_INLINE v8::Local NanNew(double time) { + return v8::Date::New(time).As(); + } + + template<> + NAN_INLINE v8::Local NanNew(int time) { + return v8::Date::New(time).As(); + } + + typedef v8::Script NanUnboundScript; + typedef v8::Script NanBoundScript; + + template + NAN_INLINE v8::Local NanNew( + P s + , const v8::ScriptOrigin& origin + ) { + return v8::Script::New(s, const_cast(&origin)); + } + + template<> + NAN_INLINE v8::Local NanNew( + v8::Local s + ) { + return v8::Script::New(s); + } + + template<> + NAN_INLINE v8::Local NanNew(bool value) { + return v8::BooleanObject::New(value).As(); + } + + template<> + NAN_INLINE v8::Local + NanNew >( + v8::Local value) { + return v8::StringObject::New(value).As(); + } + + template<> + NAN_INLINE v8::Local + NanNew >( + v8::Handle value) { + return v8::StringObject::New(value).As(); + } + + template<> + NAN_INLINE v8::Local NanNew(double val) { + return v8::NumberObject::New(val).As(); + } + + template<> + NAN_INLINE v8::Local NanNew(int32_t val) { + return v8::Uint32::NewFromUnsigned(val)->ToUint32(); + } + + template<> + NAN_INLINE v8::Local NanNew(uint32_t val) { + return v8::Uint32::NewFromUnsigned(val)->ToUint32(); + } + + template<> + NAN_INLINE v8::Local NanNew(int32_t val) { + return v8::Int32::New(val)->ToInt32(); + } + + template<> + NAN_INLINE v8::Local NanNew(uint32_t val) { + return v8::Int32::New(val)->ToInt32(); + } + + template<> + NAN_INLINE v8::Local NanNew( + uint8_t *arg + , int length) { + int len = length; + if (len < 0) { + size_t temp = strlen(reinterpret_cast(arg)); + assert(temp <= INT_MAX && "too long string"); + len = static_cast(temp); + } + uint16_t *warg = new uint16_t[len]; + for (int i = 0; i < len; i++) { + warg[i] = arg[i]; + } + v8::Local retval = v8::String::New(warg, len); + delete[] warg; + return retval; + } + + template<> + NAN_INLINE v8::Local NanNew( + const uint8_t *arg + , int length) { + int len = length; + if (len < 0) { + size_t temp = strlen(reinterpret_cast(arg)); + assert(temp <= INT_MAX && "too long string"); + len = static_cast(temp); + } + uint16_t *warg = new uint16_t[len]; + for (int i = 0; i < len; i++) { + warg[i] = arg[i]; + } + v8::Local retval = v8::String::New(warg, len); + delete[] warg; + return retval; + } + + template<> + NAN_INLINE v8::Local NanNew(uint8_t *arg) { + size_t temp = strlen(reinterpret_cast(arg)); + assert(temp <= INT_MAX && "too long string"); + int length = static_cast(temp); + uint16_t *warg = new uint16_t[length]; + for (int i = 0; i < length; i++) { + warg[i] = arg[i]; + } + + v8::Local retval = v8::String::New(warg, length); + delete[] warg; + return retval; + } + + template<> + NAN_INLINE v8::Local NanNew( + const uint8_t *arg) { + size_t temp = strlen(reinterpret_cast(arg)); + assert(temp <= INT_MAX && "too long string"); + int length = static_cast(temp); + uint16_t *warg = new uint16_t[length]; + for (int i = 0; i < length; i++) { + warg[i] = arg[i]; + } + v8::Local retval = v8::String::New(warg, length); + delete[] warg; + return retval; + } + + template<> + NAN_INLINE v8::Local NanNew( + std::string arg) { + return NanNew(arg.c_str(), arg.size()); + } + + template<> + NAN_INLINE v8::Local NanNew() { + return v8::String::Empty(); + } + + NAN_INLINE v8::Local NanNew(const char* arg, int length = -1) { + return NanNew(arg, length); + } + + NAN_INLINE v8::Local NanNew( + const uint8_t* arg + , int length = -1) { + return NanNew(arg, length); + } + + NAN_INLINE v8::Local NanNew( + const uint16_t* arg + , int length = -1) { + return NanNew(arg, length); + } + + NAN_INLINE v8::Local NanNew( + std::string& arg) { + return NanNew(arg.c_str(), arg.size()); + } + + NAN_INLINE v8::Local NanNew(double val) { + return NanNew(val); + } + + NAN_INLINE v8::Local NanNew(int val) { + return NanNew(val); + } + + NAN_INLINE v8::Local NanNew(unsigned int val) { + return NanNew(val); + } + + NAN_INLINE v8::Local NanNew(bool val) { + return NanNew(val); + } + + NAN_INLINE v8::Local NanNew( + v8::String::ExternalStringResource *resource) { + return v8::String::NewExternal(resource); + } + + NAN_INLINE v8::Local NanNew( + v8::String::ExternalAsciiStringResource *resource) { + return v8::String::NewExternal(resource); + } + +# define NanScope() v8::HandleScope scope +# define NanEscapableScope() v8::HandleScope scope +# define NanEscapeScope(val) scope.Close(val) +# define NanLocker() v8::Locker locker +# define NanUnlocker() v8::Unlocker unlocker +# define NanReturnValue(value) return scope.Close(value) +# define NanReturnUndefined() return v8::Undefined() +# define NanReturnNull() return v8::Null() +# define NanReturnEmptyString() return v8::String::Empty() +# define NanObjectWrapHandle(obj) v8::Local::New(obj->handle_) + + NAN_INLINE v8::Local NanUndefined() { + NanEscapableScope(); + return NanEscapeScope(NanNew(v8::Undefined())); + } + + NAN_INLINE v8::Local NanNull() { + NanEscapableScope(); + return NanEscapeScope(NanNew(v8::Null())); + } + + NAN_INLINE v8::Local NanTrue() { + NanEscapableScope(); + return NanEscapeScope(NanNew(v8::True())); + } + + NAN_INLINE v8::Local NanFalse() { + NanEscapableScope(); + return NanEscapeScope(NanNew(v8::False())); + } + + NAN_INLINE int NanAdjustExternalMemory(int bc) { + return static_cast(v8::V8::AdjustAmountOfExternalAllocatedMemory(bc)); + } + + NAN_INLINE void NanSetTemplate( + v8::Handle templ + , const char *name + , v8::Handle value) { + templ->Set(name, value); + } + + NAN_INLINE void NanSetTemplate( + v8::Handle templ + , v8::Handle name + , v8::Handle value + , v8::PropertyAttribute attributes) { + templ->Set(name, value, attributes); + } + + NAN_INLINE v8::Local NanGetCurrentContext() { + return v8::Context::GetCurrent(); + } + + NAN_INLINE void* NanGetInternalFieldPointer( + v8::Handle object + , int index) { + return object->GetPointerFromInternalField(index); + } + + NAN_INLINE void NanSetInternalFieldPointer( + v8::Handle object + , int index + , void* value) { + object->SetPointerInInternalField(index, value); + } + + NAN_INLINE void NanAddGCEpilogueCallback( + v8::GCEpilogueCallback callback + , v8::GCType gc_type_filter = v8::kGCTypeAll) { + v8::V8::AddGCEpilogueCallback(callback, gc_type_filter); + } + NAN_INLINE void NanRemoveGCEpilogueCallback( + v8::GCEpilogueCallback callback) { + v8::V8::RemoveGCEpilogueCallback(callback); + } + NAN_INLINE void NanAddGCPrologueCallback( + v8::GCPrologueCallback callback + , v8::GCType gc_type_filter = v8::kGCTypeAll) { + v8::V8::AddGCPrologueCallback(callback, gc_type_filter); + } + NAN_INLINE void NanRemoveGCPrologueCallback( + v8::GCPrologueCallback callback) { + v8::V8::RemoveGCPrologueCallback(callback); + } + NAN_INLINE void NanGetHeapStatistics( + v8::HeapStatistics *heap_statistics) { + v8::V8::GetHeapStatistics(heap_statistics); + } + + template + NAN_INLINE void NanAssignPersistent( + v8::Persistent& handle + , v8::Handle obj) { + handle.Dispose(); + handle = v8::Persistent::New(obj); + } + + template + class _NanWeakCallbackData; + + template + struct _NanWeakCallbackInfo { + typedef void (*Callback)(const _NanWeakCallbackData &data); + NAN_INLINE _NanWeakCallbackInfo(v8::Handle handle, P* param, Callback cb) + : parameter(param) + , callback(cb) + , persistent(v8::Persistent::New(handle)) { } + + NAN_INLINE ~_NanWeakCallbackInfo() { + persistent.Dispose(); + persistent.Clear(); + } + + P* const parameter; + Callback const callback; + v8::Persistent persistent; + }; + + template + class _NanWeakCallbackData { + public: + NAN_INLINE _NanWeakCallbackData(_NanWeakCallbackInfo *info) + : info_(info) { } + + NAN_INLINE v8::Local GetValue() const { + return NanNew(info_->persistent); + } + + NAN_INLINE P* GetParameter() const { return info_->parameter; } + + NAN_INLINE bool IsNearDeath() const { + return info_->persistent.IsNearDeath(); + } + + NAN_INLINE void Revive() const; + + NAN_INLINE _NanWeakCallbackInfo* GetCallbackInfo() const { + return info_; + } + + NAN_DEPRECATED NAN_INLINE void Dispose() const { + } + + private: + _NanWeakCallbackInfo* info_; + }; + + template + static void _NanWeakPersistentDispatcher( + v8::Persistent object, void *data) { + _NanWeakCallbackInfo* info = + static_cast<_NanWeakCallbackInfo*>(data); + _NanWeakCallbackData wcbd(info); + info->callback(wcbd); + if (wcbd.IsNearDeath()) { + delete wcbd.GetCallbackInfo(); + } + } + + template + NAN_INLINE void _NanWeakCallbackData::Revive() const { + info_->persistent.MakeWeak( + info_ + , &_NanWeakPersistentDispatcher); + } + + template + NAN_INLINE _NanWeakCallbackInfo* NanMakeWeakPersistent( + v8::Handle handle + , P* parameter + , typename _NanWeakCallbackInfo::Callback callback) { + _NanWeakCallbackInfo *cbinfo = + new _NanWeakCallbackInfo(handle, parameter, callback); + cbinfo->persistent.MakeWeak( + cbinfo + , &_NanWeakPersistentDispatcher); + return cbinfo; + } + +# define NAN_WEAK_CALLBACK(name) \ + template \ + static void name(const _NanWeakCallbackData &data) + +# define _NAN_ERROR(fun, errmsg) \ + fun(v8::String::New(errmsg)) + +# define _NAN_THROW_ERROR(fun, errmsg) \ + do { \ + NanScope(); \ + return v8::Local::New( \ + v8::ThrowException(_NAN_ERROR(fun, errmsg))); \ + } while (0); + + NAN_INLINE v8::Local NanError(const char* errmsg) { + return _NAN_ERROR(v8::Exception::Error, errmsg); + } + + NAN_INLINE v8::Local NanThrowError(const char* errmsg) { + _NAN_THROW_ERROR(v8::Exception::Error, errmsg); + } + + NAN_INLINE v8::Local NanThrowError( + v8::Handle error + ) { + NanScope(); + return v8::Local::New(v8::ThrowException(error)); + } + + NAN_INLINE v8::Local NanError( + const char *msg + , const int errorNumber + ) { + v8::Local err = v8::Exception::Error(v8::String::New(msg)); + v8::Local obj = err.As(); + obj->Set(v8::String::New("code"), v8::Int32::New(errorNumber)); + return err; + } + + NAN_INLINE v8::Local NanThrowError( + const char *msg + , const int errorNumber + ) { + return NanThrowError(NanError(msg, errorNumber)); + } + + NAN_INLINE v8::Local NanTypeError(const char* errmsg) { + return _NAN_ERROR(v8::Exception::TypeError, errmsg); + } + + NAN_INLINE v8::Local NanThrowTypeError( + const char* errmsg + ) { + _NAN_THROW_ERROR(v8::Exception::TypeError, errmsg); + } + + NAN_INLINE v8::Local NanRangeError( + const char* errmsg + ) { + return _NAN_ERROR(v8::Exception::RangeError, errmsg); + } + + NAN_INLINE v8::Local NanThrowRangeError( + const char* errmsg + ) { + _NAN_THROW_ERROR(v8::Exception::RangeError, errmsg); + } + + template + NAN_INLINE void NanDisposePersistent( + v8::Persistent &handle) { // NOLINT(runtime/references) + handle.Dispose(); + handle.Clear(); + } + + NAN_INLINE v8::Local NanNewBufferHandle ( + char *data + , size_t length + , node::Buffer::free_callback callback + , void *hint + ) { + return NanNew( + node::Buffer::New(data, length, callback, hint)->handle_); + } + + NAN_INLINE v8::Local NanNewBufferHandle ( + const char *data + , uint32_t size + ) { +#if NODE_MODULE_VERSION >= 0x000B + return NanNew(node::Buffer::New(data, size)->handle_); +#else + return NanNew( + node::Buffer::New(const_cast(data), size)->handle_); +#endif + } + + NAN_INLINE v8::Local NanNewBufferHandle (uint32_t size) { + return NanNew(node::Buffer::New(size)->handle_); + } + + NAN_INLINE void FreeData(char *data, void *hint) { + delete[] data; + } + + NAN_INLINE v8::Local NanBufferUse( + char* data + , uint32_t size + ) { + return NanNew( + node::Buffer::New(data, size, FreeData, NULL)->handle_); + } + + NAN_INLINE bool NanHasInstance( + v8::Persistent& function_template + , v8::Handle value + ) { + return function_template->HasInstance(value); + } + + NAN_INLINE v8::Local NanNewContextHandle( + v8::ExtensionConfiguration* extensions = NULL + , v8::Handle tmpl = v8::Handle() + , v8::Handle obj = v8::Handle() + ) { + v8::Persistent ctx = v8::Context::New(extensions, tmpl, obj); + v8::Local lctx = NanNew(ctx); + ctx.Dispose(); + return lctx; + } + + NAN_INLINE v8::Local NanCompileScript( + v8::Local s + , const v8::ScriptOrigin& origin + ) { + return v8::Script::Compile(s, const_cast(&origin)); + } + + NAN_INLINE v8::Local NanCompileScript( + v8::Local s + ) { + return v8::Script::Compile(s); + } + + NAN_INLINE v8::Local NanRunScript(v8::Handle script) { + return script->Run(); + } + + NAN_INLINE v8::Local NanMakeCallback( + v8::Handle target + , v8::Handle func + , int argc + , v8::Handle* argv) { +# if NODE_VERSION_AT_LEAST(0, 8, 0) + return NanNew(node::MakeCallback(target, func, argc, argv)); +# else + v8::TryCatch try_catch; + v8::Local result = NanNew(func->Call(target, argc, argv)); + if (try_catch.HasCaught()) { + node::FatalException(try_catch); + } + return result; +# endif + } + + NAN_INLINE v8::Local NanMakeCallback( + v8::Handle target + , v8::Handle symbol + , int argc + , v8::Handle* argv) { +# if NODE_VERSION_AT_LEAST(0, 8, 0) + return NanNew(node::MakeCallback(target, symbol, argc, argv)); +# else + v8::Local callback = target->Get(symbol).As(); + return NanMakeCallback(target, callback, argc, argv); +# endif + } + + NAN_INLINE v8::Local NanMakeCallback( + v8::Handle target + , const char* method + , int argc + , v8::Handle* argv) { +# if NODE_VERSION_AT_LEAST(0, 8, 0) + return NanNew(node::MakeCallback(target, method, argc, argv)); +# else + return NanMakeCallback(target, NanNew(method), argc, argv); +# endif + } + + template + NAN_INLINE void NanSetIsolateData( + v8::Isolate *isolate + , T *data + ) { + isolate->SetData(data); + } + + template + NAN_INLINE T *NanGetIsolateData( + v8::Isolate *isolate + ) { + return static_cast(isolate->GetData()); + } + + class NanAsciiString { + public: + NAN_INLINE explicit NanAsciiString(v8::Handle from) { + v8::Local toStr = from->ToString(); + int buf_size = toStr->Length() + 1; + buf = new char[buf_size]; + size = toStr->WriteAscii(buf, 0, buf_size); + } + + NAN_INLINE int Size() const { + return size; + } + + NAN_INLINE char* operator*() { return buf; } + + NAN_INLINE ~NanAsciiString() { + delete[] buf; + } + + private: + char *buf; + int size; + }; + + class NanUtf8String { + public: + NAN_INLINE explicit NanUtf8String(v8::Handle from) { + v8::Local toStr = from->ToString(); + int buf_size = toStr->Utf8Length() + 1; + buf = new char[buf_size]; + size = toStr->WriteUtf8(buf, buf_size); + } + + NAN_INLINE int Size() const { + return size; + } + + NAN_INLINE char* operator*() { return buf; } + + NAN_INLINE ~NanUtf8String() { + delete[] buf; + } + + private: + char *buf; + int size; + }; + + class NanUcs2String { + public: + NAN_INLINE explicit NanUcs2String(v8::Handle from) { + v8::Local toStr = from->ToString(); + int buf_size = toStr->Length() + 1; + buf = new uint16_t[buf_size]; + size = toStr->Write(buf, 0, buf_size); + } + + NAN_INLINE int Size() const { + return size; + } + + NAN_INLINE uint16_t* operator*() { return buf; } + + NAN_INLINE ~NanUcs2String() { + delete[] buf; + } + + private: + uint16_t *buf; + int size; + }; + +#endif // NODE_MODULE_VERSION + +typedef void (*NanFreeCallback)(char *data, void *hint); + +#define NAN_METHOD(name) _NAN_METHOD_RETURN_TYPE name(_NAN_METHOD_ARGS) +#define NAN_GETTER(name) \ + _NAN_GETTER_RETURN_TYPE name( \ + v8::Local property \ + , _NAN_GETTER_ARGS) +#define NAN_SETTER(name) \ + _NAN_SETTER_RETURN_TYPE name( \ + v8::Local property \ + , v8::Local value \ + , _NAN_SETTER_ARGS) +#define NAN_PROPERTY_GETTER(name) \ + _NAN_PROPERTY_GETTER_RETURN_TYPE name( \ + v8::Local property \ + , _NAN_PROPERTY_GETTER_ARGS) +#define NAN_PROPERTY_SETTER(name) \ + _NAN_PROPERTY_SETTER_RETURN_TYPE name( \ + v8::Local property \ + , v8::Local value \ + , _NAN_PROPERTY_SETTER_ARGS) +#define NAN_PROPERTY_ENUMERATOR(name) \ + _NAN_PROPERTY_ENUMERATOR_RETURN_TYPE name(_NAN_PROPERTY_ENUMERATOR_ARGS) +#define NAN_PROPERTY_DELETER(name) \ + _NAN_PROPERTY_DELETER_RETURN_TYPE name( \ + v8::Local property \ + , _NAN_PROPERTY_DELETER_ARGS) +#define NAN_PROPERTY_QUERY(name) \ + _NAN_PROPERTY_QUERY_RETURN_TYPE name( \ + v8::Local property \ + , _NAN_PROPERTY_QUERY_ARGS) +# define NAN_INDEX_GETTER(name) \ + _NAN_INDEX_GETTER_RETURN_TYPE name(uint32_t index, _NAN_INDEX_GETTER_ARGS) +#define NAN_INDEX_SETTER(name) \ + _NAN_INDEX_SETTER_RETURN_TYPE name( \ + uint32_t index \ + , v8::Local value \ + , _NAN_INDEX_SETTER_ARGS) +#define NAN_INDEX_ENUMERATOR(name) \ + _NAN_INDEX_ENUMERATOR_RETURN_TYPE name(_NAN_INDEX_ENUMERATOR_ARGS) +#define NAN_INDEX_DELETER(name) \ + _NAN_INDEX_DELETER_RETURN_TYPE name( \ + uint32_t index \ + , _NAN_INDEX_DELETER_ARGS) +#define NAN_INDEX_QUERY(name) \ + _NAN_INDEX_QUERY_RETURN_TYPE name(uint32_t index, _NAN_INDEX_QUERY_ARGS) + +class NanCallback { + public: + NanCallback() { + NanScope(); + v8::Local obj = NanNew(); + NanAssignPersistent(handle, obj); + } + + explicit NanCallback(const v8::Handle &fn) { + NanScope(); + v8::Local obj = NanNew(); + NanAssignPersistent(handle, obj); + SetFunction(fn); + } + + ~NanCallback() { + if (handle.IsEmpty()) return; + NanDisposePersistent(handle); + } + + NAN_INLINE void SetFunction(const v8::Handle &fn) { + NanScope(); + NanNew(handle)->Set(kCallbackIndex, fn); + } + + NAN_INLINE v8::Local GetFunction() const { + NanEscapableScope(); + return NanEscapeScope(NanNew(handle)->Get(kCallbackIndex) + .As()); + } + + NAN_INLINE bool IsEmpty() const { + NanScope(); + return NanNew(handle)->Get(kCallbackIndex)->IsUndefined(); + } + + v8::Handle Call(int argc, v8::Handle argv[]) const { + NanEscapableScope(); +#if (NODE_MODULE_VERSION > 0x000B) // 0.11.12+ + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::Local callback = NanNew(handle)-> + Get(kCallbackIndex).As(); + return NanEscapeScope(node::MakeCallback( + isolate + , isolate->GetCurrentContext()->Global() + , callback + , argc + , argv + )); +#else +#if NODE_VERSION_AT_LEAST(0, 8, 0) + v8::Local callback = handle-> + Get(kCallbackIndex).As(); + return NanEscapeScope(node::MakeCallback( + v8::Context::GetCurrent()->Global() + , callback + , argc + , argv + )); +#else + v8::Local callback = handle-> + Get(kCallbackIndex).As(); + return NanEscapeScope(NanMakeCallback( + v8::Context::GetCurrent()->Global(), callback, argc, argv)); +#endif +#endif + } + + private: + v8::Persistent handle; + static const uint32_t kCallbackIndex = 0; +}; + +/* abstract */ class NanAsyncWorker { + public: + explicit NanAsyncWorker(NanCallback *callback) + : callback(callback), errmsg_(NULL) { + request.data = this; + + NanScope(); + v8::Local obj = NanNew(); + NanAssignPersistent(persistentHandle, obj); + } + + virtual ~NanAsyncWorker() { + NanScope(); + + if (!persistentHandle.IsEmpty()) + NanDisposePersistent(persistentHandle); + if (callback) + delete callback; + if (errmsg_) + delete[] errmsg_; + } + + virtual void WorkComplete() { + NanScope(); + + if (errmsg_ == NULL) + HandleOKCallback(); + else + HandleErrorCallback(); + delete callback; + callback = NULL; + } + + NAN_INLINE void SaveToPersistent( + const char *key, const v8::Local &obj) { + v8::Local handle = NanNew(persistentHandle); + handle->Set(NanNew(key), obj); + } + + v8::Local GetFromPersistent(const char *key) const { + NanEscapableScope(); + v8::Local handle = NanNew(persistentHandle); + return NanEscapeScope(handle->Get(NanNew(key)).As()); + } + + virtual void Execute() = 0; + + uv_work_t request; + + protected: + v8::Persistent persistentHandle; + NanCallback *callback; + + virtual void HandleOKCallback() { + NanScope(); + + callback->Call(0, NULL); + } + + virtual void HandleErrorCallback() { + NanScope(); + + v8::Local argv[] = { + v8::Exception::Error(NanNew(ErrorMessage())) + }; + callback->Call(1, argv); + } + + void SetErrorMessage(const char *msg) { + if (errmsg_) { + delete[] errmsg_; + } + + size_t size = strlen(msg) + 1; + errmsg_ = new char[size]; + memcpy(errmsg_, msg, size); + } + + const char* ErrorMessage() const { + return errmsg_; + } + + private: + char *errmsg_; +}; + +NAN_INLINE void NanAsyncExecute (uv_work_t* req) { + NanAsyncWorker *worker = static_cast(req->data); + worker->Execute(); +} + +NAN_INLINE void NanAsyncExecuteComplete (uv_work_t* req) { + NanAsyncWorker* worker = static_cast(req->data); + worker->WorkComplete(); + delete worker; +} + +NAN_INLINE void NanAsyncQueueWorker (NanAsyncWorker* worker) { + uv_queue_work( + uv_default_loop() + , &worker->request + , NanAsyncExecute + , (uv_after_work_cb)NanAsyncExecuteComplete + ); +} + +//// Base 64 //// + +#define _nan_base64_encoded_size(size) ((size + 2 - ((size + 2) % 3)) / 3 * 4) + +// Doesn't check for padding at the end. Can be 1-2 bytes over. +NAN_INLINE size_t _nan_base64_decoded_size_fast(size_t size) { + size_t remainder = size % 4; + + size = (size / 4) * 3; + if (remainder) { + if (size == 0 && remainder == 1) { + // special case: 1-byte input cannot be decoded + size = 0; + } else { + // non-padded input, add 1 or 2 extra bytes + size += 1 + (remainder == 3); + } + } + + return size; +} + +template +NAN_INLINE size_t _nan_base64_decoded_size( + const T* src + , size_t size +) { + if (size == 0) + return 0; + + if (src[size - 1] == '=') + size--; + if (size > 0 && src[size - 1] == '=') + size--; + + return _nan_base64_decoded_size_fast(size); +} + +// supports regular and URL-safe base64 +static const int _nan_unbase64_table[] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -1, -1, -2, -1, -1 + , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 + , -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 62, -1, 63 + , 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1 + , -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 + , 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63 + , -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 + , 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 + , -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 + , -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 + , -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 +}; + +#define _nan_unbase64(x) _nan_unbase64_table[(uint8_t)(x)] + +template static size_t _nan_base64_decode( + char* buf + , size_t len + , const T* src + , const size_t srcLen +) { + char* dst = buf; + char* dstEnd = buf + len; + const T* srcEnd = src + srcLen; + + while (src < srcEnd && dst < dstEnd) { + ptrdiff_t remaining = srcEnd - src; + char a, b, c, d; + + while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--; + if (remaining == 0 || *src == '=') break; + a = _nan_unbase64(*src++); + + while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--; + if (remaining <= 1 || *src == '=') break; + b = _nan_unbase64(*src++); + + *dst++ = (a << 2) | ((b & 0x30) >> 4); + if (dst == dstEnd) break; + + while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--; + if (remaining <= 2 || *src == '=') break; + c = _nan_unbase64(*src++); + + *dst++ = ((b & 0x0F) << 4) | ((c & 0x3C) >> 2); + if (dst == dstEnd) break; + + while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--; + if (remaining <= 3 || *src == '=') break; + d = _nan_unbase64(*src++); + + *dst++ = ((c & 0x03) << 6) | (d & 0x3F); + } + + return dst - buf; +} + +//// HEX //// + +template unsigned _nan_hex2bin(T c) { + if (c >= '0' && c <= '9') return c - '0'; + if (c >= 'A' && c <= 'F') return 10 + (c - 'A'); + if (c >= 'a' && c <= 'f') return 10 + (c - 'a'); + return static_cast(-1); +} + +template static size_t _nan_hex_decode( + char* buf + , size_t len + , const T* src + , const size_t srcLen +) { + size_t i; + for (i = 0; i < len && i * 2 + 1 < srcLen; ++i) { + unsigned a = _nan_hex2bin(src[i * 2 + 0]); + unsigned b = _nan_hex2bin(src[i * 2 + 1]); + if (!~a || !~b) return i; + buf[i] = a * 16 + b; + } + + return i; +} + +static bool _NanGetExternalParts( + v8::Handle val + , const char** data + , size_t* len +) { + if (node::Buffer::HasInstance(val)) { + *data = node::Buffer::Data(val.As()); + *len = node::Buffer::Length(val.As()); + return true; + } + + assert(val->IsString()); + v8::Local str = NanNew(val.As()); + + if (str->IsExternalAscii()) { + const v8::String::ExternalAsciiStringResource* ext; + ext = str->GetExternalAsciiStringResource(); + *data = ext->data(); + *len = ext->length(); + return true; + + } else if (str->IsExternal()) { + const v8::String::ExternalStringResource* ext; + ext = str->GetExternalStringResource(); + *data = reinterpret_cast(ext->data()); + *len = ext->length(); + return true; + } + + return false; +} + +namespace Nan { + enum Encoding {ASCII, UTF8, BASE64, UCS2, BINARY, HEX, BUFFER}; +} + +/* NAN_DEPRECATED */ NAN_INLINE void* _NanRawString( + v8::Handle from + , enum Nan::Encoding encoding + , size_t *datalen + , void *buf + , size_t buflen + , int flags +) { + NanScope(); + + size_t sz_; + size_t term_len = !(flags & v8::String::NO_NULL_TERMINATION); + char *data = NULL; + size_t len; + bool is_extern = _NanGetExternalParts( + from + , const_cast(&data) + , &len); + + if (is_extern && !term_len) { + NanSetPointerSafe(datalen, len); + return data; + } + + v8::Local toStr = from->ToString(); + + char *to = static_cast(buf); + + switch (encoding) { + case Nan::ASCII: +#if NODE_MODULE_VERSION < 0x000C + sz_ = toStr->Length(); + if (to == NULL) { + to = new char[sz_ + term_len]; + } else { + assert(buflen >= sz_ + term_len && "too small buffer"); + } + NanSetPointerSafe( + datalen + , toStr->WriteAscii(to, 0, static_cast(sz_ + term_len), flags)); + return to; +#endif + case Nan::BINARY: + case Nan::BUFFER: + sz_ = toStr->Length(); + if (to == NULL) { + to = new char[sz_ + term_len]; + } else { + assert(buflen >= sz_ + term_len && "too small buffer"); + } +#if NODE_MODULE_VERSION < 0x000C + { + uint16_t* twobytebuf = new uint16_t[sz_ + term_len]; + + size_t len = toStr->Write(twobytebuf, 0, + static_cast(sz_ + term_len), flags); + + for (size_t i = 0; i < sz_ + term_len && i < len + term_len; i++) { + unsigned char *b = reinterpret_cast(&twobytebuf[i]); + to[i] = *b; + } + + NanSetPointerSafe(datalen, len); + + delete[] twobytebuf; + return to; + } +#else + NanSetPointerSafe( + datalen, + toStr->WriteOneByte( + reinterpret_cast(to) + , 0 + , static_cast(sz_ + term_len) + , flags)); + return to; +#endif + case Nan::UTF8: + sz_ = toStr->Utf8Length(); + if (to == NULL) { + to = new char[sz_ + term_len]; + } else { + assert(buflen >= sz_ + term_len && "too small buffer"); + } + NanSetPointerSafe( + datalen + , toStr->WriteUtf8(to, static_cast(sz_ + term_len) + , NULL, flags) + - term_len); + return to; + case Nan::BASE64: + { + v8::String::Value value(toStr); + sz_ = _nan_base64_decoded_size(*value, value.length()); + if (to == NULL) { + to = new char[sz_ + term_len]; + } else { + assert(buflen >= sz_ + term_len); + } + NanSetPointerSafe( + datalen + , _nan_base64_decode(to, sz_, *value, value.length())); + if (term_len) { + to[sz_] = '\0'; + } + return to; + } + case Nan::UCS2: + { + sz_ = toStr->Length(); + if (to == NULL) { + to = new char[(sz_ + term_len) * 2]; + } else { + assert(buflen >= (sz_ + term_len) * 2 && "too small buffer"); + } + + int bc = 2 * toStr->Write( + reinterpret_cast(to) + , 0 + , static_cast(sz_ + term_len) + , flags); + NanSetPointerSafe(datalen, bc); + return to; + } + case Nan::HEX: + { + v8::String::Value value(toStr); + sz_ = value.length(); + assert(!(sz_ & 1) && "bad hex data"); + if (to == NULL) { + to = new char[sz_ / 2 + term_len]; + } else { + assert(buflen >= sz_ / 2 + term_len && "too small buffer"); + } + NanSetPointerSafe( + datalen + , _nan_hex_decode(to, sz_ / 2, *value, value.length())); + } + if (term_len) { + to[sz_ / 2] = '\0'; + } + return to; + default: + assert(0 && "unknown encoding"); + } + return to; +} + +NAN_DEPRECATED NAN_INLINE void* NanRawString( + v8::Handle from + , enum Nan::Encoding encoding + , size_t *datalen + , void *buf + , size_t buflen + , int flags +) { + return _NanRawString(from, encoding, datalen, buf, buflen, flags); +} + + +NAN_DEPRECATED NAN_INLINE char* NanCString( + v8::Handle from + , size_t *datalen + , char *buf = NULL + , size_t buflen = 0 + , int flags = v8::String::NO_OPTIONS +) { + return static_cast( + _NanRawString(from, Nan::UTF8, datalen, buf, buflen, flags) + ); +} + +NAN_INLINE void NanSetPrototypeTemplate( + v8::Local templ + , const char *name + , v8::Handle value +) { + NanSetTemplate(templ->PrototypeTemplate(), name, value); +} + +NAN_INLINE void NanSetPrototypeTemplate( + v8::Local templ + , v8::Handle name + , v8::Handle value + , v8::PropertyAttribute attributes +) { + NanSetTemplate(templ->PrototypeTemplate(), name, value, attributes); +} + +NAN_INLINE void NanSetInstanceTemplate( + v8::Local templ + , const char *name + , v8::Handle value +) { + NanSetTemplate(templ->InstanceTemplate(), name, value); +} + +NAN_INLINE void NanSetInstanceTemplate( + v8::Local templ + , v8::Handle name + , v8::Handle value + , v8::PropertyAttribute attributes +) { + NanSetTemplate(templ->InstanceTemplate(), name, value, attributes); +} + +#endif // NAN_H_ diff --git a/node_modules/mongodb/node_modules/kerberos/node_modules/nan/package.json b/node_modules/mongodb/node_modules/kerberos/node_modules/nan/package.json new file mode 100644 index 0000000..25a90e8 --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/node_modules/nan/package.json @@ -0,0 +1,79 @@ +{ + "name": "nan", + "version": "1.3.0", + "description": "Native Abstractions for Node.js: C++ header for Node 0.8->0.12 compatibility", + "main": "include_dirs.js", + "repository": { + "type": "git", + "url": "git://github.com/rvagg/nan.git" + }, + "scripts": { + "test": "tap --gc test/js/*-test.js", + "rebuild-tests": "node-gyp rebuild --directory test" + }, + "contributors": [ + { + "name": "Rod Vagg", + "email": "r@va.gg", + "url": "https://github.com/rvagg" + }, + { + "name": "Benjamin Byholm", + "email": "bbyholm@abo.fi", + "url": "https://github.com/kkoopa/" + }, + { + "name": "Trevor Norris", + "email": "trev.norris@gmail.com", + "url": "https://github.com/trevnorris" + }, + { + "name": "Nathan Rajlich", + "email": "nathan@tootallnate.net", + "url": "https://github.com/TooTallNate" + }, + { + "name": "Brett Lawson", + "email": "brett19@gmail.com", + "url": "https://github.com/brett19" + }, + { + "name": "Ben Noordhuis", + "email": "info@bnoordhuis.nl", + "url": "https://github.com/bnoordhuis" + } + ], + "devDependencies": { + "bindings": "~1.2.1", + "node-gyp": "~1.0.1", + "tap": "~0.4.12", + "xtend": "~4.0.0" + }, + "license": "MIT", + "gitHead": "e482fbe142e58373d5a24f4e5a60c61e22a13f83", + "bugs": { + "url": "https://github.com/rvagg/nan/issues" + }, + "homepage": "https://github.com/rvagg/nan", + "_id": "nan@1.3.0", + "_shasum": "9a5b8d5ef97a10df3050e59b2c362d3baf779742", + "_from": "nan@1.3.0", + "_npmVersion": "1.4.21", + "_npmUser": { + "name": "rvagg", + "email": "rod@vagg.org" + }, + "maintainers": [ + { + "name": "rvagg", + "email": "rod@vagg.org" + } + ], + "dist": { + "shasum": "9a5b8d5ef97a10df3050e59b2c362d3baf779742", + "tarball": "http://registry.npmjs.org/nan/-/nan-1.3.0.tgz" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/nan/-/nan-1.3.0.tgz", + "readme": "ERROR: No README data found!" +} diff --git a/node_modules/mongodb/node_modules/kerberos/package.json b/node_modules/mongodb/node_modules/kerberos/package.json new file mode 100644 index 0000000..8c78d94 --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/package.json @@ -0,0 +1,55 @@ +{ + "name": "kerberos", + "version": "0.0.6", + "description": "Kerberos library for Node.js", + "main": "index.js", + "repository": { + "type": "git", + "url": "https://github.com/christkv/kerberos.git" + }, + "keywords": [ + "kerberos", + "security", + "authentication" + ], + "dependencies": { + "nan": "1.3.0" + }, + "devDependencies": { + "nodeunit": "latest" + }, + "scripts": { + "install": "(node-gyp rebuild 2> builderror.log) || (exit 0)", + "test": "nodeunit ./test" + }, + "author": { + "name": "Christian Amor Kvalheim" + }, + "license": "Apache 2.0", + "gitHead": "bb01d4fe322e022999aca19da564e7d9db59a8ed", + "bugs": { + "url": "https://github.com/christkv/kerberos/issues" + }, + "homepage": "https://github.com/christkv/kerberos", + "_id": "kerberos@0.0.6", + "_shasum": "271ac4c0fd6e3162a68ff42d8d97a28fe9e161c8", + "_from": "kerberos@0.0.6", + "_npmVersion": "2.0.0", + "_npmUser": { + "name": "christkv", + "email": "christkv@gmail.com" + }, + "maintainers": [ + { + "name": "christkv", + "email": "christkv@gmail.com" + } + ], + "dist": { + "shasum": "271ac4c0fd6e3162a68ff42d8d97a28fe9e161c8", + "tarball": "http://registry.npmjs.org/kerberos/-/kerberos-0.0.6.tgz" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/kerberos/-/kerberos-0.0.6.tgz", + "readme": "ERROR: No README data found!" +} diff --git a/node_modules/mongodb/node_modules/kerberos/test/kerberos_tests.js b/node_modules/mongodb/node_modules/kerberos/test/kerberos_tests.js new file mode 100644 index 0000000..a06c5fd --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/test/kerberos_tests.js @@ -0,0 +1,34 @@ +exports.setUp = function(callback) { + callback(); +} + +exports.tearDown = function(callback) { + callback(); +} + +exports['Simple initialize of Kerberos object'] = function(test) { + var Kerberos = require('../lib/kerberos.js').Kerberos; + var kerberos = new Kerberos(); + // console.dir(kerberos) + + // Initiate kerberos client + kerberos.authGSSClientInit('mongodb@kdc.10gen.me', Kerberos.GSS_C_MUTUAL_FLAG, function(err, context) { + console.log("===================================== authGSSClientInit") + test.equal(null, err); + test.ok(context != null && typeof context == 'object'); + // console.log("===================================== authGSSClientInit") + console.dir(err) + console.dir(context) + // console.dir(typeof result) + + // Perform the first step + kerberos.authGSSClientStep(context, function(err, result) { + console.log("===================================== authGSSClientStep") + console.dir(err) + console.dir(result) + console.dir(context) + + test.done(); + }); + }); +} \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/test/kerberos_win32_test.js b/node_modules/mongodb/node_modules/kerberos/test/kerberos_win32_test.js new file mode 100644 index 0000000..d2f7046 --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/test/kerberos_win32_test.js @@ -0,0 +1,19 @@ +exports.setUp = function(callback) { + callback(); +} + +exports.tearDown = function(callback) { + callback(); +} + +exports['Simple initialize of Kerberos win32 object'] = function(test) { + var KerberosNative = require('../build/Release/kerberos').Kerberos; + // console.dir(KerberosNative) + var kerberos = new KerberosNative(); + console.log("=========================================== 0") + console.dir(kerberos.acquireAlternateCredentials("dev1@10GEN.ME", "a")); + console.log("=========================================== 1") + console.dir(kerberos.prepareOutboundPackage("mongodb/kdc.10gen.com")); + console.log("=========================================== 2") + test.done(); +} diff --git a/node_modules/mongodb/node_modules/kerberos/test/win32/security_buffer_descriptor_tests.js b/node_modules/mongodb/node_modules/kerberos/test/win32/security_buffer_descriptor_tests.js new file mode 100644 index 0000000..3531b6b --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/test/win32/security_buffer_descriptor_tests.js @@ -0,0 +1,41 @@ +exports.setUp = function(callback) { + callback(); +} + +exports.tearDown = function(callback) { + callback(); +} + +exports['Initialize a security Buffer Descriptor'] = function(test) { + var SecurityBufferDescriptor = require('../../lib/sspi.js').SecurityBufferDescriptor + SecurityBuffer = require('../../lib/sspi.js').SecurityBuffer; + + // Create descriptor with single Buffer + var securityDescriptor = new SecurityBufferDescriptor(100); + try { + // Fail to work due to no valid Security Buffer + securityDescriptor = new SecurityBufferDescriptor(["hello"]); + test.ok(false); + } catch(err){} + + // Should Correctly construct SecurityBuffer + var buffer = new SecurityBuffer(SecurityBuffer.DATA, 100); + securityDescriptor = new SecurityBufferDescriptor([buffer]); + // Should correctly return a buffer + var result = securityDescriptor.toBuffer(); + test.equal(100, result.length); + + // Should Correctly construct SecurityBuffer + var buffer = new SecurityBuffer(SecurityBuffer.DATA, new Buffer("hello world")); + securityDescriptor = new SecurityBufferDescriptor([buffer]); + var result = securityDescriptor.toBuffer(); + test.equal("hello world", result.toString()); + + // Test passing in more than one Buffer + var buffer = new SecurityBuffer(SecurityBuffer.DATA, new Buffer("hello world")); + var buffer2 = new SecurityBuffer(SecurityBuffer.STREAM, new Buffer("adam and eve")); + securityDescriptor = new SecurityBufferDescriptor([buffer, buffer2]); + var result = securityDescriptor.toBuffer(); + test.equal("hello worldadam and eve", result.toString()); + test.done(); +} \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/test/win32/security_buffer_tests.js b/node_modules/mongodb/node_modules/kerberos/test/win32/security_buffer_tests.js new file mode 100644 index 0000000..b52b959 --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/test/win32/security_buffer_tests.js @@ -0,0 +1,22 @@ +exports.setUp = function(callback) { + callback(); +} + +exports.tearDown = function(callback) { + callback(); +} + +exports['Initialize a security Buffer'] = function(test) { + var SecurityBuffer = require('../../lib/sspi.js').SecurityBuffer; + // Create empty buffer + var securityBuffer = new SecurityBuffer(SecurityBuffer.DATA, 100); + var buffer = securityBuffer.toBuffer(); + test.equal(100, buffer.length); + + // Access data passed in + var allocated_buffer = new Buffer(256); + securityBuffer = new SecurityBuffer(SecurityBuffer.DATA, allocated_buffer); + buffer = securityBuffer.toBuffer(); + test.deepEqual(allocated_buffer, buffer); + test.done(); +} \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/test/win32/security_credentials_tests.js b/node_modules/mongodb/node_modules/kerberos/test/win32/security_credentials_tests.js new file mode 100644 index 0000000..7758180 --- /dev/null +++ b/node_modules/mongodb/node_modules/kerberos/test/win32/security_credentials_tests.js @@ -0,0 +1,55 @@ +exports.setUp = function(callback) { + callback(); +} + +exports.tearDown = function(callback) { + callback(); +} + +exports['Initialize a set of security credentials'] = function(test) { + var SecurityCredentials = require('../../lib/sspi.js').SecurityCredentials; + + // Aquire some credentials + try { + var credentials = SecurityCredentials.aquire('Kerberos', 'dev1@10GEN.ME', 'a'); + } catch(err) { + console.dir(err) + test.ok(false); + } + + + + // console.dir(SecurityCredentials); + + // var SecurityBufferDescriptor = require('../../lib/sspi.js').SecurityBufferDescriptor + // SecurityBuffer = require('../../lib/sspi.js').SecurityBuffer; + + // // Create descriptor with single Buffer + // var securityDescriptor = new SecurityBufferDescriptor(100); + // try { + // // Fail to work due to no valid Security Buffer + // securityDescriptor = new SecurityBufferDescriptor(["hello"]); + // test.ok(false); + // } catch(err){} + + // // Should Correctly construct SecurityBuffer + // var buffer = new SecurityBuffer(SecurityBuffer.DATA, 100); + // securityDescriptor = new SecurityBufferDescriptor([buffer]); + // // Should correctly return a buffer + // var result = securityDescriptor.toBuffer(); + // test.equal(100, result.length); + + // // Should Correctly construct SecurityBuffer + // var buffer = new SecurityBuffer(SecurityBuffer.DATA, new Buffer("hello world")); + // securityDescriptor = new SecurityBufferDescriptor([buffer]); + // var result = securityDescriptor.toBuffer(); + // test.equal("hello world", result.toString()); + + // // Test passing in more than one Buffer + // var buffer = new SecurityBuffer(SecurityBuffer.DATA, new Buffer("hello world")); + // var buffer2 = new SecurityBuffer(SecurityBuffer.STREAM, new Buffer("adam and eve")); + // securityDescriptor = new SecurityBufferDescriptor([buffer, buffer2]); + // var result = securityDescriptor.toBuffer(); + // test.equal("hello worldadam and eve", result.toString()); + test.done(); +} \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/readable-stream/.npmignore b/node_modules/mongodb/node_modules/readable-stream/.npmignore new file mode 100644 index 0000000..38344f8 --- /dev/null +++ b/node_modules/mongodb/node_modules/readable-stream/.npmignore @@ -0,0 +1,5 @@ +build/ +test/ +examples/ +fs.js +zlib.js \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/readable-stream/LICENSE b/node_modules/mongodb/node_modules/readable-stream/LICENSE new file mode 100644 index 0000000..e3d4e69 --- /dev/null +++ b/node_modules/mongodb/node_modules/readable-stream/LICENSE @@ -0,0 +1,18 @@ +Copyright Joyent, Inc. and other Node 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/mongodb/node_modules/readable-stream/README.md b/node_modules/mongodb/node_modules/readable-stream/README.md new file mode 100644 index 0000000..3fb3e80 --- /dev/null +++ b/node_modules/mongodb/node_modules/readable-stream/README.md @@ -0,0 +1,15 @@ +# readable-stream + +***Node-core streams for userland*** + +[![NPM](https://nodei.co/npm/readable-stream.png?downloads=true&downloadRank=true)](https://nodei.co/npm/readable-stream/) +[![NPM](https://nodei.co/npm-dl/readable-stream.png?&months=6&height=3)](https://nodei.co/npm/readable-stream/) + +This package is a mirror of the Streams2 and Streams3 implementations in Node-core. + +If you want to guarantee a stable streams base, regardless of what version of Node you, or the users of your libraries are using, use **readable-stream** *only* and avoid the *"stream"* module in Node-core. + +**readable-stream** comes in two major versions, v1.0.x and v1.1.x. The former tracks the Streams2 implementation in Node 0.10, including bug-fixes and minor improvements as they are added. The latter tracks Streams3 as it develops in Node 0.11; we will likely see a v1.2.x branch for Node 0.12. + +**readable-stream** uses proper patch-level versioning so if you pin to `"~1.0.0"` you’ll get the latest Node 0.10 Streams2 implementation, including any fixes and minor non-breaking improvements. The patch-level versions of 1.0.x and 1.1.x should mirror the patch-level versions of Node-core releases. You should prefer the **1.0.x** releases for now and when you’re ready to start using Streams3, pin to `"~1.1.0"` + diff --git a/node_modules/mongodb/node_modules/readable-stream/duplex.js b/node_modules/mongodb/node_modules/readable-stream/duplex.js new file mode 100644 index 0000000..ca807af --- /dev/null +++ b/node_modules/mongodb/node_modules/readable-stream/duplex.js @@ -0,0 +1 @@ +module.exports = require("./lib/_stream_duplex.js") diff --git a/node_modules/mongodb/node_modules/readable-stream/lib/_stream_duplex.js b/node_modules/mongodb/node_modules/readable-stream/lib/_stream_duplex.js new file mode 100644 index 0000000..b513d61 --- /dev/null +++ b/node_modules/mongodb/node_modules/readable-stream/lib/_stream_duplex.js @@ -0,0 +1,89 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a duplex stream is just a stream that is both readable and writable. +// Since JS doesn't have multiple prototypal inheritance, this class +// prototypally inherits from Readable, and then parasitically from +// Writable. + +module.exports = Duplex; + +/**/ +var objectKeys = Object.keys || function (obj) { + var keys = []; + for (var key in obj) keys.push(key); + return keys; +} +/**/ + + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +var Readable = require('./_stream_readable'); +var Writable = require('./_stream_writable'); + +util.inherits(Duplex, Readable); + +forEach(objectKeys(Writable.prototype), function(method) { + if (!Duplex.prototype[method]) + Duplex.prototype[method] = Writable.prototype[method]; +}); + +function Duplex(options) { + if (!(this instanceof Duplex)) + return new Duplex(options); + + Readable.call(this, options); + Writable.call(this, options); + + if (options && options.readable === false) + this.readable = false; + + if (options && options.writable === false) + this.writable = false; + + this.allowHalfOpen = true; + if (options && options.allowHalfOpen === false) + this.allowHalfOpen = false; + + this.once('end', onend); +} + +// the no-half-open enforcer +function onend() { + // if we allow half-open state, or if the writable side ended, + // then we're ok. + if (this.allowHalfOpen || this._writableState.ended) + return; + + // no more data can be written. + // But allow more writes to happen in this tick. + process.nextTick(this.end.bind(this)); +} + +function forEach (xs, f) { + for (var i = 0, l = xs.length; i < l; i++) { + f(xs[i], i); + } +} diff --git a/node_modules/mongodb/node_modules/readable-stream/lib/_stream_passthrough.js b/node_modules/mongodb/node_modules/readable-stream/lib/_stream_passthrough.js new file mode 100644 index 0000000..895ca50 --- /dev/null +++ b/node_modules/mongodb/node_modules/readable-stream/lib/_stream_passthrough.js @@ -0,0 +1,46 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a passthrough stream. +// basically just the most minimal sort of Transform stream. +// Every written chunk gets output as-is. + +module.exports = PassThrough; + +var Transform = require('./_stream_transform'); + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +util.inherits(PassThrough, Transform); + +function PassThrough(options) { + if (!(this instanceof PassThrough)) + return new PassThrough(options); + + Transform.call(this, options); +} + +PassThrough.prototype._transform = function(chunk, encoding, cb) { + cb(null, chunk); +}; diff --git a/node_modules/mongodb/node_modules/readable-stream/lib/_stream_readable.js b/node_modules/mongodb/node_modules/readable-stream/lib/_stream_readable.js new file mode 100644 index 0000000..6307220 --- /dev/null +++ b/node_modules/mongodb/node_modules/readable-stream/lib/_stream_readable.js @@ -0,0 +1,982 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +module.exports = Readable; + +/**/ +var isArray = require('isarray'); +/**/ + + +/**/ +var Buffer = require('buffer').Buffer; +/**/ + +Readable.ReadableState = ReadableState; + +var EE = require('events').EventEmitter; + +/**/ +if (!EE.listenerCount) EE.listenerCount = function(emitter, type) { + return emitter.listeners(type).length; +}; +/**/ + +var Stream = require('stream'); + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +var StringDecoder; + +util.inherits(Readable, Stream); + +function ReadableState(options, stream) { + options = options || {}; + + // the point at which it stops calling _read() to fill the buffer + // Note: 0 is a valid value, means "don't call _read preemptively ever" + var hwm = options.highWaterMark; + this.highWaterMark = (hwm || hwm === 0) ? hwm : 16 * 1024; + + // cast to ints. + this.highWaterMark = ~~this.highWaterMark; + + this.buffer = []; + this.length = 0; + this.pipes = null; + this.pipesCount = 0; + this.flowing = false; + this.ended = false; + this.endEmitted = false; + this.reading = false; + + // In streams that never have any data, and do push(null) right away, + // the consumer can miss the 'end' event if they do some I/O before + // consuming the stream. So, we don't emit('end') until some reading + // happens. + this.calledRead = false; + + // a flag to be able to tell if the onwrite cb is called immediately, + // or on a later tick. We set this to true at first, becuase any + // actions that shouldn't happen until "later" should generally also + // not happen before the first write call. + this.sync = true; + + // whenever we return null, then we set a flag to say + // that we're awaiting a 'readable' event emission. + this.needReadable = false; + this.emittedReadable = false; + this.readableListening = false; + + + // object stream flag. Used to make read(n) ignore n and to + // make all the buffer merging and length checks go away + this.objectMode = !!options.objectMode; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // when piping, we only care about 'readable' events that happen + // after read()ing all the bytes and not getting any pushback. + this.ranOut = false; + + // the number of writers that are awaiting a drain event in .pipe()s + this.awaitDrain = 0; + + // if true, a maybeReadMore has been scheduled + this.readingMore = false; + + this.decoder = null; + this.encoding = null; + if (options.encoding) { + if (!StringDecoder) + StringDecoder = require('string_decoder/').StringDecoder; + this.decoder = new StringDecoder(options.encoding); + this.encoding = options.encoding; + } +} + +function Readable(options) { + if (!(this instanceof Readable)) + return new Readable(options); + + this._readableState = new ReadableState(options, this); + + // legacy + this.readable = true; + + Stream.call(this); +} + +// Manually shove something into the read() buffer. +// This returns true if the highWaterMark has not been hit yet, +// similar to how Writable.write() returns true if you should +// write() some more. +Readable.prototype.push = function(chunk, encoding) { + var state = this._readableState; + + if (typeof chunk === 'string' && !state.objectMode) { + encoding = encoding || state.defaultEncoding; + if (encoding !== state.encoding) { + chunk = new Buffer(chunk, encoding); + encoding = ''; + } + } + + return readableAddChunk(this, state, chunk, encoding, false); +}; + +// Unshift should *always* be something directly out of read() +Readable.prototype.unshift = function(chunk) { + var state = this._readableState; + return readableAddChunk(this, state, chunk, '', true); +}; + +function readableAddChunk(stream, state, chunk, encoding, addToFront) { + var er = chunkInvalid(state, chunk); + if (er) { + stream.emit('error', er); + } else if (chunk === null || chunk === undefined) { + state.reading = false; + if (!state.ended) + onEofChunk(stream, state); + } else if (state.objectMode || chunk && chunk.length > 0) { + if (state.ended && !addToFront) { + var e = new Error('stream.push() after EOF'); + stream.emit('error', e); + } else if (state.endEmitted && addToFront) { + var e = new Error('stream.unshift() after end event'); + stream.emit('error', e); + } else { + if (state.decoder && !addToFront && !encoding) + chunk = state.decoder.write(chunk); + + // update the buffer info. + state.length += state.objectMode ? 1 : chunk.length; + if (addToFront) { + state.buffer.unshift(chunk); + } else { + state.reading = false; + state.buffer.push(chunk); + } + + if (state.needReadable) + emitReadable(stream); + + maybeReadMore(stream, state); + } + } else if (!addToFront) { + state.reading = false; + } + + return needMoreData(state); +} + + + +// if it's past the high water mark, we can push in some more. +// Also, if we have no data yet, we can stand some +// more bytes. This is to work around cases where hwm=0, +// such as the repl. Also, if the push() triggered a +// readable event, and the user called read(largeNumber) such that +// needReadable was set, then we ought to push more, so that another +// 'readable' event will be triggered. +function needMoreData(state) { + return !state.ended && + (state.needReadable || + state.length < state.highWaterMark || + state.length === 0); +} + +// backwards compatibility. +Readable.prototype.setEncoding = function(enc) { + if (!StringDecoder) + StringDecoder = require('string_decoder/').StringDecoder; + this._readableState.decoder = new StringDecoder(enc); + this._readableState.encoding = enc; +}; + +// Don't raise the hwm > 128MB +var MAX_HWM = 0x800000; +function roundUpToNextPowerOf2(n) { + if (n >= MAX_HWM) { + n = MAX_HWM; + } else { + // Get the next highest power of 2 + n--; + for (var p = 1; p < 32; p <<= 1) n |= n >> p; + n++; + } + return n; +} + +function howMuchToRead(n, state) { + if (state.length === 0 && state.ended) + return 0; + + if (state.objectMode) + return n === 0 ? 0 : 1; + + if (n === null || isNaN(n)) { + // only flow one buffer at a time + if (state.flowing && state.buffer.length) + return state.buffer[0].length; + else + return state.length; + } + + if (n <= 0) + return 0; + + // If we're asking for more than the target buffer level, + // then raise the water mark. Bump up to the next highest + // power of 2, to prevent increasing it excessively in tiny + // amounts. + if (n > state.highWaterMark) + state.highWaterMark = roundUpToNextPowerOf2(n); + + // don't have that much. return null, unless we've ended. + if (n > state.length) { + if (!state.ended) { + state.needReadable = true; + return 0; + } else + return state.length; + } + + return n; +} + +// you can override either this method, or the async _read(n) below. +Readable.prototype.read = function(n) { + var state = this._readableState; + state.calledRead = true; + var nOrig = n; + var ret; + + if (typeof n !== 'number' || n > 0) + state.emittedReadable = false; + + // if we're doing read(0) to trigger a readable event, but we + // already have a bunch of data in the buffer, then just trigger + // the 'readable' event and move on. + if (n === 0 && + state.needReadable && + (state.length >= state.highWaterMark || state.ended)) { + emitReadable(this); + return null; + } + + n = howMuchToRead(n, state); + + // if we've ended, and we're now clear, then finish it up. + if (n === 0 && state.ended) { + ret = null; + + // In cases where the decoder did not receive enough data + // to produce a full chunk, then immediately received an + // EOF, state.buffer will contain [, ]. + // howMuchToRead will see this and coerce the amount to + // read to zero (because it's looking at the length of the + // first in state.buffer), and we'll end up here. + // + // This can only happen via state.decoder -- no other venue + // exists for pushing a zero-length chunk into state.buffer + // and triggering this behavior. In this case, we return our + // remaining data and end the stream, if appropriate. + if (state.length > 0 && state.decoder) { + ret = fromList(n, state); + state.length -= ret.length; + } + + if (state.length === 0) + endReadable(this); + + return ret; + } + + // All the actual chunk generation logic needs to be + // *below* the call to _read. The reason is that in certain + // synthetic stream cases, such as passthrough streams, _read + // may be a completely synchronous operation which may change + // the state of the read buffer, providing enough data when + // before there was *not* enough. + // + // So, the steps are: + // 1. Figure out what the state of things will be after we do + // a read from the buffer. + // + // 2. If that resulting state will trigger a _read, then call _read. + // Note that this may be asynchronous, or synchronous. Yes, it is + // deeply ugly to write APIs this way, but that still doesn't mean + // that the Readable class should behave improperly, as streams are + // designed to be sync/async agnostic. + // Take note if the _read call is sync or async (ie, if the read call + // has returned yet), so that we know whether or not it's safe to emit + // 'readable' etc. + // + // 3. Actually pull the requested chunks out of the buffer and return. + + // if we need a readable event, then we need to do some reading. + var doRead = state.needReadable; + + // if we currently have less than the highWaterMark, then also read some + if (state.length - n <= state.highWaterMark) + doRead = true; + + // however, if we've ended, then there's no point, and if we're already + // reading, then it's unnecessary. + if (state.ended || state.reading) + doRead = false; + + if (doRead) { + state.reading = true; + state.sync = true; + // if the length is currently zero, then we *need* a readable event. + if (state.length === 0) + state.needReadable = true; + // call internal read method + this._read(state.highWaterMark); + state.sync = false; + } + + // If _read called its callback synchronously, then `reading` + // will be false, and we need to re-evaluate how much data we + // can return to the user. + if (doRead && !state.reading) + n = howMuchToRead(nOrig, state); + + if (n > 0) + ret = fromList(n, state); + else + ret = null; + + if (ret === null) { + state.needReadable = true; + n = 0; + } + + state.length -= n; + + // If we have nothing in the buffer, then we want to know + // as soon as we *do* get something into the buffer. + if (state.length === 0 && !state.ended) + state.needReadable = true; + + // If we happened to read() exactly the remaining amount in the + // buffer, and the EOF has been seen at this point, then make sure + // that we emit 'end' on the very next tick. + if (state.ended && !state.endEmitted && state.length === 0) + endReadable(this); + + return ret; +}; + +function chunkInvalid(state, chunk) { + var er = null; + if (!Buffer.isBuffer(chunk) && + 'string' !== typeof chunk && + chunk !== null && + chunk !== undefined && + !state.objectMode) { + er = new TypeError('Invalid non-string/buffer chunk'); + } + return er; +} + + +function onEofChunk(stream, state) { + if (state.decoder && !state.ended) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) { + state.buffer.push(chunk); + state.length += state.objectMode ? 1 : chunk.length; + } + } + state.ended = true; + + // if we've ended and we have some data left, then emit + // 'readable' now to make sure it gets picked up. + if (state.length > 0) + emitReadable(stream); + else + endReadable(stream); +} + +// Don't emit readable right away in sync mode, because this can trigger +// another read() call => stack overflow. This way, it might trigger +// a nextTick recursion warning, but that's not so bad. +function emitReadable(stream) { + var state = stream._readableState; + state.needReadable = false; + if (state.emittedReadable) + return; + + state.emittedReadable = true; + if (state.sync) + process.nextTick(function() { + emitReadable_(stream); + }); + else + emitReadable_(stream); +} + +function emitReadable_(stream) { + stream.emit('readable'); +} + + +// at this point, the user has presumably seen the 'readable' event, +// and called read() to consume some data. that may have triggered +// in turn another _read(n) call, in which case reading = true if +// it's in progress. +// However, if we're not ended, or reading, and the length < hwm, +// then go ahead and try to read some more preemptively. +function maybeReadMore(stream, state) { + if (!state.readingMore) { + state.readingMore = true; + process.nextTick(function() { + maybeReadMore_(stream, state); + }); + } +} + +function maybeReadMore_(stream, state) { + var len = state.length; + while (!state.reading && !state.flowing && !state.ended && + state.length < state.highWaterMark) { + stream.read(0); + if (len === state.length) + // didn't get any data, stop spinning. + break; + else + len = state.length; + } + state.readingMore = false; +} + +// abstract method. to be overridden in specific implementation classes. +// call cb(er, data) where data is <= n in length. +// for virtual (non-string, non-buffer) streams, "length" is somewhat +// arbitrary, and perhaps not very meaningful. +Readable.prototype._read = function(n) { + this.emit('error', new Error('not implemented')); +}; + +Readable.prototype.pipe = function(dest, pipeOpts) { + var src = this; + var state = this._readableState; + + switch (state.pipesCount) { + case 0: + state.pipes = dest; + break; + case 1: + state.pipes = [state.pipes, dest]; + break; + default: + state.pipes.push(dest); + break; + } + state.pipesCount += 1; + + var doEnd = (!pipeOpts || pipeOpts.end !== false) && + dest !== process.stdout && + dest !== process.stderr; + + var endFn = doEnd ? onend : cleanup; + if (state.endEmitted) + process.nextTick(endFn); + else + src.once('end', endFn); + + dest.on('unpipe', onunpipe); + function onunpipe(readable) { + if (readable !== src) return; + cleanup(); + } + + function onend() { + dest.end(); + } + + // when the dest drains, it reduces the awaitDrain counter + // on the source. This would be more elegant with a .once() + // handler in flow(), but adding and removing repeatedly is + // too slow. + var ondrain = pipeOnDrain(src); + dest.on('drain', ondrain); + + function cleanup() { + // cleanup event handlers once the pipe is broken + dest.removeListener('close', onclose); + dest.removeListener('finish', onfinish); + dest.removeListener('drain', ondrain); + dest.removeListener('error', onerror); + dest.removeListener('unpipe', onunpipe); + src.removeListener('end', onend); + src.removeListener('end', cleanup); + + // if the reader is waiting for a drain event from this + // specific writer, then it would cause it to never start + // flowing again. + // So, if this is awaiting a drain, then we just call it now. + // If we don't know, then assume that we are waiting for one. + if (!dest._writableState || dest._writableState.needDrain) + ondrain(); + } + + // if the dest has an error, then stop piping into it. + // however, don't suppress the throwing behavior for this. + function onerror(er) { + unpipe(); + dest.removeListener('error', onerror); + if (EE.listenerCount(dest, 'error') === 0) + dest.emit('error', er); + } + // This is a brutally ugly hack to make sure that our error handler + // is attached before any userland ones. NEVER DO THIS. + if (!dest._events || !dest._events.error) + dest.on('error', onerror); + else if (isArray(dest._events.error)) + dest._events.error.unshift(onerror); + else + dest._events.error = [onerror, dest._events.error]; + + + + // Both close and finish should trigger unpipe, but only once. + function onclose() { + dest.removeListener('finish', onfinish); + unpipe(); + } + dest.once('close', onclose); + function onfinish() { + dest.removeListener('close', onclose); + unpipe(); + } + dest.once('finish', onfinish); + + function unpipe() { + src.unpipe(dest); + } + + // tell the dest that it's being piped to + dest.emit('pipe', src); + + // start the flow if it hasn't been started already. + if (!state.flowing) { + // the handler that waits for readable events after all + // the data gets sucked out in flow. + // This would be easier to follow with a .once() handler + // in flow(), but that is too slow. + this.on('readable', pipeOnReadable); + + state.flowing = true; + process.nextTick(function() { + flow(src); + }); + } + + return dest; +}; + +function pipeOnDrain(src) { + return function() { + var dest = this; + var state = src._readableState; + state.awaitDrain--; + if (state.awaitDrain === 0) + flow(src); + }; +} + +function flow(src) { + var state = src._readableState; + var chunk; + state.awaitDrain = 0; + + function write(dest, i, list) { + var written = dest.write(chunk); + if (false === written) { + state.awaitDrain++; + } + } + + while (state.pipesCount && null !== (chunk = src.read())) { + + if (state.pipesCount === 1) + write(state.pipes, 0, null); + else + forEach(state.pipes, write); + + src.emit('data', chunk); + + // if anyone needs a drain, then we have to wait for that. + if (state.awaitDrain > 0) + return; + } + + // if every destination was unpiped, either before entering this + // function, or in the while loop, then stop flowing. + // + // NB: This is a pretty rare edge case. + if (state.pipesCount === 0) { + state.flowing = false; + + // if there were data event listeners added, then switch to old mode. + if (EE.listenerCount(src, 'data') > 0) + emitDataEvents(src); + return; + } + + // at this point, no one needed a drain, so we just ran out of data + // on the next readable event, start it over again. + state.ranOut = true; +} + +function pipeOnReadable() { + if (this._readableState.ranOut) { + this._readableState.ranOut = false; + flow(this); + } +} + + +Readable.prototype.unpipe = function(dest) { + var state = this._readableState; + + // if we're not piping anywhere, then do nothing. + if (state.pipesCount === 0) + return this; + + // just one destination. most common case. + if (state.pipesCount === 1) { + // passed in one, but it's not the right one. + if (dest && dest !== state.pipes) + return this; + + if (!dest) + dest = state.pipes; + + // got a match. + state.pipes = null; + state.pipesCount = 0; + this.removeListener('readable', pipeOnReadable); + state.flowing = false; + if (dest) + dest.emit('unpipe', this); + return this; + } + + // slow case. multiple pipe destinations. + + if (!dest) { + // remove all. + var dests = state.pipes; + var len = state.pipesCount; + state.pipes = null; + state.pipesCount = 0; + this.removeListener('readable', pipeOnReadable); + state.flowing = false; + + for (var i = 0; i < len; i++) + dests[i].emit('unpipe', this); + return this; + } + + // try to find the right one. + var i = indexOf(state.pipes, dest); + if (i === -1) + return this; + + state.pipes.splice(i, 1); + state.pipesCount -= 1; + if (state.pipesCount === 1) + state.pipes = state.pipes[0]; + + dest.emit('unpipe', this); + + return this; +}; + +// set up data events if they are asked for +// Ensure readable listeners eventually get something +Readable.prototype.on = function(ev, fn) { + var res = Stream.prototype.on.call(this, ev, fn); + + if (ev === 'data' && !this._readableState.flowing) + emitDataEvents(this); + + if (ev === 'readable' && this.readable) { + var state = this._readableState; + if (!state.readableListening) { + state.readableListening = true; + state.emittedReadable = false; + state.needReadable = true; + if (!state.reading) { + this.read(0); + } else if (state.length) { + emitReadable(this, state); + } + } + } + + return res; +}; +Readable.prototype.addListener = Readable.prototype.on; + +// pause() and resume() are remnants of the legacy readable stream API +// If the user uses them, then switch into old mode. +Readable.prototype.resume = function() { + emitDataEvents(this); + this.read(0); + this.emit('resume'); +}; + +Readable.prototype.pause = function() { + emitDataEvents(this, true); + this.emit('pause'); +}; + +function emitDataEvents(stream, startPaused) { + var state = stream._readableState; + + if (state.flowing) { + // https://github.com/isaacs/readable-stream/issues/16 + throw new Error('Cannot switch to old mode now.'); + } + + var paused = startPaused || false; + var readable = false; + + // convert to an old-style stream. + stream.readable = true; + stream.pipe = Stream.prototype.pipe; + stream.on = stream.addListener = Stream.prototype.on; + + stream.on('readable', function() { + readable = true; + + var c; + while (!paused && (null !== (c = stream.read()))) + stream.emit('data', c); + + if (c === null) { + readable = false; + stream._readableState.needReadable = true; + } + }); + + stream.pause = function() { + paused = true; + this.emit('pause'); + }; + + stream.resume = function() { + paused = false; + if (readable) + process.nextTick(function() { + stream.emit('readable'); + }); + else + this.read(0); + this.emit('resume'); + }; + + // now make it start, just in case it hadn't already. + stream.emit('readable'); +} + +// wrap an old-style stream as the async data source. +// This is *not* part of the readable stream interface. +// It is an ugly unfortunate mess of history. +Readable.prototype.wrap = function(stream) { + var state = this._readableState; + var paused = false; + + var self = this; + stream.on('end', function() { + if (state.decoder && !state.ended) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) + self.push(chunk); + } + + self.push(null); + }); + + stream.on('data', function(chunk) { + if (state.decoder) + chunk = state.decoder.write(chunk); + + // don't skip over falsy values in objectMode + //if (state.objectMode && util.isNullOrUndefined(chunk)) + if (state.objectMode && (chunk === null || chunk === undefined)) + return; + else if (!state.objectMode && (!chunk || !chunk.length)) + return; + + var ret = self.push(chunk); + if (!ret) { + paused = true; + stream.pause(); + } + }); + + // proxy all the other methods. + // important when wrapping filters and duplexes. + for (var i in stream) { + if (typeof stream[i] === 'function' && + typeof this[i] === 'undefined') { + this[i] = function(method) { return function() { + return stream[method].apply(stream, arguments); + }}(i); + } + } + + // proxy certain important events. + var events = ['error', 'close', 'destroy', 'pause', 'resume']; + forEach(events, function(ev) { + stream.on(ev, self.emit.bind(self, ev)); + }); + + // when we try to consume some more bytes, simply unpause the + // underlying stream. + self._read = function(n) { + if (paused) { + paused = false; + stream.resume(); + } + }; + + return self; +}; + + + +// exposed for testing purposes only. +Readable._fromList = fromList; + +// Pluck off n bytes from an array of buffers. +// Length is the combined lengths of all the buffers in the list. +function fromList(n, state) { + var list = state.buffer; + var length = state.length; + var stringMode = !!state.decoder; + var objectMode = !!state.objectMode; + var ret; + + // nothing in the list, definitely empty. + if (list.length === 0) + return null; + + if (length === 0) + ret = null; + else if (objectMode) + ret = list.shift(); + else if (!n || n >= length) { + // read it all, truncate the array. + if (stringMode) + ret = list.join(''); + else + ret = Buffer.concat(list, length); + list.length = 0; + } else { + // read just some of it. + if (n < list[0].length) { + // just take a part of the first list item. + // slice is the same for buffers and strings. + var buf = list[0]; + ret = buf.slice(0, n); + list[0] = buf.slice(n); + } else if (n === list[0].length) { + // first list is a perfect match + ret = list.shift(); + } else { + // complex case. + // we have enough to cover it, but it spans past the first buffer. + if (stringMode) + ret = ''; + else + ret = new Buffer(n); + + var c = 0; + for (var i = 0, l = list.length; i < l && c < n; i++) { + var buf = list[0]; + var cpy = Math.min(n - c, buf.length); + + if (stringMode) + ret += buf.slice(0, cpy); + else + buf.copy(ret, c, 0, cpy); + + if (cpy < buf.length) + list[0] = buf.slice(cpy); + else + list.shift(); + + c += cpy; + } + } + } + + return ret; +} + +function endReadable(stream) { + var state = stream._readableState; + + // If we get here before consuming all the bytes, then that is a + // bug in node. Should never happen. + if (state.length > 0) + throw new Error('endReadable called on non-empty stream'); + + if (!state.endEmitted && state.calledRead) { + state.ended = true; + process.nextTick(function() { + // Check that we didn't get one last unshift. + if (!state.endEmitted && state.length === 0) { + state.endEmitted = true; + stream.readable = false; + stream.emit('end'); + } + }); + } +} + +function forEach (xs, f) { + for (var i = 0, l = xs.length; i < l; i++) { + f(xs[i], i); + } +} + +function indexOf (xs, x) { + for (var i = 0, l = xs.length; i < l; i++) { + if (xs[i] === x) return i; + } + return -1; +} diff --git a/node_modules/mongodb/node_modules/readable-stream/lib/_stream_transform.js b/node_modules/mongodb/node_modules/readable-stream/lib/_stream_transform.js new file mode 100644 index 0000000..eb188df --- /dev/null +++ b/node_modules/mongodb/node_modules/readable-stream/lib/_stream_transform.js @@ -0,0 +1,210 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + + +// a transform stream is a readable/writable stream where you do +// something with the data. Sometimes it's called a "filter", +// but that's not a great name for it, since that implies a thing where +// some bits pass through, and others are simply ignored. (That would +// be a valid example of a transform, of course.) +// +// While the output is causally related to the input, it's not a +// necessarily symmetric or synchronous transformation. For example, +// a zlib stream might take multiple plain-text writes(), and then +// emit a single compressed chunk some time in the future. +// +// Here's how this works: +// +// The Transform stream has all the aspects of the readable and writable +// stream classes. When you write(chunk), that calls _write(chunk,cb) +// internally, and returns false if there's a lot of pending writes +// buffered up. When you call read(), that calls _read(n) until +// there's enough pending readable data buffered up. +// +// In a transform stream, the written data is placed in a buffer. When +// _read(n) is called, it transforms the queued up data, calling the +// buffered _write cb's as it consumes chunks. If consuming a single +// written chunk would result in multiple output chunks, then the first +// outputted bit calls the readcb, and subsequent chunks just go into +// the read buffer, and will cause it to emit 'readable' if necessary. +// +// This way, back-pressure is actually determined by the reading side, +// since _read has to be called to start processing a new chunk. However, +// a pathological inflate type of transform can cause excessive buffering +// here. For example, imagine a stream where every byte of input is +// interpreted as an integer from 0-255, and then results in that many +// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in +// 1kb of data being output. In this case, you could write a very small +// amount of input, and end up with a very large amount of output. In +// such a pathological inflating mechanism, there'd be no way to tell +// the system to stop doing the transform. A single 4MB write could +// cause the system to run out of memory. +// +// However, even in such a pathological case, only a single written chunk +// would be consumed, and then the rest would wait (un-transformed) until +// the results of the previous transformed chunk were consumed. + +module.exports = Transform; + +var Duplex = require('./_stream_duplex'); + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +util.inherits(Transform, Duplex); + + +function TransformState(options, stream) { + this.afterTransform = function(er, data) { + return afterTransform(stream, er, data); + }; + + this.needTransform = false; + this.transforming = false; + this.writecb = null; + this.writechunk = null; +} + +function afterTransform(stream, er, data) { + var ts = stream._transformState; + ts.transforming = false; + + var cb = ts.writecb; + + if (!cb) + return stream.emit('error', new Error('no writecb in Transform class')); + + ts.writechunk = null; + ts.writecb = null; + + if (data !== null && data !== undefined) + stream.push(data); + + if (cb) + cb(er); + + var rs = stream._readableState; + rs.reading = false; + if (rs.needReadable || rs.length < rs.highWaterMark) { + stream._read(rs.highWaterMark); + } +} + + +function Transform(options) { + if (!(this instanceof Transform)) + return new Transform(options); + + Duplex.call(this, options); + + var ts = this._transformState = new TransformState(options, this); + + // when the writable side finishes, then flush out anything remaining. + var stream = this; + + // start out asking for a readable event once data is transformed. + this._readableState.needReadable = true; + + // we have implemented the _read method, and done the other things + // that Readable wants before the first _read call, so unset the + // sync guard flag. + this._readableState.sync = false; + + this.once('finish', function() { + if ('function' === typeof this._flush) + this._flush(function(er) { + done(stream, er); + }); + else + done(stream); + }); +} + +Transform.prototype.push = function(chunk, encoding) { + this._transformState.needTransform = false; + return Duplex.prototype.push.call(this, chunk, encoding); +}; + +// This is the part where you do stuff! +// override this function in implementation classes. +// 'chunk' is an input chunk. +// +// Call `push(newChunk)` to pass along transformed output +// to the readable side. You may call 'push' zero or more times. +// +// Call `cb(err)` when you are done with this chunk. If you pass +// an error, then that'll put the hurt on the whole operation. If you +// never call cb(), then you'll never get another chunk. +Transform.prototype._transform = function(chunk, encoding, cb) { + throw new Error('not implemented'); +}; + +Transform.prototype._write = function(chunk, encoding, cb) { + var ts = this._transformState; + ts.writecb = cb; + ts.writechunk = chunk; + ts.writeencoding = encoding; + if (!ts.transforming) { + var rs = this._readableState; + if (ts.needTransform || + rs.needReadable || + rs.length < rs.highWaterMark) + this._read(rs.highWaterMark); + } +}; + +// Doesn't matter what the args are here. +// _transform does all the work. +// That we got here means that the readable side wants more data. +Transform.prototype._read = function(n) { + var ts = this._transformState; + + if (ts.writechunk !== null && ts.writecb && !ts.transforming) { + ts.transforming = true; + this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform); + } else { + // mark that we need a transform, so that any data that comes in + // will get processed, now that we've asked for it. + ts.needTransform = true; + } +}; + + +function done(stream, er) { + if (er) + return stream.emit('error', er); + + // if there's nothing in the write buffer, then that means + // that nothing more will ever be provided + var ws = stream._writableState; + var rs = stream._readableState; + var ts = stream._transformState; + + if (ws.length) + throw new Error('calling transform done when ws.length != 0'); + + if (ts.transforming) + throw new Error('calling transform done when still transforming'); + + return stream.push(null); +} diff --git a/node_modules/mongodb/node_modules/readable-stream/lib/_stream_writable.js b/node_modules/mongodb/node_modules/readable-stream/lib/_stream_writable.js new file mode 100644 index 0000000..4bdaa4f --- /dev/null +++ b/node_modules/mongodb/node_modules/readable-stream/lib/_stream_writable.js @@ -0,0 +1,386 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// A bit simpler than readable streams. +// Implement an async ._write(chunk, cb), and it'll handle all +// the drain event emission and buffering. + +module.exports = Writable; + +/**/ +var Buffer = require('buffer').Buffer; +/**/ + +Writable.WritableState = WritableState; + + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +var Stream = require('stream'); + +util.inherits(Writable, Stream); + +function WriteReq(chunk, encoding, cb) { + this.chunk = chunk; + this.encoding = encoding; + this.callback = cb; +} + +function WritableState(options, stream) { + options = options || {}; + + // the point at which write() starts returning false + // Note: 0 is a valid value, means that we always return false if + // the entire buffer is not flushed immediately on write() + var hwm = options.highWaterMark; + this.highWaterMark = (hwm || hwm === 0) ? hwm : 16 * 1024; + + // object stream flag to indicate whether or not this stream + // contains buffers or objects. + this.objectMode = !!options.objectMode; + + // cast to ints. + this.highWaterMark = ~~this.highWaterMark; + + this.needDrain = false; + // at the start of calling end() + this.ending = false; + // when end() has been called, and returned + this.ended = false; + // when 'finish' is emitted + this.finished = false; + + // should we decode strings into buffers before passing to _write? + // this is here so that some node-core streams can optimize string + // handling at a lower level. + var noDecode = options.decodeStrings === false; + this.decodeStrings = !noDecode; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // not an actual buffer we keep track of, but a measurement + // of how much we're waiting to get pushed to some underlying + // socket or file. + this.length = 0; + + // a flag to see when we're in the middle of a write. + this.writing = false; + + // a flag to be able to tell if the onwrite cb is called immediately, + // or on a later tick. We set this to true at first, becuase any + // actions that shouldn't happen until "later" should generally also + // not happen before the first write call. + this.sync = true; + + // a flag to know if we're processing previously buffered items, which + // may call the _write() callback in the same tick, so that we don't + // end up in an overlapped onwrite situation. + this.bufferProcessing = false; + + // the callback that's passed to _write(chunk,cb) + this.onwrite = function(er) { + onwrite(stream, er); + }; + + // the callback that the user supplies to write(chunk,encoding,cb) + this.writecb = null; + + // the amount that is being written when _write is called. + this.writelen = 0; + + this.buffer = []; + + // True if the error was already emitted and should not be thrown again + this.errorEmitted = false; +} + +function Writable(options) { + var Duplex = require('./_stream_duplex'); + + // Writable ctor is applied to Duplexes, though they're not + // instanceof Writable, they're instanceof Readable. + if (!(this instanceof Writable) && !(this instanceof Duplex)) + return new Writable(options); + + this._writableState = new WritableState(options, this); + + // legacy. + this.writable = true; + + Stream.call(this); +} + +// Otherwise people can pipe Writable streams, which is just wrong. +Writable.prototype.pipe = function() { + this.emit('error', new Error('Cannot pipe. Not readable.')); +}; + + +function writeAfterEnd(stream, state, cb) { + var er = new Error('write after end'); + // TODO: defer error events consistently everywhere, not just the cb + stream.emit('error', er); + process.nextTick(function() { + cb(er); + }); +} + +// If we get something that is not a buffer, string, null, or undefined, +// and we're not in objectMode, then that's an error. +// Otherwise stream chunks are all considered to be of length=1, and the +// watermarks determine how many objects to keep in the buffer, rather than +// how many bytes or characters. +function validChunk(stream, state, chunk, cb) { + var valid = true; + if (!Buffer.isBuffer(chunk) && + 'string' !== typeof chunk && + chunk !== null && + chunk !== undefined && + !state.objectMode) { + var er = new TypeError('Invalid non-string/buffer chunk'); + stream.emit('error', er); + process.nextTick(function() { + cb(er); + }); + valid = false; + } + return valid; +} + +Writable.prototype.write = function(chunk, encoding, cb) { + var state = this._writableState; + var ret = false; + + if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + + if (Buffer.isBuffer(chunk)) + encoding = 'buffer'; + else if (!encoding) + encoding = state.defaultEncoding; + + if (typeof cb !== 'function') + cb = function() {}; + + if (state.ended) + writeAfterEnd(this, state, cb); + else if (validChunk(this, state, chunk, cb)) + ret = writeOrBuffer(this, state, chunk, encoding, cb); + + return ret; +}; + +function decodeChunk(state, chunk, encoding) { + if (!state.objectMode && + state.decodeStrings !== false && + typeof chunk === 'string') { + chunk = new Buffer(chunk, encoding); + } + return chunk; +} + +// if we're already writing something, then just put this +// in the queue, and wait our turn. Otherwise, call _write +// If we return false, then we need a drain event, so set that flag. +function writeOrBuffer(stream, state, chunk, encoding, cb) { + chunk = decodeChunk(state, chunk, encoding); + if (Buffer.isBuffer(chunk)) + encoding = 'buffer'; + var len = state.objectMode ? 1 : chunk.length; + + state.length += len; + + var ret = state.length < state.highWaterMark; + // we must ensure that previous needDrain will not be reset to false. + if (!ret) + state.needDrain = true; + + if (state.writing) + state.buffer.push(new WriteReq(chunk, encoding, cb)); + else + doWrite(stream, state, len, chunk, encoding, cb); + + return ret; +} + +function doWrite(stream, state, len, chunk, encoding, cb) { + state.writelen = len; + state.writecb = cb; + state.writing = true; + state.sync = true; + stream._write(chunk, encoding, state.onwrite); + state.sync = false; +} + +function onwriteError(stream, state, sync, er, cb) { + if (sync) + process.nextTick(function() { + cb(er); + }); + else + cb(er); + + stream._writableState.errorEmitted = true; + stream.emit('error', er); +} + +function onwriteStateUpdate(state) { + state.writing = false; + state.writecb = null; + state.length -= state.writelen; + state.writelen = 0; +} + +function onwrite(stream, er) { + var state = stream._writableState; + var sync = state.sync; + var cb = state.writecb; + + onwriteStateUpdate(state); + + if (er) + onwriteError(stream, state, sync, er, cb); + else { + // Check if we're actually ready to finish, but don't emit yet + var finished = needFinish(stream, state); + + if (!finished && !state.bufferProcessing && state.buffer.length) + clearBuffer(stream, state); + + if (sync) { + process.nextTick(function() { + afterWrite(stream, state, finished, cb); + }); + } else { + afterWrite(stream, state, finished, cb); + } + } +} + +function afterWrite(stream, state, finished, cb) { + if (!finished) + onwriteDrain(stream, state); + cb(); + if (finished) + finishMaybe(stream, state); +} + +// Must force callback to be called on nextTick, so that we don't +// emit 'drain' before the write() consumer gets the 'false' return +// value, and has a chance to attach a 'drain' listener. +function onwriteDrain(stream, state) { + if (state.length === 0 && state.needDrain) { + state.needDrain = false; + stream.emit('drain'); + } +} + + +// if there's something in the buffer waiting, then process it +function clearBuffer(stream, state) { + state.bufferProcessing = true; + + for (var c = 0; c < state.buffer.length; c++) { + var entry = state.buffer[c]; + var chunk = entry.chunk; + var encoding = entry.encoding; + var cb = entry.callback; + var len = state.objectMode ? 1 : chunk.length; + + doWrite(stream, state, len, chunk, encoding, cb); + + // if we didn't call the onwrite immediately, then + // it means that we need to wait until it does. + // also, that means that the chunk and cb are currently + // being processed, so move the buffer counter past them. + if (state.writing) { + c++; + break; + } + } + + state.bufferProcessing = false; + if (c < state.buffer.length) + state.buffer = state.buffer.slice(c); + else + state.buffer.length = 0; +} + +Writable.prototype._write = function(chunk, encoding, cb) { + cb(new Error('not implemented')); +}; + +Writable.prototype.end = function(chunk, encoding, cb) { + var state = this._writableState; + + if (typeof chunk === 'function') { + cb = chunk; + chunk = null; + encoding = null; + } else if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + + if (typeof chunk !== 'undefined' && chunk !== null) + this.write(chunk, encoding); + + // ignore unnecessary end() calls. + if (!state.ending && !state.finished) + endWritable(this, state, cb); +}; + + +function needFinish(stream, state) { + return (state.ending && + state.length === 0 && + !state.finished && + !state.writing); +} + +function finishMaybe(stream, state) { + var need = needFinish(stream, state); + if (need) { + state.finished = true; + stream.emit('finish'); + } + return need; +} + +function endWritable(stream, state, cb) { + state.ending = true; + finishMaybe(stream, state); + if (cb) { + if (state.finished) + process.nextTick(cb); + else + stream.once('finish', cb); + } + state.ended = true; +} diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/README.md b/node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/README.md new file mode 100644 index 0000000..5a76b41 --- /dev/null +++ b/node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/README.md @@ -0,0 +1,3 @@ +# core-util-is + +The `util.is*` functions introduced in Node v0.12. diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/float.patch b/node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/float.patch new file mode 100644 index 0000000..a06d5c0 --- /dev/null +++ b/node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/float.patch @@ -0,0 +1,604 @@ +diff --git a/lib/util.js b/lib/util.js +index a03e874..9074e8e 100644 +--- a/lib/util.js ++++ b/lib/util.js +@@ -19,430 +19,6 @@ + // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + // USE OR OTHER DEALINGS IN THE SOFTWARE. + +-var formatRegExp = /%[sdj%]/g; +-exports.format = function(f) { +- if (!isString(f)) { +- var objects = []; +- for (var i = 0; i < arguments.length; i++) { +- objects.push(inspect(arguments[i])); +- } +- return objects.join(' '); +- } +- +- var i = 1; +- var args = arguments; +- var len = args.length; +- var str = String(f).replace(formatRegExp, function(x) { +- if (x === '%%') return '%'; +- if (i >= len) return x; +- switch (x) { +- case '%s': return String(args[i++]); +- case '%d': return Number(args[i++]); +- case '%j': +- try { +- return JSON.stringify(args[i++]); +- } catch (_) { +- return '[Circular]'; +- } +- default: +- return x; +- } +- }); +- for (var x = args[i]; i < len; x = args[++i]) { +- if (isNull(x) || !isObject(x)) { +- str += ' ' + x; +- } else { +- str += ' ' + inspect(x); +- } +- } +- return str; +-}; +- +- +-// Mark that a method should not be used. +-// Returns a modified function which warns once by default. +-// If --no-deprecation is set, then it is a no-op. +-exports.deprecate = function(fn, msg) { +- // Allow for deprecating things in the process of starting up. +- if (isUndefined(global.process)) { +- return function() { +- return exports.deprecate(fn, msg).apply(this, arguments); +- }; +- } +- +- if (process.noDeprecation === true) { +- return fn; +- } +- +- var warned = false; +- function deprecated() { +- if (!warned) { +- if (process.throwDeprecation) { +- throw new Error(msg); +- } else if (process.traceDeprecation) { +- console.trace(msg); +- } else { +- console.error(msg); +- } +- warned = true; +- } +- return fn.apply(this, arguments); +- } +- +- return deprecated; +-}; +- +- +-var debugs = {}; +-var debugEnviron; +-exports.debuglog = function(set) { +- if (isUndefined(debugEnviron)) +- debugEnviron = process.env.NODE_DEBUG || ''; +- set = set.toUpperCase(); +- if (!debugs[set]) { +- if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { +- var pid = process.pid; +- debugs[set] = function() { +- var msg = exports.format.apply(exports, arguments); +- console.error('%s %d: %s', set, pid, msg); +- }; +- } else { +- debugs[set] = function() {}; +- } +- } +- return debugs[set]; +-}; +- +- +-/** +- * Echos the value of a value. Trys to print the value out +- * in the best way possible given the different types. +- * +- * @param {Object} obj The object to print out. +- * @param {Object} opts Optional options object that alters the output. +- */ +-/* legacy: obj, showHidden, depth, colors*/ +-function inspect(obj, opts) { +- // default options +- var ctx = { +- seen: [], +- stylize: stylizeNoColor +- }; +- // legacy... +- if (arguments.length >= 3) ctx.depth = arguments[2]; +- if (arguments.length >= 4) ctx.colors = arguments[3]; +- if (isBoolean(opts)) { +- // legacy... +- ctx.showHidden = opts; +- } else if (opts) { +- // got an "options" object +- exports._extend(ctx, opts); +- } +- // set default options +- if (isUndefined(ctx.showHidden)) ctx.showHidden = false; +- if (isUndefined(ctx.depth)) ctx.depth = 2; +- if (isUndefined(ctx.colors)) ctx.colors = false; +- if (isUndefined(ctx.customInspect)) ctx.customInspect = true; +- if (ctx.colors) ctx.stylize = stylizeWithColor; +- return formatValue(ctx, obj, ctx.depth); +-} +-exports.inspect = inspect; +- +- +-// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics +-inspect.colors = { +- 'bold' : [1, 22], +- 'italic' : [3, 23], +- 'underline' : [4, 24], +- 'inverse' : [7, 27], +- 'white' : [37, 39], +- 'grey' : [90, 39], +- 'black' : [30, 39], +- 'blue' : [34, 39], +- 'cyan' : [36, 39], +- 'green' : [32, 39], +- 'magenta' : [35, 39], +- 'red' : [31, 39], +- 'yellow' : [33, 39] +-}; +- +-// Don't use 'blue' not visible on cmd.exe +-inspect.styles = { +- 'special': 'cyan', +- 'number': 'yellow', +- 'boolean': 'yellow', +- 'undefined': 'grey', +- 'null': 'bold', +- 'string': 'green', +- 'date': 'magenta', +- // "name": intentionally not styling +- 'regexp': 'red' +-}; +- +- +-function stylizeWithColor(str, styleType) { +- var style = inspect.styles[styleType]; +- +- if (style) { +- return '\u001b[' + inspect.colors[style][0] + 'm' + str + +- '\u001b[' + inspect.colors[style][1] + 'm'; +- } else { +- return str; +- } +-} +- +- +-function stylizeNoColor(str, styleType) { +- return str; +-} +- +- +-function arrayToHash(array) { +- var hash = {}; +- +- array.forEach(function(val, idx) { +- hash[val] = true; +- }); +- +- return hash; +-} +- +- +-function formatValue(ctx, value, recurseTimes) { +- // Provide a hook for user-specified inspect functions. +- // Check that value is an object with an inspect function on it +- if (ctx.customInspect && +- value && +- isFunction(value.inspect) && +- // Filter out the util module, it's inspect function is special +- value.inspect !== exports.inspect && +- // Also filter out any prototype objects using the circular check. +- !(value.constructor && value.constructor.prototype === value)) { +- var ret = value.inspect(recurseTimes, ctx); +- if (!isString(ret)) { +- ret = formatValue(ctx, ret, recurseTimes); +- } +- return ret; +- } +- +- // Primitive types cannot have properties +- var primitive = formatPrimitive(ctx, value); +- if (primitive) { +- return primitive; +- } +- +- // Look up the keys of the object. +- var keys = Object.keys(value); +- var visibleKeys = arrayToHash(keys); +- +- if (ctx.showHidden) { +- keys = Object.getOwnPropertyNames(value); +- } +- +- // Some type of object without properties can be shortcutted. +- if (keys.length === 0) { +- if (isFunction(value)) { +- var name = value.name ? ': ' + value.name : ''; +- return ctx.stylize('[Function' + name + ']', 'special'); +- } +- if (isRegExp(value)) { +- return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); +- } +- if (isDate(value)) { +- return ctx.stylize(Date.prototype.toString.call(value), 'date'); +- } +- if (isError(value)) { +- return formatError(value); +- } +- } +- +- var base = '', array = false, braces = ['{', '}']; +- +- // Make Array say that they are Array +- if (isArray(value)) { +- array = true; +- braces = ['[', ']']; +- } +- +- // Make functions say that they are functions +- if (isFunction(value)) { +- var n = value.name ? ': ' + value.name : ''; +- base = ' [Function' + n + ']'; +- } +- +- // Make RegExps say that they are RegExps +- if (isRegExp(value)) { +- base = ' ' + RegExp.prototype.toString.call(value); +- } +- +- // Make dates with properties first say the date +- if (isDate(value)) { +- base = ' ' + Date.prototype.toUTCString.call(value); +- } +- +- // Make error with message first say the error +- if (isError(value)) { +- base = ' ' + formatError(value); +- } +- +- if (keys.length === 0 && (!array || value.length == 0)) { +- return braces[0] + base + braces[1]; +- } +- +- if (recurseTimes < 0) { +- if (isRegExp(value)) { +- return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); +- } else { +- return ctx.stylize('[Object]', 'special'); +- } +- } +- +- ctx.seen.push(value); +- +- var output; +- if (array) { +- output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); +- } else { +- output = keys.map(function(key) { +- return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); +- }); +- } +- +- ctx.seen.pop(); +- +- return reduceToSingleString(output, base, braces); +-} +- +- +-function formatPrimitive(ctx, value) { +- if (isUndefined(value)) +- return ctx.stylize('undefined', 'undefined'); +- if (isString(value)) { +- var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') +- .replace(/'/g, "\\'") +- .replace(/\\"/g, '"') + '\''; +- return ctx.stylize(simple, 'string'); +- } +- if (isNumber(value)) { +- // Format -0 as '-0'. Strict equality won't distinguish 0 from -0, +- // so instead we use the fact that 1 / -0 < 0 whereas 1 / 0 > 0 . +- if (value === 0 && 1 / value < 0) +- return ctx.stylize('-0', 'number'); +- return ctx.stylize('' + value, 'number'); +- } +- if (isBoolean(value)) +- return ctx.stylize('' + value, 'boolean'); +- // For some reason typeof null is "object", so special case here. +- if (isNull(value)) +- return ctx.stylize('null', 'null'); +-} +- +- +-function formatError(value) { +- return '[' + Error.prototype.toString.call(value) + ']'; +-} +- +- +-function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { +- var output = []; +- for (var i = 0, l = value.length; i < l; ++i) { +- if (hasOwnProperty(value, String(i))) { +- output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, +- String(i), true)); +- } else { +- output.push(''); +- } +- } +- keys.forEach(function(key) { +- if (!key.match(/^\d+$/)) { +- output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, +- key, true)); +- } +- }); +- return output; +-} +- +- +-function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { +- var name, str, desc; +- desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; +- if (desc.get) { +- if (desc.set) { +- str = ctx.stylize('[Getter/Setter]', 'special'); +- } else { +- str = ctx.stylize('[Getter]', 'special'); +- } +- } else { +- if (desc.set) { +- str = ctx.stylize('[Setter]', 'special'); +- } +- } +- if (!hasOwnProperty(visibleKeys, key)) { +- name = '[' + key + ']'; +- } +- if (!str) { +- if (ctx.seen.indexOf(desc.value) < 0) { +- if (isNull(recurseTimes)) { +- str = formatValue(ctx, desc.value, null); +- } else { +- str = formatValue(ctx, desc.value, recurseTimes - 1); +- } +- if (str.indexOf('\n') > -1) { +- if (array) { +- str = str.split('\n').map(function(line) { +- return ' ' + line; +- }).join('\n').substr(2); +- } else { +- str = '\n' + str.split('\n').map(function(line) { +- return ' ' + line; +- }).join('\n'); +- } +- } +- } else { +- str = ctx.stylize('[Circular]', 'special'); +- } +- } +- if (isUndefined(name)) { +- if (array && key.match(/^\d+$/)) { +- return str; +- } +- name = JSON.stringify('' + key); +- if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { +- name = name.substr(1, name.length - 2); +- name = ctx.stylize(name, 'name'); +- } else { +- name = name.replace(/'/g, "\\'") +- .replace(/\\"/g, '"') +- .replace(/(^"|"$)/g, "'"); +- name = ctx.stylize(name, 'string'); +- } +- } +- +- return name + ': ' + str; +-} +- +- +-function reduceToSingleString(output, base, braces) { +- var numLinesEst = 0; +- var length = output.reduce(function(prev, cur) { +- numLinesEst++; +- if (cur.indexOf('\n') >= 0) numLinesEst++; +- return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; +- }, 0); +- +- if (length > 60) { +- return braces[0] + +- (base === '' ? '' : base + '\n ') + +- ' ' + +- output.join(',\n ') + +- ' ' + +- braces[1]; +- } +- +- return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; +-} +- +- + // NOTE: These type checking functions intentionally don't use `instanceof` + // because it is fragile and can be easily faked with `Object.create()`. + function isArray(ar) { +@@ -522,166 +98,10 @@ function isPrimitive(arg) { + exports.isPrimitive = isPrimitive; + + function isBuffer(arg) { +- return arg instanceof Buffer; ++ return Buffer.isBuffer(arg); + } + exports.isBuffer = isBuffer; + + function objectToString(o) { + return Object.prototype.toString.call(o); +-} +- +- +-function pad(n) { +- return n < 10 ? '0' + n.toString(10) : n.toString(10); +-} +- +- +-var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', +- 'Oct', 'Nov', 'Dec']; +- +-// 26 Feb 16:19:34 +-function timestamp() { +- var d = new Date(); +- var time = [pad(d.getHours()), +- pad(d.getMinutes()), +- pad(d.getSeconds())].join(':'); +- return [d.getDate(), months[d.getMonth()], time].join(' '); +-} +- +- +-// log is just a thin wrapper to console.log that prepends a timestamp +-exports.log = function() { +- console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); +-}; +- +- +-/** +- * Inherit the prototype methods from one constructor into another. +- * +- * The Function.prototype.inherits from lang.js rewritten as a standalone +- * function (not on Function.prototype). NOTE: If this file is to be loaded +- * during bootstrapping this function needs to be rewritten using some native +- * functions as prototype setup using normal JavaScript does not work as +- * expected during bootstrapping (see mirror.js in r114903). +- * +- * @param {function} ctor Constructor function which needs to inherit the +- * prototype. +- * @param {function} superCtor Constructor function to inherit prototype from. +- */ +-exports.inherits = function(ctor, superCtor) { +- ctor.super_ = superCtor; +- ctor.prototype = Object.create(superCtor.prototype, { +- constructor: { +- value: ctor, +- enumerable: false, +- writable: true, +- configurable: true +- } +- }); +-}; +- +-exports._extend = function(origin, add) { +- // Don't do anything if add isn't an object +- if (!add || !isObject(add)) return origin; +- +- var keys = Object.keys(add); +- var i = keys.length; +- while (i--) { +- origin[keys[i]] = add[keys[i]]; +- } +- return origin; +-}; +- +-function hasOwnProperty(obj, prop) { +- return Object.prototype.hasOwnProperty.call(obj, prop); +-} +- +- +-// Deprecated old stuff. +- +-exports.p = exports.deprecate(function() { +- for (var i = 0, len = arguments.length; i < len; ++i) { +- console.error(exports.inspect(arguments[i])); +- } +-}, 'util.p: Use console.error() instead'); +- +- +-exports.exec = exports.deprecate(function() { +- return require('child_process').exec.apply(this, arguments); +-}, 'util.exec is now called `child_process.exec`.'); +- +- +-exports.print = exports.deprecate(function() { +- for (var i = 0, len = arguments.length; i < len; ++i) { +- process.stdout.write(String(arguments[i])); +- } +-}, 'util.print: Use console.log instead'); +- +- +-exports.puts = exports.deprecate(function() { +- for (var i = 0, len = arguments.length; i < len; ++i) { +- process.stdout.write(arguments[i] + '\n'); +- } +-}, 'util.puts: Use console.log instead'); +- +- +-exports.debug = exports.deprecate(function(x) { +- process.stderr.write('DEBUG: ' + x + '\n'); +-}, 'util.debug: Use console.error instead'); +- +- +-exports.error = exports.deprecate(function(x) { +- for (var i = 0, len = arguments.length; i < len; ++i) { +- process.stderr.write(arguments[i] + '\n'); +- } +-}, 'util.error: Use console.error instead'); +- +- +-exports.pump = exports.deprecate(function(readStream, writeStream, callback) { +- var callbackCalled = false; +- +- function call(a, b, c) { +- if (callback && !callbackCalled) { +- callback(a, b, c); +- callbackCalled = true; +- } +- } +- +- readStream.addListener('data', function(chunk) { +- if (writeStream.write(chunk) === false) readStream.pause(); +- }); +- +- writeStream.addListener('drain', function() { +- readStream.resume(); +- }); +- +- readStream.addListener('end', function() { +- writeStream.end(); +- }); +- +- readStream.addListener('close', function() { +- call(); +- }); +- +- readStream.addListener('error', function(err) { +- writeStream.end(); +- call(err); +- }); +- +- writeStream.addListener('error', function(err) { +- readStream.destroy(); +- call(err); +- }); +-}, 'util.pump(): Use readableStream.pipe() instead'); +- +- +-var uv; +-exports._errnoException = function(err, syscall) { +- if (isUndefined(uv)) uv = process.binding('uv'); +- var errname = uv.errname(err); +- var e = new Error(syscall + ' ' + errname); +- e.code = errname; +- e.errno = errname; +- e.syscall = syscall; +- return e; +-}; ++} \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/lib/util.js b/node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/lib/util.js new file mode 100644 index 0000000..9074e8e --- /dev/null +++ b/node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/lib/util.js @@ -0,0 +1,107 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// NOTE: These type checking functions intentionally don't use `instanceof` +// because it is fragile and can be easily faked with `Object.create()`. +function isArray(ar) { + return Array.isArray(ar); +} +exports.isArray = isArray; + +function isBoolean(arg) { + return typeof arg === 'boolean'; +} +exports.isBoolean = isBoolean; + +function isNull(arg) { + return arg === null; +} +exports.isNull = isNull; + +function isNullOrUndefined(arg) { + return arg == null; +} +exports.isNullOrUndefined = isNullOrUndefined; + +function isNumber(arg) { + return typeof arg === 'number'; +} +exports.isNumber = isNumber; + +function isString(arg) { + return typeof arg === 'string'; +} +exports.isString = isString; + +function isSymbol(arg) { + return typeof arg === 'symbol'; +} +exports.isSymbol = isSymbol; + +function isUndefined(arg) { + return arg === void 0; +} +exports.isUndefined = isUndefined; + +function isRegExp(re) { + return isObject(re) && objectToString(re) === '[object RegExp]'; +} +exports.isRegExp = isRegExp; + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} +exports.isObject = isObject; + +function isDate(d) { + return isObject(d) && objectToString(d) === '[object Date]'; +} +exports.isDate = isDate; + +function isError(e) { + return isObject(e) && + (objectToString(e) === '[object Error]' || e instanceof Error); +} +exports.isError = isError; + +function isFunction(arg) { + return typeof arg === 'function'; +} +exports.isFunction = isFunction; + +function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; +} +exports.isPrimitive = isPrimitive; + +function isBuffer(arg) { + return Buffer.isBuffer(arg); +} +exports.isBuffer = isBuffer; + +function objectToString(o) { + return Object.prototype.toString.call(o); +} \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/package.json b/node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/package.json new file mode 100644 index 0000000..2b7593c --- /dev/null +++ b/node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/package.json @@ -0,0 +1,54 @@ +{ + "name": "core-util-is", + "version": "1.0.1", + "description": "The `util.is*` functions introduced in Node v0.12.", + "main": "lib/util.js", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/core-util-is" + }, + "keywords": [ + "util", + "isBuffer", + "isArray", + "isNumber", + "isString", + "isRegExp", + "isThis", + "isThat", + "polyfill" + ], + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me/" + }, + "license": "MIT", + "bugs": { + "url": "https://github.com/isaacs/core-util-is/issues" + }, + "readme": "# core-util-is\n\nThe `util.is*` functions introduced in Node v0.12.\n", + "readmeFilename": "README.md", + "homepage": "https://github.com/isaacs/core-util-is", + "_id": "core-util-is@1.0.1", + "dist": { + "shasum": "6b07085aef9a3ccac6ee53bf9d3df0c1521a5538", + "tarball": "http://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" + }, + "_from": "core-util-is@~1.0.0", + "_npmVersion": "1.3.23", + "_npmUser": { + "name": "isaacs", + "email": "i@izs.me" + }, + "maintainers": [ + { + "name": "isaacs", + "email": "i@izs.me" + } + ], + "directories": {}, + "_shasum": "6b07085aef9a3ccac6ee53bf9d3df0c1521a5538", + "_resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", + "scripts": {} +} diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/util.js b/node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/util.js new file mode 100644 index 0000000..007fa10 --- /dev/null +++ b/node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/util.js @@ -0,0 +1,106 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// NOTE: These type checking functions intentionally don't use `instanceof` +// because it is fragile and can be easily faked with `Object.create()`. +function isArray(ar) { + return Array.isArray(ar); +} +exports.isArray = isArray; + +function isBoolean(arg) { + return typeof arg === 'boolean'; +} +exports.isBoolean = isBoolean; + +function isNull(arg) { + return arg === null; +} +exports.isNull = isNull; + +function isNullOrUndefined(arg) { + return arg == null; +} +exports.isNullOrUndefined = isNullOrUndefined; + +function isNumber(arg) { + return typeof arg === 'number'; +} +exports.isNumber = isNumber; + +function isString(arg) { + return typeof arg === 'string'; +} +exports.isString = isString; + +function isSymbol(arg) { + return typeof arg === 'symbol'; +} +exports.isSymbol = isSymbol; + +function isUndefined(arg) { + return arg === void 0; +} +exports.isUndefined = isUndefined; + +function isRegExp(re) { + return isObject(re) && objectToString(re) === '[object RegExp]'; +} +exports.isRegExp = isRegExp; + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} +exports.isObject = isObject; + +function isDate(d) { + return isObject(d) && objectToString(d) === '[object Date]'; +} +exports.isDate = isDate; + +function isError(e) { + return isObject(e) && objectToString(e) === '[object Error]'; +} +exports.isError = isError; + +function isFunction(arg) { + return typeof arg === 'function'; +} +exports.isFunction = isFunction; + +function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; +} +exports.isPrimitive = isPrimitive; + +function isBuffer(arg) { + return arg instanceof Buffer; +} +exports.isBuffer = isBuffer; + +function objectToString(o) { + return Object.prototype.toString.call(o); +} diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/LICENSE b/node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/LICENSE new file mode 100644 index 0000000..dea3013 --- /dev/null +++ b/node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/LICENSE @@ -0,0 +1,16 @@ +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/mongodb/node_modules/readable-stream/node_modules/inherits/README.md b/node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/README.md new file mode 100644 index 0000000..b1c5665 --- /dev/null +++ b/node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/README.md @@ -0,0 +1,42 @@ +Browser-friendly inheritance fully compatible with standard node.js +[inherits](http://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructor). + +This package exports standard `inherits` from node.js `util` module in +node environment, but also provides alternative browser-friendly +implementation through [browser +field](https://gist.github.com/shtylman/4339901). Alternative +implementation is a literal copy of standard one located in standalone +module to avoid requiring of `util`. It also has a shim for old +browsers with no `Object.create` support. + +While keeping you sure you are using standard `inherits` +implementation in node.js environment, it allows bundlers such as +[browserify](https://github.com/substack/node-browserify) to not +include full `util` package to your client code if all you need is +just `inherits` function. It worth, because browser shim for `util` +package is large and `inherits` is often the single function you need +from it. + +It's recommended to use this package instead of +`require('util').inherits` for any code that has chances to be used +not only in node.js but in browser too. + +## usage + +```js +var inherits = require('inherits'); +// then use exactly as the standard one +``` + +## note on version ~1.0 + +Version ~1.0 had completely different motivation and is not compatible +neither with 2.0 nor with standard node.js `inherits`. + +If you are using version ~1.0 and planning to switch to ~2.0, be +careful: + +* new version uses `super_` instead of `super` for referencing + superclass +* new version overwrites current prototype while old one preserves any + existing fields on it diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/inherits.js b/node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/inherits.js new file mode 100644 index 0000000..29f5e24 --- /dev/null +++ b/node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/inherits.js @@ -0,0 +1 @@ +module.exports = require('util').inherits diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/inherits_browser.js b/node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/inherits_browser.js new file mode 100644 index 0000000..c1e78a7 --- /dev/null +++ b/node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/inherits_browser.js @@ -0,0 +1,23 @@ +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + }; +} else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } +} diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/package.json b/node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/package.json new file mode 100644 index 0000000..3d69f4f --- /dev/null +++ b/node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/package.json @@ -0,0 +1,51 @@ +{ + "name": "inherits", + "description": "Browser-friendly inheritance fully compatible with standard node.js inherits()", + "version": "2.0.1", + "keywords": [ + "inheritance", + "class", + "klass", + "oop", + "object-oriented", + "inherits", + "browser", + "browserify" + ], + "main": "./inherits.js", + "browser": "./inherits_browser.js", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/inherits" + }, + "license": "ISC", + "scripts": { + "test": "node test" + }, + "readme": "Browser-friendly inheritance fully compatible with standard node.js\n[inherits](http://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructor).\n\nThis package exports standard `inherits` from node.js `util` module in\nnode environment, but also provides alternative browser-friendly\nimplementation through [browser\nfield](https://gist.github.com/shtylman/4339901). Alternative\nimplementation is a literal copy of standard one located in standalone\nmodule to avoid requiring of `util`. It also has a shim for old\nbrowsers with no `Object.create` support.\n\nWhile keeping you sure you are using standard `inherits`\nimplementation in node.js environment, it allows bundlers such as\n[browserify](https://github.com/substack/node-browserify) to not\ninclude full `util` package to your client code if all you need is\njust `inherits` function. It worth, because browser shim for `util`\npackage is large and `inherits` is often the single function you need\nfrom it.\n\nIt's recommended to use this package instead of\n`require('util').inherits` for any code that has chances to be used\nnot only in node.js but in browser too.\n\n## usage\n\n```js\nvar inherits = require('inherits');\n// then use exactly as the standard one\n```\n\n## note on version ~1.0\n\nVersion ~1.0 had completely different motivation and is not compatible\nneither with 2.0 nor with standard node.js `inherits`.\n\nIf you are using version ~1.0 and planning to switch to ~2.0, be\ncareful:\n\n* new version uses `super_` instead of `super` for referencing\n superclass\n* new version overwrites current prototype while old one preserves any\n existing fields on it\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/isaacs/inherits/issues" + }, + "_id": "inherits@2.0.1", + "dist": { + "shasum": "b17d08d326b4423e568eff719f91b0b1cbdf69f1", + "tarball": "http://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + }, + "_from": "inherits@~2.0.1", + "_npmVersion": "1.3.8", + "_npmUser": { + "name": "isaacs", + "email": "i@izs.me" + }, + "maintainers": [ + { + "name": "isaacs", + "email": "i@izs.me" + } + ], + "directories": {}, + "_shasum": "b17d08d326b4423e568eff719f91b0b1cbdf69f1", + "_resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "homepage": "https://github.com/isaacs/inherits" +} diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/test.js b/node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/test.js new file mode 100644 index 0000000..fc53012 --- /dev/null +++ b/node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/test.js @@ -0,0 +1,25 @@ +var inherits = require('./inherits.js') +var assert = require('assert') + +function test(c) { + assert(c.constructor === Child) + assert(c.constructor.super_ === Parent) + assert(Object.getPrototypeOf(c) === Child.prototype) + assert(Object.getPrototypeOf(Object.getPrototypeOf(c)) === Parent.prototype) + assert(c instanceof Child) + assert(c instanceof Parent) +} + +function Child() { + Parent.call(this) + test(this) +} + +function Parent() {} + +inherits(Child, Parent) + +var c = new Child +test(c) + +console.log('ok') diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/README.md b/node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/README.md new file mode 100644 index 0000000..052a62b --- /dev/null +++ b/node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/README.md @@ -0,0 +1,54 @@ + +# isarray + +`Array#isArray` for older browsers. + +## Usage + +```js +var isArray = require('isarray'); + +console.log(isArray([])); // => true +console.log(isArray({})); // => false +``` + +## Installation + +With [npm](http://npmjs.org) do + +```bash +$ npm install isarray +``` + +Then bundle for the browser with +[browserify](https://github.com/substack/browserify). + +With [component](http://component.io) do + +```bash +$ component install juliangruber/isarray +``` + +## License + +(MIT) + +Copyright (c) 2013 Julian Gruber <julian@juliangruber.com> + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +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/mongodb/node_modules/readable-stream/node_modules/isarray/build/build.js b/node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/build/build.js new file mode 100644 index 0000000..ec58596 --- /dev/null +++ b/node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/build/build.js @@ -0,0 +1,209 @@ + +/** + * Require the given path. + * + * @param {String} path + * @return {Object} exports + * @api public + */ + +function require(path, parent, orig) { + var resolved = require.resolve(path); + + // lookup failed + if (null == resolved) { + orig = orig || path; + parent = parent || 'root'; + var err = new Error('Failed to require "' + orig + '" from "' + parent + '"'); + err.path = orig; + err.parent = parent; + err.require = true; + throw err; + } + + var module = require.modules[resolved]; + + // perform real require() + // by invoking the module's + // registered function + if (!module.exports) { + module.exports = {}; + module.client = module.component = true; + module.call(this, module.exports, require.relative(resolved), module); + } + + return module.exports; +} + +/** + * Registered modules. + */ + +require.modules = {}; + +/** + * Registered aliases. + */ + +require.aliases = {}; + +/** + * Resolve `path`. + * + * Lookup: + * + * - PATH/index.js + * - PATH.js + * - PATH + * + * @param {String} path + * @return {String} path or null + * @api private + */ + +require.resolve = function(path) { + if (path.charAt(0) === '/') path = path.slice(1); + var index = path + '/index.js'; + + var paths = [ + path, + path + '.js', + path + '.json', + path + '/index.js', + path + '/index.json' + ]; + + for (var i = 0; i < paths.length; i++) { + var path = paths[i]; + if (require.modules.hasOwnProperty(path)) return path; + } + + if (require.aliases.hasOwnProperty(index)) { + return require.aliases[index]; + } +}; + +/** + * Normalize `path` relative to the current path. + * + * @param {String} curr + * @param {String} path + * @return {String} + * @api private + */ + +require.normalize = function(curr, path) { + var segs = []; + + if ('.' != path.charAt(0)) return path; + + curr = curr.split('/'); + path = path.split('/'); + + for (var i = 0; i < path.length; ++i) { + if ('..' == path[i]) { + curr.pop(); + } else if ('.' != path[i] && '' != path[i]) { + segs.push(path[i]); + } + } + + return curr.concat(segs).join('/'); +}; + +/** + * Register module at `path` with callback `definition`. + * + * @param {String} path + * @param {Function} definition + * @api private + */ + +require.register = function(path, definition) { + require.modules[path] = definition; +}; + +/** + * Alias a module definition. + * + * @param {String} from + * @param {String} to + * @api private + */ + +require.alias = function(from, to) { + if (!require.modules.hasOwnProperty(from)) { + throw new Error('Failed to alias "' + from + '", it does not exist'); + } + require.aliases[to] = from; +}; + +/** + * Return a require function relative to the `parent` path. + * + * @param {String} parent + * @return {Function} + * @api private + */ + +require.relative = function(parent) { + var p = require.normalize(parent, '..'); + + /** + * lastIndexOf helper. + */ + + function lastIndexOf(arr, obj) { + var i = arr.length; + while (i--) { + if (arr[i] === obj) return i; + } + return -1; + } + + /** + * The relative require() itself. + */ + + function localRequire(path) { + var resolved = localRequire.resolve(path); + return require(resolved, parent, path); + } + + /** + * Resolve relative to the parent. + */ + + localRequire.resolve = function(path) { + var c = path.charAt(0); + if ('/' == c) return path.slice(1); + if ('.' == c) return require.normalize(p, path); + + // resolve deps by returning + // the dep in the nearest "deps" + // directory + var segs = parent.split('/'); + var i = lastIndexOf(segs, 'deps') + 1; + if (!i) i = 0; + path = segs.slice(0, i + 1).join('/') + '/deps/' + path; + return path; + }; + + /** + * Check if module is defined at `path`. + */ + + localRequire.exists = function(path) { + return require.modules.hasOwnProperty(localRequire.resolve(path)); + }; + + return localRequire; +}; +require.register("isarray/index.js", function(exports, require, module){ +module.exports = Array.isArray || function (arr) { + return Object.prototype.toString.call(arr) == '[object Array]'; +}; + +}); +require.alias("isarray/index.js", "isarray/index.js"); + diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/component.json b/node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/component.json new file mode 100644 index 0000000..9e31b68 --- /dev/null +++ b/node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/component.json @@ -0,0 +1,19 @@ +{ + "name" : "isarray", + "description" : "Array#isArray for older browsers", + "version" : "0.0.1", + "repository" : "juliangruber/isarray", + "homepage": "https://github.com/juliangruber/isarray", + "main" : "index.js", + "scripts" : [ + "index.js" + ], + "dependencies" : {}, + "keywords": ["browser","isarray","array"], + "author": { + "name": "Julian Gruber", + "email": "mail@juliangruber.com", + "url": "http://juliangruber.com" + }, + "license": "MIT" +} diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/index.js b/node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/index.js new file mode 100644 index 0000000..5f5ad45 --- /dev/null +++ b/node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/index.js @@ -0,0 +1,3 @@ +module.exports = Array.isArray || function (arr) { + return Object.prototype.toString.call(arr) == '[object Array]'; +}; diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/package.json b/node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/package.json new file mode 100644 index 0000000..fc7904b --- /dev/null +++ b/node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/package.json @@ -0,0 +1,54 @@ +{ + "name": "isarray", + "description": "Array#isArray for older browsers", + "version": "0.0.1", + "repository": { + "type": "git", + "url": "git://github.com/juliangruber/isarray.git" + }, + "homepage": "https://github.com/juliangruber/isarray", + "main": "index.js", + "scripts": { + "test": "tap test/*.js" + }, + "dependencies": {}, + "devDependencies": { + "tap": "*" + }, + "keywords": [ + "browser", + "isarray", + "array" + ], + "author": { + "name": "Julian Gruber", + "email": "mail@juliangruber.com", + "url": "http://juliangruber.com" + }, + "license": "MIT", + "readme": "\n# isarray\n\n`Array#isArray` for older browsers.\n\n## Usage\n\n```js\nvar isArray = require('isarray');\n\nconsole.log(isArray([])); // => true\nconsole.log(isArray({})); // => false\n```\n\n## Installation\n\nWith [npm](http://npmjs.org) do\n\n```bash\n$ npm install isarray\n```\n\nThen bundle for the browser with\n[browserify](https://github.com/substack/browserify).\n\nWith [component](http://component.io) do\n\n```bash\n$ component install juliangruber/isarray\n```\n\n## License\n\n(MIT)\n\nCopyright (c) 2013 Julian Gruber <julian@juliangruber.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\nof the Software, and to permit persons to whom the Software is furnished to do\nso, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n", + "readmeFilename": "README.md", + "_id": "isarray@0.0.1", + "dist": { + "shasum": "8a18acfca9a8f4177e09abfc6038939b05d1eedf", + "tarball": "http://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + }, + "_from": "isarray@0.0.1", + "_npmVersion": "1.2.18", + "_npmUser": { + "name": "juliangruber", + "email": "julian@juliangruber.com" + }, + "maintainers": [ + { + "name": "juliangruber", + "email": "julian@juliangruber.com" + } + ], + "directories": {}, + "_shasum": "8a18acfca9a8f4177e09abfc6038939b05d1eedf", + "_resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "bugs": { + "url": "https://github.com/juliangruber/isarray/issues" + } +} diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/.npmignore b/node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/.npmignore new file mode 100644 index 0000000..206320c --- /dev/null +++ b/node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/.npmignore @@ -0,0 +1,2 @@ +build +test diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/LICENSE b/node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/LICENSE new file mode 100644 index 0000000..6de584a --- /dev/null +++ b/node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/LICENSE @@ -0,0 +1,20 @@ +Copyright Joyent, Inc. and other Node contributors. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the +following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/README.md b/node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/README.md new file mode 100644 index 0000000..4d2aa00 --- /dev/null +++ b/node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/README.md @@ -0,0 +1,7 @@ +**string_decoder.js** (`require('string_decoder')`) from Node.js core + +Copyright Joyent, Inc. and other Node contributors. See LICENCE file for details. + +Version numbers match the versions found in Node core, e.g. 0.10.24 matches Node 0.10.24, likewise 0.11.10 matches Node 0.11.10. **Prefer the stable version over the unstable.** + +The *build/* directory contains a build script that will scrape the source from the [joyent/node](https://github.com/joyent/node) repo given a specific Node version. \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/index.js b/node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/index.js new file mode 100644 index 0000000..b00e54f --- /dev/null +++ b/node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/index.js @@ -0,0 +1,221 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var Buffer = require('buffer').Buffer; + +var isBufferEncoding = Buffer.isEncoding + || function(encoding) { + switch (encoding && encoding.toLowerCase()) { + case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': case 'raw': return true; + default: return false; + } + } + + +function assertEncoding(encoding) { + if (encoding && !isBufferEncoding(encoding)) { + throw new Error('Unknown encoding: ' + encoding); + } +} + +// StringDecoder provides an interface for efficiently splitting a series of +// buffers into a series of JS strings without breaking apart multi-byte +// characters. CESU-8 is handled as part of the UTF-8 encoding. +// +// @TODO Handling all encodings inside a single object makes it very difficult +// to reason about this code, so it should be split up in the future. +// @TODO There should be a utf8-strict encoding that rejects invalid UTF-8 code +// points as used by CESU-8. +var StringDecoder = exports.StringDecoder = function(encoding) { + this.encoding = (encoding || 'utf8').toLowerCase().replace(/[-_]/, ''); + assertEncoding(encoding); + switch (this.encoding) { + case 'utf8': + // CESU-8 represents each of Surrogate Pair by 3-bytes + this.surrogateSize = 3; + break; + case 'ucs2': + case 'utf16le': + // UTF-16 represents each of Surrogate Pair by 2-bytes + this.surrogateSize = 2; + this.detectIncompleteChar = utf16DetectIncompleteChar; + break; + case 'base64': + // Base-64 stores 3 bytes in 4 chars, and pads the remainder. + this.surrogateSize = 3; + this.detectIncompleteChar = base64DetectIncompleteChar; + break; + default: + this.write = passThroughWrite; + return; + } + + // Enough space to store all bytes of a single character. UTF-8 needs 4 + // bytes, but CESU-8 may require up to 6 (3 bytes per surrogate). + this.charBuffer = new Buffer(6); + // Number of bytes received for the current incomplete multi-byte character. + this.charReceived = 0; + // Number of bytes expected for the current incomplete multi-byte character. + this.charLength = 0; +}; + + +// write decodes the given buffer and returns it as JS string that is +// guaranteed to not contain any partial multi-byte characters. Any partial +// character found at the end of the buffer is buffered up, and will be +// returned when calling write again with the remaining bytes. +// +// Note: Converting a Buffer containing an orphan surrogate to a String +// currently works, but converting a String to a Buffer (via `new Buffer`, or +// Buffer#write) will replace incomplete surrogates with the unicode +// replacement character. See https://codereview.chromium.org/121173009/ . +StringDecoder.prototype.write = function(buffer) { + var charStr = ''; + // if our last write ended with an incomplete multibyte character + while (this.charLength) { + // determine how many remaining bytes this buffer has to offer for this char + var available = (buffer.length >= this.charLength - this.charReceived) ? + this.charLength - this.charReceived : + buffer.length; + + // add the new bytes to the char buffer + buffer.copy(this.charBuffer, this.charReceived, 0, available); + this.charReceived += available; + + if (this.charReceived < this.charLength) { + // still not enough chars in this buffer? wait for more ... + return ''; + } + + // remove bytes belonging to the current character from the buffer + buffer = buffer.slice(available, buffer.length); + + // get the character that was split + charStr = this.charBuffer.slice(0, this.charLength).toString(this.encoding); + + // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character + var charCode = charStr.charCodeAt(charStr.length - 1); + if (charCode >= 0xD800 && charCode <= 0xDBFF) { + this.charLength += this.surrogateSize; + charStr = ''; + continue; + } + this.charReceived = this.charLength = 0; + + // if there are no more bytes in this buffer, just emit our char + if (buffer.length === 0) { + return charStr; + } + break; + } + + // determine and set charLength / charReceived + this.detectIncompleteChar(buffer); + + var end = buffer.length; + if (this.charLength) { + // buffer the incomplete character bytes we got + buffer.copy(this.charBuffer, 0, buffer.length - this.charReceived, end); + end -= this.charReceived; + } + + charStr += buffer.toString(this.encoding, 0, end); + + var end = charStr.length - 1; + var charCode = charStr.charCodeAt(end); + // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character + if (charCode >= 0xD800 && charCode <= 0xDBFF) { + var size = this.surrogateSize; + this.charLength += size; + this.charReceived += size; + this.charBuffer.copy(this.charBuffer, size, 0, size); + buffer.copy(this.charBuffer, 0, 0, size); + return charStr.substring(0, end); + } + + // or just emit the charStr + return charStr; +}; + +// detectIncompleteChar determines if there is an incomplete UTF-8 character at +// the end of the given buffer. If so, it sets this.charLength to the byte +// length that character, and sets this.charReceived to the number of bytes +// that are available for this character. +StringDecoder.prototype.detectIncompleteChar = function(buffer) { + // determine how many bytes we have to check at the end of this buffer + var i = (buffer.length >= 3) ? 3 : buffer.length; + + // Figure out if one of the last i bytes of our buffer announces an + // incomplete char. + for (; i > 0; i--) { + var c = buffer[buffer.length - i]; + + // See http://en.wikipedia.org/wiki/UTF-8#Description + + // 110XXXXX + if (i == 1 && c >> 5 == 0x06) { + this.charLength = 2; + break; + } + + // 1110XXXX + if (i <= 2 && c >> 4 == 0x0E) { + this.charLength = 3; + break; + } + + // 11110XXX + if (i <= 3 && c >> 3 == 0x1E) { + this.charLength = 4; + break; + } + } + this.charReceived = i; +}; + +StringDecoder.prototype.end = function(buffer) { + var res = ''; + if (buffer && buffer.length) + res = this.write(buffer); + + if (this.charReceived) { + var cr = this.charReceived; + var buf = this.charBuffer; + var enc = this.encoding; + res += buf.slice(0, cr).toString(enc); + } + + return res; +}; + +function passThroughWrite(buffer) { + return buffer.toString(this.encoding); +} + +function utf16DetectIncompleteChar(buffer) { + this.charReceived = buffer.length % 2; + this.charLength = this.charReceived ? 2 : 0; +} + +function base64DetectIncompleteChar(buffer) { + this.charReceived = buffer.length % 3; + this.charLength = this.charReceived ? 3 : 0; +} diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/package.json b/node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/package.json new file mode 100644 index 0000000..a8c586b --- /dev/null +++ b/node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/package.json @@ -0,0 +1,54 @@ +{ + "name": "string_decoder", + "version": "0.10.31", + "description": "The string_decoder module from Node core", + "main": "index.js", + "dependencies": {}, + "devDependencies": { + "tap": "~0.4.8" + }, + "scripts": { + "test": "tap test/simple/*.js" + }, + "repository": { + "type": "git", + "url": "git://github.com/rvagg/string_decoder.git" + }, + "homepage": "https://github.com/rvagg/string_decoder", + "keywords": [ + "string", + "decoder", + "browser", + "browserify" + ], + "license": "MIT", + "gitHead": "d46d4fd87cf1d06e031c23f1ba170ca7d4ade9a0", + "bugs": { + "url": "https://github.com/rvagg/string_decoder/issues" + }, + "_id": "string_decoder@0.10.31", + "_shasum": "62e203bc41766c6c28c9fc84301dab1c5310fa94", + "_from": "string_decoder@~0.10.x", + "_npmVersion": "1.4.23", + "_npmUser": { + "name": "rvagg", + "email": "rod@vagg.org" + }, + "maintainers": [ + { + "name": "substack", + "email": "mail@substack.net" + }, + { + "name": "rvagg", + "email": "rod@vagg.org" + } + ], + "dist": { + "shasum": "62e203bc41766c6c28c9fc84301dab1c5310fa94", + "tarball": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "readme": "ERROR: No README data found!" +} diff --git a/node_modules/mongodb/node_modules/readable-stream/package.json b/node_modules/mongodb/node_modules/readable-stream/package.json new file mode 100644 index 0000000..153fb54 --- /dev/null +++ b/node_modules/mongodb/node_modules/readable-stream/package.json @@ -0,0 +1,70 @@ +{ + "name": "readable-stream", + "version": "1.0.33", + "description": "Streams2, a user-land copy of the stream library from Node.js v0.10.x", + "main": "readable.js", + "dependencies": { + "core-util-is": "~1.0.0", + "isarray": "0.0.1", + "string_decoder": "~0.10.x", + "inherits": "~2.0.1" + }, + "devDependencies": { + "tap": "~0.2.6" + }, + "scripts": { + "test": "tap test/simple/*.js" + }, + "repository": { + "type": "git", + "url": "git://github.com/isaacs/readable-stream" + }, + "keywords": [ + "readable", + "stream", + "pipe" + ], + "browser": { + "util": false + }, + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me/" + }, + "license": "MIT", + "gitHead": "0bf97a117c5646556548966409ebc57a6dda2638", + "bugs": { + "url": "https://github.com/isaacs/readable-stream/issues" + }, + "homepage": "https://github.com/isaacs/readable-stream", + "_id": "readable-stream@1.0.33", + "_shasum": "3a360dd66c1b1d7fd4705389860eda1d0f61126c", + "_from": "readable-stream@latest", + "_npmVersion": "1.4.28", + "_npmUser": { + "name": "rvagg", + "email": "rod@vagg.org" + }, + "maintainers": [ + { + "name": "isaacs", + "email": "i@izs.me" + }, + { + "name": "tootallnate", + "email": "nathan@tootallnate.net" + }, + { + "name": "rvagg", + "email": "rod@vagg.org" + } + ], + "dist": { + "shasum": "3a360dd66c1b1d7fd4705389860eda1d0f61126c", + "tarball": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", + "readme": "ERROR: No README data found!" +} diff --git a/node_modules/mongodb/node_modules/readable-stream/passthrough.js b/node_modules/mongodb/node_modules/readable-stream/passthrough.js new file mode 100644 index 0000000..27e8d8a --- /dev/null +++ b/node_modules/mongodb/node_modules/readable-stream/passthrough.js @@ -0,0 +1 @@ +module.exports = require("./lib/_stream_passthrough.js") diff --git a/node_modules/mongodb/node_modules/readable-stream/readable.js b/node_modules/mongodb/node_modules/readable-stream/readable.js new file mode 100644 index 0000000..8b5337b --- /dev/null +++ b/node_modules/mongodb/node_modules/readable-stream/readable.js @@ -0,0 +1,8 @@ +var Stream = require('stream'); // hack to fix a circular dependency issue when used with browserify +exports = module.exports = require('./lib/_stream_readable.js'); +exports.Stream = Stream; +exports.Readable = exports; +exports.Writable = require('./lib/_stream_writable.js'); +exports.Duplex = require('./lib/_stream_duplex.js'); +exports.Transform = require('./lib/_stream_transform.js'); +exports.PassThrough = require('./lib/_stream_passthrough.js'); diff --git a/node_modules/mongodb/node_modules/readable-stream/transform.js b/node_modules/mongodb/node_modules/readable-stream/transform.js new file mode 100644 index 0000000..5d482f0 --- /dev/null +++ b/node_modules/mongodb/node_modules/readable-stream/transform.js @@ -0,0 +1 @@ +module.exports = require("./lib/_stream_transform.js") diff --git a/node_modules/mongodb/node_modules/readable-stream/writable.js b/node_modules/mongodb/node_modules/readable-stream/writable.js new file mode 100644 index 0000000..e1e9efd --- /dev/null +++ b/node_modules/mongodb/node_modules/readable-stream/writable.js @@ -0,0 +1 @@ +module.exports = require("./lib/_stream_writable.js") diff --git a/node_modules/mongodb/package.json b/node_modules/mongodb/package.json new file mode 100755 index 0000000..47169d9 --- /dev/null +++ b/node_modules/mongodb/package.json @@ -0,0 +1,252 @@ +{ + "name": "mongodb", + "description": "A node.js driver for MongoDB", + "keywords": [ + "mongodb", + "mongo", + "driver", + "db" + ], + "version": "1.4.23", + "author": { + "name": "Christian Amor Kvalheim", + "email": "christkv@gmail.com" + }, + "contributors": [ + { + "name": "Aaron Heckmann" + }, + { + "name": "Christoph Pojer" + }, + { + "name": "Pau Ramon Revilla" + }, + { + "name": "Nathan White" + }, + { + "name": "Emmerman" + }, + { + "name": "Seth LaForge" + }, + { + "name": "Boris Filipov" + }, + { + "name": "Stefan Schärmeli" + }, + { + "name": "Tedde Lundgren" + }, + { + "name": "renctan" + }, + { + "name": "Sergey Ukustov" + }, + { + "name": "Ciaran Jessup" + }, + { + "name": "kuno" + }, + { + "name": "srimonti" + }, + { + "name": "Erik Abele" + }, + { + "name": "Pratik Daga" + }, + { + "name": "Slobodan Utvic" + }, + { + "name": "Kristina Chodorow" + }, + { + "name": "Yonathan Randolph" + }, + { + "name": "Brian Noguchi" + }, + { + "name": "Sam Epstein" + }, + { + "name": "James Harrison Fisher" + }, + { + "name": "Vladimir Dronnikov" + }, + { + "name": "Ben Hockey" + }, + { + "name": "Henrik Johansson" + }, + { + "name": "Simon Weare" + }, + { + "name": "Alex Gorbatchev" + }, + { + "name": "Shimon Doodkin" + }, + { + "name": "Kyle Mueller" + }, + { + "name": "Eran Hammer-Lahav" + }, + { + "name": "Marcin Ciszak" + }, + { + "name": "François de Metz" + }, + { + "name": "Vinay Pulim" + }, + { + "name": "nstielau" + }, + { + "name": "Adam Wiggins" + }, + { + "name": "entrinzikyl" + }, + { + "name": "Jeremy Selier" + }, + { + "name": "Ian Millington" + }, + { + "name": "Public Keating" + }, + { + "name": "andrewjstone" + }, + { + "name": "Christopher Stott" + }, + { + "name": "Corey Jewett" + }, + { + "name": "brettkiefer" + }, + { + "name": "Rob Holland" + }, + { + "name": "Senmiao Liu" + }, + { + "name": "heroic" + }, + { + "name": "gitfy" + }, + { + "name": "Andrew Stone" + }, + { + "name": "John Le Drew" + }, + { + "name": "Lucasfilm Singapore" + }, + { + "name": "Roman Shtylman" + }, + { + "name": "Matt Self" + }, + { + "name": "Gregory Langlais" + }, + { + "name": "Samantha Ritter" + } + ], + "repository": { + "type": "git", + "url": "http://github.com/mongodb/node-mongodb-native.git" + }, + "bugs": { + "url": "http://github.com/mongodb/node-mongodb-native/issues" + }, + "dependencies": { + "bson": "~0.2", + "kerberos": "0.0.6", + "readable-stream": "latest" + }, + "devDependencies": { + "dox": "0.4.4", + "uglify-js": "1.2.5", + "ejs": "0.6.1", + "request": "2.12.0", + "nodeunit": "0.7.3", + "markdown": "0.3.1", + "gleak": "0.5.0", + "step": "0.0.5", + "async": "0.1.22", + "integra": "0.1.8", + "optimist": "latest", + "rimraf": "2.2.6", + "semver": "4.1.0", + "mongodb-core": "1.1.3" + }, + "optionalDependencies": { + "kerberos": "0.0.6", + "readable-stream": "latest" + }, + "config": { + "native": false + }, + "main": "./lib/mongodb/index", + "homepage": "http://mongodb.github.com/node-mongodb-native/", + "directories": { + "lib": "./lib/mongodb" + }, + "engines": { + "node": ">=0.6.19" + }, + "scripts": { + "test": "node test/runner.js -t functional" + }, + "licenses": [ + { + "type": "Apache License, Version 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0" + } + ], + "gitHead": "5fb481a1e1d127c48550de6f7ddf3acf52cc2fab", + "_id": "mongodb@1.4.23", + "_shasum": "da19ffb2b16a7182b92460a9ff4207b3bb2fb9b6", + "_from": "mongodb@", + "_npmVersion": "2.0.0", + "_npmUser": { + "name": "christkv", + "email": "christkv@gmail.com" + }, + "maintainers": [ + { + "name": "christkv", + "email": "christkv@gmail.com" + } + ], + "dist": { + "shasum": "da19ffb2b16a7182b92460a9ff4207b3bb2fb9b6", + "tarball": "http://registry.npmjs.org/mongodb/-/mongodb-1.4.23.tgz" + }, + "_resolved": "https://registry.npmjs.org/mongodb/-/mongodb-1.4.23.tgz", + "readme": "ERROR: No README data found!" +} diff --git a/node_modules/neon/.npmignore b/node_modules/neon/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/node_modules/neon/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/neon/CHANGELOG.markdown b/node_modules/neon/CHANGELOG.markdown new file mode 100644 index 0000000..cb2fde4 --- /dev/null +++ b/node_modules/neon/CHANGELOG.markdown @@ -0,0 +1,22 @@ +2.0.0 (2014-02-15) + + - Requiring now adds Class, Module, Interface to global scope (neon) + - You can now require the stdlib with require('neon/stdlib') + - Requiring now adds CustomEvent, CustomEventSupport, NodeSupport + and BubblingSupport to the global scope (stdlib) + - Major version bump because it's not compatible with 1.x (The other + was loaded in a namespace) + +1.1.0 (2014-01-29) + + - Added stdlib, consisting on: + - NodeSupport + - CustomEvent and CustomEventSupport + - BubblingSupport + - Added tests for stdlib + - Moved files to /lib + +1.0.0 (2012-06-23) + + - Cleaned up and packed Neon library, used already in production. + Added usage files, improved documentation. diff --git a/node_modules/neon/README.markdown b/node_modules/neon/README.markdown new file mode 100644 index 0000000..2e7d4bf --- /dev/null +++ b/node_modules/neon/README.markdown @@ -0,0 +1,76 @@ += Neon + +== JavaScript DSL for Classical Inheritance + +This files provides a DSL for the following design patterns: + +* inheritance +* interface +* module + +Neon packs a DSL for Class creation, that helps in making programs following an object oriented design. + +The philosophy is that it should not try to emulate other languages, so it preserves the JavaScript good parts, +but with a nicer syntax to create classes that ensure interfaces and include reusable functionality as modules. + +== Why another Class System? + +As the web applications are getting more complex these times, backend and frontend engineers work has fusioned, and they need to be able to establish a common language. It was created for people coming from OOP languages like Ruby to Javascript. + +=== Usage + + Interface('Editable')({ + constructor : ['x'], + prototype : ['x'] + }); + + Module('Composition')({ + y : 5, + prototype : { + z : 3 + } + }); + + Module('Other')({ + a : 5, + prototype : { + b : 3 + } + }); + + Class('Overlay').inherits(Widget).ensures(Editable).includes(Composition, Other)({ + html : '
', + prototype : { + init : function (element){ + if(!element){ + element = document.createElement('div'); + element.innerHTML = 'hello'; + document.body.appendChild(element); + } + }, + b : 5 + } + }); + +== License + +Copyright (c) 2009 Fernando Trasviña + +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/neon/neon.js b/node_modules/neon/neon.js new file mode 100644 index 0000000..bf0b94c --- /dev/null +++ b/node_modules/neon/neon.js @@ -0,0 +1,234 @@ + +if (typeof global === "undefined") { + global = window; +} + +global.Interface = function Interface(nameOrNameSpace, name) { + var nameSpace, interfaceName, factory; + nameSpace = (nameOrNameSpace && name) ? nameOrNameSpace : this; + interfaceName = (nameOrNameSpace && name) ? name : + (nameOrNameSpace) ? nameOrNameSpace : 'interface' + Math.random().toString(); + factory = function(definition) { + definition.isInterface = true; + definition.name = interfaceName; + nameSpace[interfaceName] = definition; + return nameSpace[interfaceName]; + }; + return factory; +}; + +global.Module = function Module(nameOrNameSpace, name) { + var nameSpace, moduleName, factory, newModule; + + nameSpace = (nameOrNameSpace && name) ? nameOrNameSpace : this; + moduleName = (nameOrNameSpace && name) ? name : + (nameOrNameSpace) ? nameOrNameSpace : 'module' + Math.random().toString(); + + newModule = { + moduleName : moduleName, + prototype : {}, + __includedModules : [], + include : function(module) { + var property; + for (property in module) { + if (module.hasOwnProperty(property) + && property !== 'prototype' + && property !== 'isModule' + && property !== '__includedModules' + && property !== 'include' + && property !== 'moduleName') { + newModule[property] = module[property]; + } + } + + if (module.hasOwnProperty('prototype') && module.prototype) { + for (property in module.prototype) { + if (module.prototype.hasOwnProperty(property)) { + newModule.prototype[property] = module.prototype[property]; + } + } + } + else { + module.prototype = {}; + } + + this.__includedModules.push(module); + + return this; + } + } + + factory = function(definition){ + var property; + + newModule.isModule = true; + + for (property in definition) { + if (definition.hasOwnProperty(property) + && property !== 'prototype' + && property !== 'isModule' + && property !== '__includedModules' + && property !== 'include' + && property !== 'moduleName') { + newModule[property] = definition[property]; + } + } + + if (definition.hasOwnProperty('prototype') && definition.prototype) { + for (property in definition.prototype) { + if (definition.prototype.hasOwnProperty(property)) { + newModule.prototype[property] = definition.prototype[property]; + } + } + } + + nameSpace[moduleName] = newModule; + + return nameSpace[moduleName]; + }; + + factory.includes = function () { + for(var i = 0; i < arguments.length; i++){ + newModule.include(arguments[i]); + } + return factory; + }; + + return factory; +}; + +global.Class = function Class(classNameOrNameSpace, className) { + var nameSpace, newClass, classFactory; + nameSpace = (classNameOrNameSpace && className) ? classNameOrNameSpace : global; + className = (classNameOrNameSpace && className) ? className : + (classNameOrNameSpace) ? classNameOrNameSpace : 'class' + Math.random().toString(); + + newClass = function() { + if (this.init) { + this.init.apply(this, arguments); + } + }; + + newClass.__descendants = []; + newClass.__implementedInterfaces = []; + newClass.__includedModules = []; + newClass.className = className; + newClass.include = function(module) { + var property; + for (property in module) { + if (module.hasOwnProperty(property) + && property != 'prototype' + && property != 'constructor' + && property != 'isModule' + && property != 'superClass' + && property != 'include') { + newClass[property] = module[property]; + } + } + + if (module.hasOwnProperty('prototype') && module.prototype) { + for (property in module.prototype) { + if (module.prototype.hasOwnProperty(property)) { + newClass.prototype[property] = module.prototype[property]; + } + } + } else { + module.prototype = {}; + } + + newClass.__includedModules.push(module); + return this; + }; + + classFactory = function(classDefinition) { + var i, il, j, jl, property, classPrototype = classDefinition.prototype; + if (classPrototype) { + for (property in classPrototype) { + if (classPrototype.hasOwnProperty(property)) { + newClass.prototype[property] = classPrototype[property]; + } + } + delete classDefinition.prototype; + } + for (property in classDefinition) { + if (classDefinition.hasOwnProperty(property)) { + newClass[property] = classDefinition[property]; + } + } + + for (i = 0, il = newClass.__implementedInterfaces.length; i < il; i++) { + for (j = 0, jl = newClass.__implementedInterfaces[i].constructor.length; j < jl; j++) { + if (!newClass[ newClass.__implementedInterfaces[i].constructor[j] ]) { + console.log('must implement static ' + newClass.__implementedInterfaces[i].name); + break; + } + } + + if (newClass.__implementedInterfaces[i].hasOwnProperty('prototype') + && newClass.__implementedInterfaces[i].prototype) { + for (j = 0, jl = newClass.__implementedInterfaces[i].prototype.length; j < jl; j++) { + if (!newClass.prototype[newClass.__implementedInterfaces[i].prototype[j]]) { + console.log('must implement prototype ' + newClass.__implementedInterfaces[i].name); + break; + } + } + } + } + + try { + if (Li && Li.ObjectSpy && Li.Spy) { + newClass.__objectSpy = new Li.ObjectSpy(); + newClass.__objectSpy.spy(newClass); + newClass.__objectSpy.spy(newClass.prototype); + } + } catch (error) {} + + nameSpace[className] = newClass; + return newClass; + }; + + classFactory.inherits = function(superClass) { + var i, inheritedClass; + newClass.superClass = superClass; + if (superClass.hasOwnProperty('__descendants')) { + superClass.__descendants.push(newClass); + } + inheritedClass = function() { + }; + inheritedClass.prototype = superClass.prototype; + newClass.prototype = new inheritedClass(); + newClass.prototype.constructor = newClass; + + for (i in superClass) { + if (superClass.hasOwnProperty(i) + && i != 'prototype' + && i !== 'className' + && i !== 'superClass' + && i !== 'include' + && i != '__descendants') { + newClass[i] = superClass[i]; + } + } + + delete this.inherits; + return this; + }; + + classFactory.ensures = function(interfaces) { + for (var i = 0; i < arguments.length; i++) { + newClass.__implementedInterfaces.push(arguments[i]); + } + delete this.ensures; + return classFactory; + }; + + classFactory.includes = function() { + for (var i = 0; i < arguments.length; i++) { + newClass.include(arguments[i]); + } + return classFactory; + }; + + return classFactory; + +}; diff --git a/node_modules/neon/package.json b/node_modules/neon/package.json new file mode 100644 index 0000000..aa60775 --- /dev/null +++ b/node_modules/neon/package.json @@ -0,0 +1,55 @@ +{ + "name": "neon", + "version": "2.0.0", + "description": "Javascript DSL for Classical Inheritance", + "main": "./neon", + "directories": { + "lib": "./lib" + }, + "repository": { + "type": "git", + "url": "https://github.com/azendal/neon.git" + }, + "keywords": [ + "class", + "prototype", + "inheritance", + "oop" + ], + "bugs": { + "url": "https://github.com/azendal/neon/issues" + }, + "_id": "neon@2.0.0", + "dist": { + "shasum": "eb70092c57fb03e2201c3682aed5b54ab9ed1316", + "tarball": "http://registry.npmjs.org/neon/-/neon-2.0.0.tgz" + }, + "_from": "neon@", + "_npmVersion": "1.2.25", + "_npmUser": { + "name": "chubas", + "email": "chubas7@gmail.com" + }, + "maintainers": [ + { + "name": "siedrix", + "email": "siedrix@gmail.com" + }, + { + "name": "benbeltran", + "email": "ben@nsovocal.com" + }, + { + "name": "chubas", + "email": "chubas7@gmail.com" + }, + { + "name": "azendal", + "email": "trasvina@gmail.com" + } + ], + "_shasum": "eb70092c57fb03e2201c3682aed5b54ab9ed1316", + "_resolved": "https://registry.npmjs.org/neon/-/neon-2.0.0.tgz", + "readme": "ERROR: No README data found!", + "homepage": "https://github.com/azendal/neon" +} diff --git a/node_modules/neon/stdlib/bubbling_support.js b/node_modules/neon/stdlib/bubbling_support.js new file mode 100644 index 0000000..30e0f5d --- /dev/null +++ b/node_modules/neon/stdlib/bubbling_support.js @@ -0,0 +1,32 @@ +Module('BubblingSupport')({ + dispatch : function (type, data) { + data = data || {}; + var event = CustomEventSupport.prototype.dispatch.call(this, type, data); + if (event.isPropagationStopped === false) { + if (this.parent && this.parent.dispatch) { + data.target = event.target; + data.currentTarget = this.parent; + this.parent.dispatch(event.type, data); + } + } + return event; + }, + + prototype : { + dispatch : function (type, data) { + data = data || {}; + + var event = CustomEventSupport.prototype.dispatch.call(this, type, data); + + if (event.isPropagationStopped === false && event.bubbles === true) { + if (this.parent && this.parent.dispatch) { + data.target = event.target; + data.currentTarget = this.parent; + this.parent.dispatch(event.type, data); + } + } + + return event; + } + } + }); diff --git a/node_modules/neon/stdlib/custom_event.js b/node_modules/neon/stdlib/custom_event.js new file mode 100644 index 0000000..c3c033c --- /dev/null +++ b/node_modules/neon/stdlib/custom_event.js @@ -0,0 +1,37 @@ +Class('CustomEvent')({ + prototype : { + bubbles : true, + cancelable : true, + currentTarget : null, + timeStamp : 0, + target : null, + type : '', + isPropagationStopped : false, + isDefaultPrevented : false, + isImmediatePropagationStopped : false, + areImmediateHandlersPrevented : false, + init : function init(type, data) { + this.type = type; + if (typeof data !== 'undefined') { + for(var property in data) { + if (data.hasOwnProperty(property)) { + this[property] = data[property]; + } + } + } + }, + stopPropagation : function stopPropagation() { + this.isPropagationStopped = true; + }, + preventDefault : function preventDefault() { + this.isDefaultPrevented = true; + }, + stopImmediatePropagation : function stopImmediatePropagation() { + this.preventImmediateHandlers(); + this.stopPropagation(); + }, + preventImmediateHandlers : function preventImmediateHandlers() { + this.areImmediateHandlersPrevented = true; + } + } +}); diff --git a/node_modules/neon/stdlib/custom_event_support.js b/node_modules/neon/stdlib/custom_event_support.js new file mode 100644 index 0000000..fecbd71 --- /dev/null +++ b/node_modules/neon/stdlib/custom_event_support.js @@ -0,0 +1,180 @@ +Module('CustomEventSupport')({ + + eventListeners : null, + + bind : function(type, eventHandler) { + var found, i, listeners; + + if(!this.eventListeners) { + this.eventListeners = {}; + } + + if(!this.eventListeners[type]) { + this.eventListeners[type] = []; + } + + found = false; + + listeners = this.eventListeners[type]; + for (i = 0; i < listeners.length; i++) { + if (listeners[i] === eventHandler) { + found = true; + break; + } + } + + if(!found) { + this.eventListeners[type].push(eventHandler); + } + + return this; + }, + + unbind : function(type, eventHandler) { + var i, found, listeners; + + found = false; + + if(!this.eventListeners) { + this.eventListeners = {}; + } + + if(typeof eventHandler == 'undefined') { + this.eventListeners[type] = []; + } + + listeners = this.eventListeners[type]; + for (i = 0; i < listeners.length; i++) { + if(listeners[i] === eventHandler) { + found = true; + break; + } + } + + if(found) { + this.eventListeners[type].splice(i, 1); + } + + return this; + }, + + dispatch : function(type, data) { + var event, listeners, instance, i; + + if (this.eventListeners === null) { + this.eventListeners = {}; + } + + if (typeof data === 'undefined') { + data = {}; + } + + if (data.hasOwnProperty('target') === false) { + data.target = this; + } + + event = new CustomEvent(type, data); + listeners = this.eventListeners[type] || []; + instance = this; + + for (i = 0; i < listeners.length; i = i + 1) { + listeners[i].call(instance, event); + if (event.areImmediateHandlersPrevented === true) { + break; + } + } + + return event; + }, + + prototype : { + + eventListeners : null, + + bind : function(type, eventHandler) { + var found, i, listeners; + + if(!this.eventListeners) { + this.eventListeners = {}; + } + + if(!this.eventListeners[type]) { + this.eventListeners[type] = []; + } + + found = false; + + listeners = this.eventListeners[type]; + for (i = 0; i < listeners.length; i++) { + if(listeners[i] === eventHandler) { + found = true; + break; + } + } + + if(!found) { + this.eventListeners[type].push(eventHandler); + } + + return this; + }, + + unbind : function(type, eventHandler) { + var i, found, listeners; + + found = false; + i = 0; + + if(!this.eventListeners) { + this.eventListeners = {}; + } + + if(typeof eventHandler == 'undefined') { + this.eventListeners[type] = []; + } + + listeners = this.eventListeners[type]; + for (i = 0; i < listeners.length; i++) { + if(listeners[i] == eventHandler) { + found = true; + break; + } + } + + if(found) { + this.eventListeners[type].splice(i, 1); + } + + return this; + }, + + dispatch : function(type, data) { + var event, listeners, instance, i; + + if (this.eventListeners === null) { + this.eventListeners = {}; + } + + if (typeof data === 'undefined') { + data = {}; + } + + if (data.hasOwnProperty('target') === false) { + data.target = this; + } + + event = new CustomEvent(type, data); + listeners = this.eventListeners[type] || []; + instance = this; + + for (i = 0; i < listeners.length; i = i + 1) { + listeners[i].call(instance, event); + if (event.areImmediateHandlersPrevented === true) { + break; + } + } + + return event; + } + } +}); diff --git a/node_modules/neon/stdlib/index.js b/node_modules/neon/stdlib/index.js new file mode 100644 index 0000000..862193b --- /dev/null +++ b/node_modules/neon/stdlib/index.js @@ -0,0 +1,7 @@ +// This file is node only +if(typeof require !== 'undefined'){ + require('./custom_event'); + require('./custom_event_support'); + require('./node_support'); + require('./bubbling_support'); +} diff --git a/node_modules/neon/stdlib/node_support.js b/node_modules/neon/stdlib/node_support.js new file mode 100644 index 0000000..b1e9473 --- /dev/null +++ b/node_modules/neon/stdlib/node_support.js @@ -0,0 +1,123 @@ +Module('NodeSupport')({ + prototype : { + parent : null, + + children : [], + + appendChild : function(child) { + if(child.parent) { + child.parent.removeChild(child); + } + + if(!this.hasOwnProperty('children')) { + this.children = []; + } + + this.children.push(child); + this[child.name] = child; + child.setParent(this); + return child; + }, + + insertBefore : function (child, beforeChild) { + var position; + + if (child.parent) { + child.parent.removeChild(child); + } + + if (!this.hasOwnProperty('children')) { + this.children = []; + } + + if (typeof beforeChild === 'undefined') { + this.appendChild(child); + } else { + position = this.children.indexOf(beforeChild); + this.children.splice(position, 0, child); + + this[child.name] = child; + child.setParent(this); + } + + return child; + + }, + + insertChild : function(child, position) { + console.warn('NodeSupport insertChild method is deprecated, try insertBefore'); + + if (child.parent) { + child.parent.removeChild(child); + } + + if (!this.hasOwnProperty('children')) { + this.children = []; + } + + if (typeof position == 'undefined') { + this.children.push(child); + this[child.name] = child; + child.setParent(this); + return child; + } + + this.children.splice(position, 0, child); + this[child.name] = child; + child.setParent(this); + return child; + }, + + removeChild : function (child) { + var position = this.children.indexOf(child); + + if (position !== -1) { + this.children.splice(position, 1); + delete this[child.name]; + child.parent = null; + } + + return child; + }, + + setParent : function (parent) { + this.parent = parent; + return this; + }, + + getDescendants : function () { + var nodes = []; + this.children.forEach(function (node) { + nodes.push(node); + }); + this.children.forEach(function (node) { + nodes = nodes.concat(node.getDescendants()); + }); + return nodes; + }, + + getPreviousSibling : function () { + if (typeof this.parent === 'undefined') { + return; + } + + if (this.parent.children[0] === this) { + return; + } + + return this.parent.children[ this.parent.children.indexOf(this) - 1 ]; + }, + + getNextSibling : function () { + if (typeof this.parent === 'undefined') { + return; + } + + if (this.parent.children[ this.parent.children.length - 1 ] === this) { + return; + } + + return this.parent.children[ this.parent.children.indexOf(this) + 1 ]; + } + } +}); diff --git a/node_modules/neon/test/neon_browser.html b/node_modules/neon/test/neon_browser.html new file mode 100644 index 0000000..9b3d15a --- /dev/null +++ b/node_modules/neon/test/neon_browser.html @@ -0,0 +1,11 @@ + + + + Neon + + + + +

Neon

+ + diff --git a/node_modules/neon/test/neon_stdlib_browser.html b/node_modules/neon/test/neon_stdlib_browser.html new file mode 100644 index 0000000..fd585a0 --- /dev/null +++ b/node_modules/neon/test/neon_stdlib_browser.html @@ -0,0 +1,15 @@ + + + + Neon + + + + + + + + +

Neon

+ + diff --git a/node_modules/neon/test/neon_stdlib_test.js b/node_modules/neon/test/neon_stdlib_test.js new file mode 100644 index 0000000..bba9445 --- /dev/null +++ b/node_modules/neon/test/neon_stdlib_test.js @@ -0,0 +1,84 @@ +// @TODO: Make proper spec'ing and testing for these modules +if(typeof require !== 'undefined') { + console.log("Requiring neon stdlib from file"); + require('neon'); + require('neon/stdlib'); +} + +console.log("CustomEvent ", typeof CustomEvent !== 'undefined'); +console.log("CustomEventSupport ", typeof CustomEventSupport !== 'undefined'); +console.log("NodeSupport ", typeof NodeSupport !== 'undefined'); +console.log("BubblingSupport ", typeof BubblingSupport !== 'undefined'); + +console.log("--- node support") + +Class('TreeNode').includes(NodeSupport)({ + prototype : { + init : function(name) { + this.name = name; + } + } +}); + +var root = new TreeNode('root'); + +console.log(root); + +var left = new TreeNode('left'); +var right = new TreeNode('right'); + +root.appendChild(left); +right.setParent(root); + +console.log(root.children.indexOf(left)); +console.log(left == right.parent.left); + +Class('X').includes(CustomEventSupport)({ + prototype : { + init : function() { + + } + } +}); + +console.log('--- custom event support'); + +var sender = new X(); + +sender.dispatch('alert', { message : 'ERROR: nobody should be receiving yet' }); +sender.bind('alert', function(event) { + console.log(event.message == 'TEST'); +}); + +sender.dispatch('alert', { message : 'TEST' }); + +console.log('--- bubbling support'); + +Class('BubblingTreeNode').includes(NodeSupport, CustomEventSupport, BubblingSupport)({ + prototype : { + init : function(name) { + this.name = name; + this.bind('alert', function(event) { + console.log("Bound to alert on init (" + this.name + ")"); + }); + } + } +}); + +var root = new BubblingTreeNode('root'); +var son = root.appendChild(new BubblingTreeNode('son')); +var grandson = son.appendChild(new BubblingTreeNode('grandson')); + +console.log("Bubbles up"); +grandson.dispatch('alert'); + +console.log("Doesn't bubble down"); +root.dispatch('alert'); + +// @ TODO : Leave this tests to azendal, I have to read the browser's propagation spec +// console.log("Prevent default"); +// son.bind('alert', function(event) { +// console.log(event); +// event.preventImmediatePropagation(); +// }); +// grandson.dispatch('alert'); diff --git a/node_modules/neon/test/neon_test.js b/node_modules/neon/test/neon_test.js new file mode 100644 index 0000000..d49a7b4 --- /dev/null +++ b/node_modules/neon/test/neon_test.js @@ -0,0 +1,64 @@ +if(typeof require !== 'undefined') { // We are in Node, need to require the file + + console.log("Requiring neon from file"); + require('neon'); + // In Coffeescript, the following construct is recommended + // { Class, Module, Interface } = require('neon') +} + + +console.log('Class :', typeof Class); +console.log('Module :', typeof Module); +console.log('Interface :', typeof Interface); + +Module('Composition')({ + moduleClassVariable : 1, + prototype : { + moduleInstanceVariable : 2 + } +}); + +Interface('Contract')({ + constructor : ['ensuredClassVariable'], + prototype : ['ensuredInstanceVariable'] +}); + +Class('BaseClass')({ + baseClassVariable : 3, + prototype : { + baseInstanceVariable : 4 + } +}); + +var AnonymousModule = Module()({ + anonymousClassVariable : 5, + prototype : { + anonymousInstanceVariable : 6 + } +}); + +Class('MyClass').inherits(BaseClass).ensures(Contract).includes(Composition, AnonymousModule)({ + GREETING : 'HELLO', + inheritedClassVariable : 7, + ensuredClassVariable : 8, + prototype : { + inheritedInstanceVariable : 9, + ensuredInstanceVariable : 10, + init : function(argument) { + console.log(this.constructor.GREETING + ' ' + argument + '!'); + } + } +}); + +var instance = new MyClass('world'); +console.log(MyClass.moduleClassVariable); +console.log(instance.moduleInstanceVariable); +console.log(MyClass.baseClassVariable); +console.log(instance.baseInstanceVariable); +console.log(MyClass.anonymousClassVariable); +console.log(instance.anonymousInstanceVariable); +console.log(MyClass.inheritedClassVariable); +console.log(MyClass.ensuredClassVariable); +console.log(instance.inheritedInstanceVariable); +console.log(instance.ensuredInstanceVariable); + diff --git a/node_modules/tellurium/CHANGELOG.md b/node_modules/tellurium/CHANGELOG.md new file mode 100644 index 0000000..50a8a6a --- /dev/null +++ b/node_modules/tellurium/CHANGELOG.md @@ -0,0 +1,5 @@ +2.0.0 (2014-02-15) + + - Changed FirebugLogger for a console logger as the default one + - Requires new major version of neon, and follows the same pattern for + requiring tellurium \ No newline at end of file diff --git a/node_modules/tellurium/README.md b/node_modules/tellurium/README.md new file mode 100644 index 0000000..a7066a9 --- /dev/null +++ b/node_modules/tellurium/README.md @@ -0,0 +1,242 @@ + +----+ + | Te | + +----+ + +Tellurium is a JavaScript Testing Framework using testing patterns like Mock, Stub, and Spy. + +## Features: + +* Support asynchronous specifications by default +* Support syncronous specifications via .sync() +* Support Scripted test by default +* Support guided tests via .guided() +* ... (yes there is more but why dont you give it a try?) + +This framework tries to go as close as possible with EcmaScript behaviour. so if you used anothers language +testing frameworks you may find that some of your tools are not here but trust me its better this way. + +## Does it work? +Yes Tellurium is tested with Tellurium + +## Is is used for other projects? +Yes it is but not many yet. but it really works, if not pls send me an issue or a msg. + +## Ok how can I use it? + + var someObj = { + good : true; + }; + + Tellurium.suite('my first test')({ + this.specify('someObj must be good')({ + this.assert(someObj.good).toBe(true); + }); + }); + + Tellurium.run(); + +## Theory of Operation + +Tellurium was designed to do front-end testing. this is a very important thing to consider because environment is very different from server side environments, so there is a number of objects that may be colliding and interacting to form a web application. Complex web applications tend to be event driven and not so much procedural because of the interaction of the user, network, and other events happening on the system in different order and on different times. + +Creating such system is not very easy to organize but there was some work done before and following the principle of unix of having small units of code that perform one task well, Tellurium has a number of dependencies instead of trying to build everything from the ground up. + +## Testing + +* **Test Method** + + Where do we put our test code? + + *We encode each test as a single Test Method on some class.* + +* **Four-Phase Test** (Setup -> Exercise -> Verify -> Teardown) + + How do we structure our test logic to make what we are testing obvious? + + *We structure each test with four distinct parts executed in sequence.* + +* **Assertion Method** + + How do we make tests self-checking? + + *We call a utility method to evaluate whether an expected outcome has been achieved.* + +* **Assertion Message** + + How do we structure our test logic to know which assertion failed? + + *We include a descriptive string argument in each call to an Assertion Method.* + +* **Testcase** + + Where do we put our test code? + + *Class We group a set of related Test Methods on a single Testcase Class.* + +* **Test Runner** + + How do we run the tests? + + *We define an application that instantiates a Test Suite Object and executes all the Testcase Objects it contains.* + +* **Testcase Object** + + How do we run the tests? + + *We create a Command object for each test and call the run method when we wish to execute it.* + +* **Test Suite Object** + + How do we run the tests when we have many tests to run? + + *We define a collection class that implements the standard test interface and use it to run a set of related Testcase Objects.* + +* **Test Discovery** + + How does the Test Runner know which tests to run? + + The Test Automation Framework discovers all tests that belong to the test suite automatically. + +* **Test Enumeration** + + How does the Test Runner know which tests to run? + + The test automater manually writes the code that enumerates all tests that belong to the test suite. + +* **Test Selection** + + How does the Test Runner know which tests to run? + + *The Test Automation Framework selects the Test Methods to be run at runtime based on attributes of the tests.* + +## This Library is based on the xUnit Test Patterns Book. + +* **Stub** + + How can we verify logic independently when it depends on indirect inputs from other software components? + + *We replace a real object with a test-specific object that feeds the desired indirect inputs into the system under test.* + +* **Spy** + + How do we implement Behavior Verification? How can we verify logic independently when it has indirect outputs to other software components? + + *We use a Test Double to capture the indirect output calls made to another component by the SUT for later verification by the test.* + +* **Mock** + + How do we implement Behavior Verification for indirect outputs of the SUT? How can we verify logic independently when it depends on indirect inputs from other software components? + + *We replace an object on which the SUT depends on with a test-specific object that verifies it is being used correctly by the SUT.* + +* **Assertion** + + How do we make tests self-checking? + + *We call a utility method to evaluate whether an expected outcome has been achieved.* + +* **Fresh Fixture Setup** + + * **Inline-Setup** + + How do we construct the Fresh Fixture? + + *Each Test Method creates its own Fresh Fixture by calling the appropriate constructor methods to build exactly the test fixture it requires.* + + * **Delegated Setup** + + How do we construct the Fresh Fixture? + + *Each Test Method creates its own Fresh Fixture by calling Creation Methods from within the Test Methods.* + + * **Creation Method** + How do we construct the Fresh Fixture? + + *We set up the test fixture by calling methods that hide the mechanics of building ready-to-use objects behind Intent-Revealing Names.* + + * **Implicit Setup** + + How do we construct the Fresh Fixture? + + *We build the test fixture common to several tests in the setUp method.* + +* **Shared Fixture Construction** + + * **Prebuilt Fixture** + + How do we cause the Shared Fixture to be built before the first test method that needs it? + + *We build the Shared Fixture separately from running the tests.* + + * **Lazy Setup** + + How do we cause the Shared Fixture to be built before the first test method that needs it? + + *We use Lazy Initialization of the fixture to create it in the first test that needs it.* + + * **Suite Fixture Setup** + + How do we cause the Shared Fixture to be built before the first test method that needs it? + + *We build/destroy the shared fixture in special methods called by the Test Automation Framework before/after the first/last Test Method is called.* + + * **Setup Decorator** + + How do we cause the Shared Fixture to be built before the first test method that needs it? + + *We wrap the test suite with a Decorator that sets up the shared test fixture before running the tests and tears it down after all tests are done.* + + * **Chained Tests** + + How do we cause the Shared Fixture to be built before the first test method that needs it? + + *We let the other tests in a test suite set up the test fixture.* + +## Testing Strategies + +* **Recorded Test** + + How do we prepare automated tests for our software? + + *We automate tests by recording interactions with the application and playing them back using a test tool.* + +* **Scripted Test** + + How do we prepare automated tests for our software? + + *We automate the tests by writing test programs by hand.* + +* **Data-Driven Test** + + How do we prepare automated tests for our software? How do we reduce Test Code Duplication? + + *We store all the information needed for each test in a data file and write an interpreter that reads the file and executes the tests.* + +* **Guided Test** + + How do we prepare automated tests for our software? How do we not forget a test? + + *We combine scripted or data-driven test with something similar to a recorded test (but that recorded process cannot dupplicate). and guide the tester trough the tests.* + + + +### Dependencies + +* Neon (Object Organization DSL) +* CustomEvent (Synthetic events for objects) +* CustomEventSupport (Includable module to give the ability of customEvents to an object) + +### Objects from Tellurium + +* Tellurium (<> <> <>. is the initial point of almost all operations); +* Tellurium.Stub (<>. Mechanism to define a non implemented property) +* Tellurium.Stub.Factory (<>. Provides Stub functionality to an Object) +* Tellurium.Spy +* Tellurium.Spy.Factory +* Tellurium.Assertion +* Tellurium.Context +* Tellurium.Suite +* Tellurium.Description +* Tellurium.Specification +* Tellurium.Reporter + diff --git a/node_modules/tellurium/build/tellurium-min.js b/node_modules/tellurium/build/tellurium-min.js new file mode 100644 index 0000000..bb8de46 --- /dev/null +++ b/node_modules/tellurium/build/tellurium-min.js @@ -0,0 +1 @@ +var Te=Module("Tellurium")({children:[],completedChildren:[],isCompleted:false,reporter:null,suite:function(b){var a=function(d){var c=new Tellurium.Suite(b,d);c.setParent(Tellurium);Tellurium.children.push(c);return c};return a},run:function(c){var b,a,d;this.completedChildren=[];this.isCompleted=false;if(typeof c==="string"){c=[c]}if(c){for(a=0;a0)},toBeCalledWith:function(a){return(this.actual.called[0].arguments===a)},toReturn:function(a){return(this.actual.called[0].returned===a)},toBeGreaterThan:function(a){return(this.actual>a)},toBeLessThan:function(a){return(this.actual + + + Tellurium Test Runner + + + + + + + + + + + + + + + diff --git a/node_modules/tellurium/tellurium.js b/node_modules/tellurium/tellurium.js new file mode 100644 index 0000000..2eeda6b --- /dev/null +++ b/node_modules/tellurium/tellurium.js @@ -0,0 +1,901 @@ +if(typeof require !== 'undefined') { + require('neon'); +} + +Module('Tellurium')({ + children : [], + completedChildren : [], + isCompleted : false, + reporter : null, + + suite : function (description) { + var factory = function (code) { + var suite = new Tellurium.Suite(description, code); + suite.setParent(Tellurium); + Tellurium.children.push(suite); + return suite; + }; + + return factory; + }, + + run : function (ids) { + var i, j, id; + + this.completedChildren = []; + this.isCompleted = false; + + if (typeof ids === 'string') { + ids = [ids]; + } + + if (ids) { + for (j = 0; j < ids.length; j += 1) { + id = ids[j]; + for (i = 0; i < this.children.length; i += 1) { + if (this.children[i].description === id) { + console.time('run ' + this.children[i].description); + this.children[i].run(); + } + } + } + } else { + console.time('run all'); + for (i = 0; i < this.children.length; i += 1) { + Tellurium.children[i].run(); + } + } + + return this; + }, + + childCompleted : function (child) { + this.completedChildren.push(child); + + if (this.reporter === null) { + this.reporter = new Tellurium.Reporter.Console(); + } + // console.timeEnd('run ' + child.description); + this.reporter.run(child); + + if (this.children.length === this.completedChildren.length) { + this.completed(); + } + + return this; + }, + + completed : function () { + this.isCompleted = true; + // console.timeEnd('run all'); + return this; + } +}); + +Class(Tellurium, 'Stub')({ + prototype : { + targetObject : null, + methodName : null, + newMethod : null, + originalMethod : null, + + init : function (config) { + config = config || {}; + + this.targetObject = config.targetObject; + this.methodName = config.methodName; + this.newMethod = config.newMethod; + }, + + applyStub : function () { + this.originalMethod = this.targetObject[this.methodName]; + this.targetObject[this.methodName] = this.newMethod; + return this; + }, + + removeStub : function () { + this.targetObject[this.methodName] = this.originalMethod; + return this; + }, + + on : function (targetObject) { + this.targetObject = targetObject; + return this; + }, + + method : function (methodName) { + this.methodName = methodName; + return this; + }, + + using : function (newMethod) { + this.newMethod = newMethod; + this.applyStub(); + return this; + } + } +}); + +Module(Tellurium.Stub, 'Factory')({ + prototype : { + stubs : null, + + stub : function () { + var stub = new Tellurium.Stub(); + this.stubs = this.stubs || []; + this.stubs.push(stub); + return stub; + }, + + cleanStubs : function () { + var i; + + for (i = 0; i < this.stubs.length; i += 1) { + this.stubs[i].removeStub(); + } + + return this; + } + } +}); + +Class(Tellurium, 'Spy')({ + prototype : { + targetObject : null, + methodName : null, + spyMethod : null, + originalMethod : null, + objectHasMethod : null, + called : null, + + init : function (config) { + config = config || {}; + + this.called = []; + this.targetObject = config.targetObject; + this.methodName = config.methodName; + }, + + applySpy : function () { + var spy; + + spy = this; + if (this.targetObject.hasOwnProperty(this.methodName) === false) { + this.objectHasMethod = false; + } + else { + this.objectHasMethod = true; + } + + this.originalMethod = this.targetObject[this.methodName]; + + this.targetObject[this.methodName] = function () { + var args, result; + args = Array.prototype.slice.call(arguments, 0, arguments.length); + var scope = this; + + if (this === spy) { + scope = spy.targetObject; + } + + var startTime = Date.now(); + result = spy.originalMethod.apply(scope, args); + var endTime = Date.now(); + + spy.called.push({ + arguments : args, + returned : result, + time : endTime - startTime + }); + return result; + }; + return this; + }, + + removeSpy : function () { + if (this.objectHasMethod === true) { + this.targetObject[this.methodName] = this.originalMethod; + } + else { + delete this.targetObject[this.methodName]; + } + return this; + }, + + on : function (targetObject) { + this.targetObject = targetObject; + return this; + }, + + method : function (methodName) { + this.methodName = methodName; + this.applySpy(); + return this; + } + } +}); + +Module(Tellurium.Spy, 'Factory')({ + prototype : { + spies : null, + spy : function () { + var spy = new Tellurium.Spy(); + this.spies = this.spies || []; + this.spies.push(spy); + return spy; + }, + + cleanSpies : function () { + var i; + + for (i = 0; i < this.spies.length; i += 1) { + this.spies[i].removeSpy(); + } + + return this; + } + } +}); + +Class(Tellurium, 'Assertion')({ + includeAssertions : function (assertions) { + var assertion; + for (assertion in assertions) { + if (assertions.hasOwnProperty(assertion)) { + this.prototype.addAssert(assertion, assertions[assertion]); + } + } + + return this; + }, + + prototype : { + TYPE_TRUE : 'TYPE_TRUE', + TYPE_FALSE : 'TYPE_FALSE', + STATUS_FAIL : 'STATUS_FAIL', + STATUS_SUCCESS : 'STATUS_SUCCESS', + actual : null, + expected : null, + spec : null, + status : null, + type : null, + label : null, + + init : function (actual, spec) { + this.type = this.TYPE_TRUE; + this.actual = actual; + this.spec = spec; + }, + + withLabel : function (label) { + this.label = label; + return this; + }, + + not : function () { + this.type = this.TYPE_FALSE; + return this; + }, + + notify : function (assertResult) { + if (assertResult === true) { + if (this.type === this.TYPE_FALSE) { + this.status = this.STATUS_FAIL; + this.spec.assertionFailed(this); + } else { + this.status = this.STATUS_SUCCESS; + this.spec.assertionPassed(this); + } + } else { + if (this.type === this.TYPE_FALSE) { + this.status = this.STATUS_SUCCESS; + this.spec.assertionPassed(this); + } else { + this.status = this.STATUS_FAIL; + this.spec.assertionFailed(this); + } + } + + return this; + }, + + addAssert : function (name, assertFn) { + this[name] = function () { + var args; + + args = Array.prototype.slice.call(arguments, 0, arguments.length); + this.invoked = name; + this.expected = args; + this.notify(assertFn.apply(this, args)); + return this; + }; + + return this; + } + } +}); + +Tellurium.Assertion.includeAssertions({ + toBe : function (expected) { + return (this.actual === expected); + }, + + toEqual : function (expected) { + return (this.actual == expected); + }, + + toMatch : function (expected) { + return (expected.test(this.actual) === true); + }, + + toBeDefined : function () { + return (typeof this.actual !== 'undefined'); + }, + + toBeNull : function () { + return (this.actual === null); + }, + + toBeTruthy : function () { + return ((this.actual) ? true : false); + }, + + toBeCalled : function () { + return (this.actual.called.length > 0); + }, + + toBeCalledWith : function (expected) { + return (this.actual.called[0].arguments === expected); + }, + + toReturn : function (expected) { + return (this.actual.called[0].returned === expected); + }, + + toBeGreaterThan : function (expected) { + return (this.actual > expected); + }, + + toBeLessThan : function (expected) { + return (this.actual < expected); + }, + + toBeInstanceOf : function (expected) { + return (this.actual.constructor === expected); + }, + + toThrowError : function (expected) { + try { + this.actual(); + } catch (e) { + if (e === expected || e.name === expected) { + return true; + } + } + return false; + }, + + toNotThrowError : function () { + try { + this.actual(); + return true; + } catch (e) { + return false; + } + } +}); + +Module(Tellurium, 'Context')({ + prototype : { + registry : null, + description : null, + code : null, + parent : null, + children : null, + completedChildren : null, + setupCode : null, + tearDownCode : null, + beforeEachPool : null, + completedBeforeEach : null, + afterEachPool : null, + completedAfterEach : null, + isCompleted : null, + + init : function (description, code) { + this.registry = []; + this.description = description; + this.code = code; + this.children = []; + this.completedChildren = []; + this.beforeEachPool = []; + this.completedBeforeEach = []; + this.completedAfterEach = []; + this.afterEachPool = []; + this.isCompleted = false; + }, + + appendChild : function (child) { + if (child.parent) { + child.parent.removeChild(child); + } + + this.children.push(child); + child.setParent(this); + + return child; + }, + + setParent : function (parent) { + this.parent = parent; + + return this; + }, + + setup : function (code) { + this.setupCode = new Tellurium.Executable(code); + return this; + }, + + tearDown : function (code) { + this.tearDownCode = new Tellurium.Executable(code); + return this; + }, + + describe : function (description) { + var current, fn, guided; + + current = this; + + fn = function (code) { + var describe = new Tellurium.Description(description, code); + + if (guided === true) { + describe.guided = true; + var index = 0; + describe.run = function () { + this.code.call(this, this); + + if (this.children.length === 0) { + this.completed(); + } + + if (this.setupCode) { + this.setupCode.run(); + } + + if (this.children[index] instanceof Tellurium.Specification) { + this.runBeforeEach(this, this.children[index]); + } + + this.children[index].run(); + + return this; + }; + + describe.childCompleted = function (child) { + this.completedChildren.push(child); + + if (child instanceof Tellurium.Specification) { + this.runAfterEach(child); + } + + if (this.children.length === this.completedChildren.length) { + this.completed(); + } else { + index = index + 1; + if (this.children[index] instanceof Tellurium.Specification) { + this.runBeforeEach(this, this.children[index]); + } + this.children[index].run(); + } + + return this; + }; + } else { + describe.guided = false; + } + + current.appendChild(describe); + + return current; + }; + + fn.guided = function () { + guided = true; + return fn; + }; + + return fn; + }, + + specify : function (description) { + var current = this; + var sync = false; + var fn = function (code) { + var specification = new Tellurium.Specification(description, code); + specification.sync = sync; + current.appendChild(specification); + }; + + fn.sync = function () { + sync = true; + return fn; + }; + + return fn; + }, + + beforeEach : function (code) { + this.beforeEachPool.push(code); + + return this; + }, + + afterEach : function (code) { + this.afterEachPool.push(code); + + return this; + }, + + run : function () { + var i, context; + + context = this; + this.children = []; + this.completedChildren = []; + + this.code.call(this, this); + + if (this.children.length === 0) { + this.completed(); + } + + if (this.setupCode) { + this.setupCode.onCompleted(function () { + for (i = 0; i < context.children.length; i += 1) { + if (context.children[i] instanceof Tellurium.Specification) { + context.runBeforeEach(context, context.children[i]); + } + context.children[i].run(); + } + }); + this.setupCode.run(); + } else { + for (i = 0; i < this.children.length; i += 1) { + if (this.children[i] instanceof Tellurium.Specification || this.children[i] instanceof Tellurium.Description) { + this.runBeforeEach(this.children[i], this); + } + this.children[i].run(); + } + } + + return this; + }, + + runBeforeEach : function (target, context) { + var i; + + context = context || this; + + if (this.parent && this.parent.runBeforeEach) { + this.parent.runBeforeEach(target, context); + } + + for (i = 0; i < this.beforeEachPool.length; i += 1) { + this.beforeEachPool[i].call(target, target, context); + } + + return this; + }, + + runAfterEach : function (target, context) { + var i; + + context = context || this; + + if (this.parent && this.parent.runAfterEach) { + this.parent.runAfterEach(target, context); + } + + for (i = 0; i < this.afterEachPool.length; i += 1) { + this.afterEachPool[i].call(target, target, context); + } + + return this; + }, + + childCompleted : function (child) { + this.completedChildren.push(child); + + if (child instanceof Tellurium.Specification || child instanceof Tellurium.Description) { + this.runAfterEach(child, this); + } + + if (this.children.length === this.completedChildren.length) { + this.completed(); + } + + return this; + }, + + completed : function () { + var context; + + context = this; + + this.isCompleted = true; + + if (this.spies) { + this.cleanSpies(); + } + + if (this.stubs) { + this.cleanStubs(); + } + + if (this.tearDownCode) { + this.tearDownCode.onCompleted(function () { + if (context.parent) { + context.parent.childCompleted(context); + } + }); + this.tearDownCode.run(); + } else { + if (this.parent) { + this.parent.childCompleted(this); + } + } + + return this; + } + } +}); + +Class(Tellurium, 'Executable')({ + prototype : { + code : null, + isCompleted : null, + isAsynchronous : true, + + init : function (code) { + this.code = code; + }, + + completed : function () { + this.isCompleted = true; + this.onCompletedCode(); + return this; + }, + + run : function () { + this.isCompleted = false; + this.code.apply(this); + return this; + }, + + onCompleted : function (code) { + this.onCompletedCode = function () { + code(); + return this; + }; + return this; + } + } +}); + +Class(Tellurium, 'Suite').includes(Tellurium.Context, Tellurium.Stub.Factory, Tellurium.Spy.Factory)({}); + +Class(Tellurium, 'Description').includes(Tellurium.Context, Tellurium.Stub.Factory, Tellurium.Spy.Factory)({ + prototype : { + guided : false + } +}); + +Class(Tellurium, 'Specification').includes(Tellurium.Stub.Factory, Tellurium.Spy.Factory)({ + prototype : { + STATUS_PENDING : 'STATUS_PENDING', + STATUS_FAIL : 'STATUS_FAIL', + STATUS_SUCCESS : 'STATUS_SUCCESS', + description : null, + code : null, + parent : null, + assertions : null, + registry : null, + status : null, + isCompleted : null, + sync : false, + + init : function (description, code) { + this.description = description; + this.code = code; + this.registry = {}; + this.assertions = []; + this.spies = []; + this.stubs = []; + this.isCompleted = false; + }, + + setParent : function (parent) { + this.parent = parent; + return this; + }, + + run : function () { + if (this.code) { + this.code.call(this, this); + if (this.sync === true) { + this.completed(); + } + } else { + this.pending(); + } + }, + + pending : function () { + this.status = this.STATUS_PENDING; + this.completed(); + }, + + assertionPassed : function () { + if (this.status !== this.STATUS_FAIL) { + this.status = this.STATUS_SUCCESS; + } + + return this; + }, + + assertionFailed : function () { + this.status = this.STATUS_FAIL; + + return this; + }, + + assert : function (actual) { + + if (this.isCompleted === true) { + throw "called assert on a completed test"; + } + + var assertion = new Tellurium.Assertion(actual, this); + this.assertions.push(assertion); + return assertion; + }, + + mock : function () { + return {}; + }, + + completed : function () { + + if (this.isCompleted === true) { + throw "called completed more than once for test"; + } + + this.isCompleted = true; + + if (this.spies) { + this.cleanSpies(); + } + + if (this.stubs) { + this.cleanStubs(); + } + + if (this.status === null) { + this.status = this.STATUS_SUCCESS; + } + + this.parent.childCompleted(this); + + return this; + } + } +}); + +Tellurium.Reporter = {}; + +/* + * Standard console, nothing fancy. Override this one or create one, + * depending on your needs + */ +Class(Tellurium.Reporter, 'Console')({ + prototype : { + totalSpecs : null, + failedSpecs : null, + passedSpecs : null, + pendingSpecs : null, + + init : function () { + this.totalSpecs = 0; + this.failedSpecs = 0; + this.passedSpecs = 0; + this.pendingSpecs = 0; + }, + + run : function (suite) { + console.log("==========================="); + console.log('Tellurium Test Results for ' + suite.description); + this.totalSpecs = 0; + this.passedSpecs = 0; + this.failedSpecs = 0; + this.pendingSpecs = 0; + + this.suite(suite); + console.info('Total: ', this.totalSpecs); + console.info('Passed: ', this.passedSpecs); + console.info('Failed: ' + this.failedSpecs); + console.warn('Pending: ', this.pendingSpecs); + console.log("==========================="); + }, + + suite : function (suite) { + var i; + + console.log(' ' + suite.description); + + for (i = 0; i < suite.children.length; i += 1) { + if (suite.children[i] instanceof Tellurium.Description) { + this.description(suite.children[i]); + } else if (suite.children[i] instanceof Tellurium.Specification) { + this.specification(suite.children[i]); + } + } + }, + + description : function (description) { + var i; + console.log(' ' + description.description); + + for (i = 0; i < description.children.length; i += 1) { + if (description.children[i] instanceof Tellurium.Description) { + this.description(description.children[i]); + } else if (description.children[i] instanceof Tellurium.Specification) { + this.specification(description.children[i]); + } + } + + }, + + specification : function (specification) { + var i; + + this.totalSpecs = this.totalSpecs + 1; + + if (specification.status === specification.STATUS_FAIL) { + this.failedSpecs = this.failedSpecs + 1; + console.log("FAIL " + specification.description); + } else if (specification.status === specification.STATUS_SUCCESS) { + this.passedSpecs = this.passedSpecs + 1; + console.log("PASS " + specification.description); + } else if (specification.status === specification.STATUS_PENDING) { + this.pendingSpecs = this.pendingSpecs + 1; + console.log("PENDING " + specification.description); + } + + console.log("Assertions:"); + for (i = 0; i < specification.assertions.length; i += 1) { + this.assertion(specification.assertions[i]); + } + + }, + + assertion : function (assertion) { + var not; + if (assertion.type === Tellurium.Assertion.prototype.TYPE_FALSE) { + not = ' not '; + } else { + not = ' '; + } + + if (assertion.status === assertion.STATUS_SUCCESS) { + console.log(" " + assertion.label + " " + assertion.actual); + console.log(" " + assertion.label + " " + assertion.actual + + not + assertion.invoked + ' ' + (assertion.expected) ? assertion.expected : ''); + } else if (assertion.status === assertion.STATUS_FAIL) { + console.log(" " + assertion.label + " " + assertion.actual + + not + assertion.invoked + ' ' + (assertion.expected) ? assertion.expected : ''); + } + } + } +}); + diff --git a/spec/spec/argon/storage/mongodb.js b/spec/spec/argon/storage/mongodb.js new file mode 100644 index 0000000..ec5c3fd --- /dev/null +++ b/spec/spec/argon/storage/mongodb.js @@ -0,0 +1,76 @@ +var client = require('mongodb').MongoClient, + setupSuite; + +require('neon'); +require('neon/stdlib'); +require('../../../../argon'); +require('../../../../vendor/validation_support'); +require('../../../../argon/model'); +require('../../../../argon/association'); +require('../../../../argon/storage'); +require('../../../../argon/storage/mongodb'); +require('tellurium'); + +setupSuite = function setupSuite(db) { + Tellurium.suite('MongoDB Storage')(function(){ + var storage = new Argon.Storage.MongoDB({ + driver : db, + collectionName : 'test' + }); + + this.describe('create records')(function () { + + this.specify('should create a valid record')(function () { + var spec = this; + storage.create({data : {a : 'a'}}, function (data) { + spec.assert(data.a).toBe('a'); + spec.completed(); + }); + }); + + this.specify('should apply preprocessors')(function () { + var spec = this; + storage.preprocessors.push(function (data) { + data.preprocessor = true; + return data; + }); + + storage.create({data : {a : 'a'}}, function (data) { + spec.assert(data.preprocessor).toBe(true); + spec.completed(); + }); + }); + + this.specify('should apply processors')(function () { + var spec = this; + + storage.processors.push(function (data) { + data.processor = true; + return data; + }); + + storage.create({data : {a : 'a'}}, function (data) { + spec.assert(data.processor).toBe(true); + spec.completed(); + }); + }); + + }); + }); +}; + +client.connect("mongodb://localhost:27017/argon_test", function handleConnection(error, db) { + + if (error) { + console.log("Could not conenct to mongo"); + return; + }; + + var collection = db.collection('test'); + + collection.remove({}, function (error, data) { + setupSuite(db); + Tellurium.run(); + }); + +}); From 6085d7658a1f5f47ead30e732cb551e607550f93 Mon Sep 17 00:00:00 2001 From: Gus Ortiz Date: Wed, 7 Jan 2015 21:06:53 -0600 Subject: [PATCH 2/4] Remove node_modules and add to gitignore --- .gitignore | 2 + node_modules/mongodb/.gitmodules | 0 node_modules/mongodb/.travis.yml | 5 - node_modules/mongodb/CONTRIBUTING.md | 23 - node_modules/mongodb/LICENSE | 201 - node_modules/mongodb/Makefile | 28 - node_modules/mongodb/Readme.md | 418 -- node_modules/mongodb/index.js | 1 - node_modules/mongodb/lib/mongodb/admin.js | 340 -- .../mongodb/lib/mongodb/aggregation_cursor.js | 187 - .../mongodb/lib/mongodb/auth/mongodb_cr.js | 81 - .../lib/mongodb/auth/mongodb_gssapi.js | 172 - .../mongodb/lib/mongodb/auth/mongodb_plain.js | 79 - .../mongodb/lib/mongodb/auth/mongodb_scram.js | 250 - .../mongodb/lib/mongodb/auth/mongodb_sspi.js | 156 - .../mongodb/lib/mongodb/auth/mongodb_x509.js | 68 - .../mongodb/lib/mongodb/collection.js | 676 --- .../lib/mongodb/collection/aggregation.js | 318 -- .../lib/mongodb/collection/batch/common.js | 439 -- .../lib/mongodb/collection/batch/ordered.js | 530 -- .../lib/mongodb/collection/batch/unordered.js | 576 -- .../lib/mongodb/collection/commands.js | 139 - .../mongodb/lib/mongodb/collection/core.js | 800 --- .../mongodb/lib/mongodb/collection/geo.js | 78 - .../mongodb/lib/mongodb/collection/index.js | 72 - .../mongodb/lib/mongodb/collection/query.js | 218 - .../mongodb/lib/mongodb/collection/shared.js | 120 - .../mongodb/lib/mongodb/command_cursor.js | 362 -- .../lib/mongodb/commands/base_command.js | 29 - .../lib/mongodb/commands/db_command.js | 101 - .../lib/mongodb/commands/delete_command.js | 129 - .../lib/mongodb/commands/get_more_command.js | 88 - .../lib/mongodb/commands/insert_command.js | 161 - .../mongodb/commands/kill_cursor_command.js | 98 - .../lib/mongodb/commands/query_command.js | 296 - .../lib/mongodb/commands/update_command.js | 189 - .../mongodb/lib/mongodb/connection/base.js | 515 -- .../lib/mongodb/connection/connection.js | 563 -- .../lib/mongodb/connection/connection_pool.js | 305 -- .../mongodb/connection/connection_utils.js | 23 - .../mongodb/lib/mongodb/connection/mongos.js | 578 -- .../lib/mongodb/connection/read_preference.js | 67 - .../lib/mongodb/connection/repl_set/ha.js | 448 -- .../mongodb/connection/repl_set/options.js | 126 - .../mongodb/connection/repl_set/repl_set.js | 830 --- .../connection/repl_set/repl_set_state.js | 74 - .../repl_set/strategies/ping_strategy.js | 366 -- .../strategies/statistics_strategy.js | 93 - .../mongodb/lib/mongodb/connection/server.js | 945 ---- .../mongodb/connection/server_capabilities.js | 48 - .../lib/mongodb/connection/url_parser.js | 265 - node_modules/mongodb/lib/mongodb/cursor.js | 1038 ---- .../mongodb/lib/mongodb/cursorstream.js | 167 - node_modules/mongodb/lib/mongodb/db.js | 2179 -------- .../mongodb/lib/mongodb/gridfs/chunk.js | 232 - .../mongodb/lib/mongodb/gridfs/grid.js | 104 - .../mongodb/lib/mongodb/gridfs/gridstore.js | 1570 ------ .../mongodb/lib/mongodb/gridfs/readstream.js | 206 - node_modules/mongodb/lib/mongodb/index.js | 62 - .../mongodb/lib/mongodb/mongo_client.js | 482 -- .../lib/mongodb/responses/mongo_reply.js | 83 - node_modules/mongodb/lib/mongodb/scope.js | 86 - node_modules/mongodb/lib/mongodb/utils.js | 286 - .../mongodb/node_modules/bson/.travis.yml | 4 - .../mongodb/node_modules/bson/LICENSE | 201 - .../mongodb/node_modules/bson/Makefile | 19 - .../mongodb/node_modules/bson/README.md | 45 - .../mongodb/node_modules/bson/binding.gyp | 18 - .../node_modules/bson/browser_build/bson.js | 4843 ----------------- .../bson/browser_build/package.json | 8 - .../mongodb/node_modules/bson/build/Makefile | 350 -- .../build/Release/.deps/Release/bson.node.d | 1 - .../Release/obj.target/bson/ext/bson.o.d | 26 - .../node_modules/bson/build/Release/bson.node | Bin 58484 -> 0 bytes .../bson/build/Release/linker.lock | 0 .../build/Release/obj.target/bson/ext/bson.o | Bin 336876 -> 0 bytes .../node_modules/bson/build/binding.Makefile | 6 - .../node_modules/bson/build/bson.target.mk | 154 - .../node_modules/bson/build/config.gypi | 119 - .../node_modules/bson/build/gyp-mac-tool | 512 -- .../node_modules/bson/build_browser.js | 7 - .../mongodb/node_modules/bson/builderror.log | 4 - .../mongodb/node_modules/bson/ext/Makefile | 28 - .../mongodb/node_modules/bson/ext/bson.cc | 1072 ---- .../mongodb/node_modules/bson/ext/bson.h | 278 - .../mongodb/node_modules/bson/ext/index.js | 40 - .../bson/ext/win32/ia32/bson.node | Bin 113664 -> 0 bytes .../node_modules/bson/ext/win32/x64/bson.node | Bin 130560 -> 0 bytes .../mongodb/node_modules/bson/ext/wscript | 39 - .../node_modules/bson/lib/bson/binary.js | 343 -- .../bson/lib/bson/binary_parser.js | 385 -- .../node_modules/bson/lib/bson/bson.js | 1573 ------ .../node_modules/bson/lib/bson/bson_new.js | 776 --- .../node_modules/bson/lib/bson/code.js | 24 - .../node_modules/bson/lib/bson/db_ref.js | 31 - .../node_modules/bson/lib/bson/double.js | 33 - .../bson/lib/bson/float_parser.js | 121 - .../node_modules/bson/lib/bson/index.js | 74 - .../node_modules/bson/lib/bson/long.js | 854 --- .../node_modules/bson/lib/bson/max_key.js | 13 - .../node_modules/bson/lib/bson/min_key.js | 13 - .../node_modules/bson/lib/bson/objectid.js | 266 - .../node_modules/bson/lib/bson/symbol.js | 48 - .../node_modules/bson/lib/bson/timestamp.js | 853 --- .../node_modules/bson/node_modules/nan/.dntrc | 30 - .../bson/node_modules/nan/CHANGELOG.md | 200 - .../bson/node_modules/nan/LICENSE | 46 - .../bson/node_modules/nan/README.md | 1054 ---- .../bson/node_modules/nan/appveyor.yml | 32 - .../bson/node_modules/nan/include_dirs.js | 1 - .../node_modules/bson/node_modules/nan/nan.h | 2331 -------- .../bson/node_modules/nan/package.json | 79 - .../mongodb/node_modules/bson/package.json | 76 - .../mongodb/node_modules/bson/tools/gleak.js | 21 - .../bson/tools/jasmine-1.1.0/MIT.LICENSE | 20 - .../bson/tools/jasmine-1.1.0/jasmine-html.js | 190 - .../bson/tools/jasmine-1.1.0/jasmine.css | 166 - .../bson/tools/jasmine-1.1.0/jasmine.js | 2476 --------- .../tools/jasmine-1.1.0/jasmine_favicon.png | Bin 905 -> 0 bytes .../mongodb/node_modules/kerberos/LICENSE | 201 - .../mongodb/node_modules/kerberos/README.md | 4 - .../mongodb/node_modules/kerberos/binding.gyp | 43 - .../node_modules/kerberos/build/Makefile | 350 -- .../obj.target/kerberos/lib/kerberos.o.d.raw | 15 - .../kerberos/build/binding.Makefile | 6 - .../node_modules/kerberos/build/config.gypi | 119 - .../node_modules/kerberos/build/gyp-mac-tool | 512 -- .../kerberos/build/kerberos.target.mk | 172 - .../node_modules/kerberos/builderror.log | 23 - .../mongodb/node_modules/kerberos/index.js | 6 - .../kerberos/lib/auth_processes/mongodb.js | 281 - .../node_modules/kerberos/lib/base64.c | 134 - .../node_modules/kerberos/lib/base64.h | 22 - .../node_modules/kerberos/lib/kerberos.cc | 591 -- .../node_modules/kerberos/lib/kerberos.h | 49 - .../node_modules/kerberos/lib/kerberos.js | 91 - .../kerberos/lib/kerberos_context.cc | 76 - .../kerberos/lib/kerberos_context.h | 48 - .../node_modules/kerberos/lib/kerberosgss.c | 693 --- .../node_modules/kerberos/lib/kerberosgss.h | 70 - .../mongodb/node_modules/kerberos/lib/sspi.js | 15 - .../node_modules/kerberos/lib/win32/base64.c | 121 - .../node_modules/kerberos/lib/win32/base64.h | 18 - .../kerberos/lib/win32/kerberos.cc | 53 - .../kerberos/lib/win32/kerberos.h | 60 - .../kerberos/lib/win32/kerberos_sspi.c | 244 - .../kerberos/lib/win32/kerberos_sspi.h | 106 - .../node_modules/kerberos/lib/win32/worker.cc | 7 - .../node_modules/kerberos/lib/win32/worker.h | 38 - .../lib/win32/wrappers/security_buffer.cc | 106 - .../lib/win32/wrappers/security_buffer.h | 47 - .../lib/win32/wrappers/security_buffer.js | 12 - .../wrappers/security_buffer_descriptor.cc | 185 - .../wrappers/security_buffer_descriptor.h | 45 - .../wrappers/security_buffer_descriptor.js | 3 - .../lib/win32/wrappers/security_context.cc | 871 --- .../lib/win32/wrappers/security_context.h | 72 - .../lib/win32/wrappers/security_context.js | 3 - .../win32/wrappers/security_credentials.cc | 351 -- .../lib/win32/wrappers/security_credentials.h | 67 - .../win32/wrappers/security_credentials.js | 22 - .../node_modules/kerberos/lib/worker.cc | 7 - .../node_modules/kerberos/lib/worker.h | 38 - .../kerberos/node_modules/nan/.dntrc | 30 - .../kerberos/node_modules/nan/CHANGELOG.md | 200 - .../kerberos/node_modules/nan/LICENSE | 46 - .../kerberos/node_modules/nan/README.md | 1054 ---- .../kerberos/node_modules/nan/appveyor.yml | 32 - .../kerberos/node_modules/nan/include_dirs.js | 1 - .../kerberos/node_modules/nan/nan.h | 2331 -------- .../kerberos/node_modules/nan/package.json | 79 - .../node_modules/kerberos/package.json | 55 - .../kerberos/test/kerberos_tests.js | 34 - .../kerberos/test/kerberos_win32_test.js | 19 - .../win32/security_buffer_descriptor_tests.js | 41 - .../test/win32/security_buffer_tests.js | 22 - .../test/win32/security_credentials_tests.js | 55 - .../node_modules/readable-stream/.npmignore | 5 - .../node_modules/readable-stream/LICENSE | 18 - .../node_modules/readable-stream/README.md | 15 - .../node_modules/readable-stream/duplex.js | 1 - .../readable-stream/lib/_stream_duplex.js | 89 - .../lib/_stream_passthrough.js | 46 - .../readable-stream/lib/_stream_readable.js | 982 ---- .../readable-stream/lib/_stream_transform.js | 210 - .../readable-stream/lib/_stream_writable.js | 386 -- .../node_modules/core-util-is/README.md | 3 - .../node_modules/core-util-is/float.patch | 604 -- .../node_modules/core-util-is/lib/util.js | 107 - .../node_modules/core-util-is/package.json | 54 - .../node_modules/core-util-is/util.js | 106 - .../node_modules/inherits/LICENSE | 16 - .../node_modules/inherits/README.md | 42 - .../node_modules/inherits/inherits.js | 1 - .../node_modules/inherits/inherits_browser.js | 23 - .../node_modules/inherits/package.json | 51 - .../node_modules/inherits/test.js | 25 - .../node_modules/isarray/README.md | 54 - .../node_modules/isarray/build/build.js | 209 - .../node_modules/isarray/component.json | 19 - .../node_modules/isarray/index.js | 3 - .../node_modules/isarray/package.json | 54 - .../node_modules/string_decoder/.npmignore | 2 - .../node_modules/string_decoder/LICENSE | 20 - .../node_modules/string_decoder/README.md | 7 - .../node_modules/string_decoder/index.js | 221 - .../node_modules/string_decoder/package.json | 54 - .../node_modules/readable-stream/package.json | 70 - .../readable-stream/passthrough.js | 1 - .../node_modules/readable-stream/readable.js | 8 - .../node_modules/readable-stream/transform.js | 1 - .../node_modules/readable-stream/writable.js | 1 - node_modules/mongodb/package.json | 252 - node_modules/neon/.npmignore | 1 - node_modules/neon/CHANGELOG.markdown | 22 - node_modules/neon/README.markdown | 76 - node_modules/neon/neon.js | 234 - node_modules/neon/package.json | 55 - node_modules/neon/stdlib/bubbling_support.js | 32 - node_modules/neon/stdlib/custom_event.js | 37 - .../neon/stdlib/custom_event_support.js | 180 - node_modules/neon/stdlib/index.js | 7 - node_modules/neon/stdlib/node_support.js | 123 - node_modules/neon/test/neon_browser.html | 11 - .../neon/test/neon_stdlib_browser.html | 15 - node_modules/neon/test/neon_stdlib_test.js | 84 - node_modules/neon/test/neon_test.js | 64 - node_modules/tellurium/CHANGELOG.md | 5 - node_modules/tellurium/README.md | 242 - node_modules/tellurium/build/tellurium-min.js | 1 - node_modules/tellurium/package.json | 44 - .../tellurium/reporters/firebug_reporter.js | 102 - node_modules/tellurium/spec/basic.js | 210 - node_modules/tellurium/spec/browser.html | 20 - node_modules/tellurium/tellurium.js | 901 --- 235 files changed, 2 insertions(+), 55294 deletions(-) create mode 100644 .gitignore delete mode 100644 node_modules/mongodb/.gitmodules delete mode 100644 node_modules/mongodb/.travis.yml delete mode 100644 node_modules/mongodb/CONTRIBUTING.md delete mode 100644 node_modules/mongodb/LICENSE delete mode 100644 node_modules/mongodb/Makefile delete mode 100644 node_modules/mongodb/Readme.md delete mode 100755 node_modules/mongodb/index.js delete mode 100644 node_modules/mongodb/lib/mongodb/admin.js delete mode 100644 node_modules/mongodb/lib/mongodb/aggregation_cursor.js delete mode 100644 node_modules/mongodb/lib/mongodb/auth/mongodb_cr.js delete mode 100644 node_modules/mongodb/lib/mongodb/auth/mongodb_gssapi.js delete mode 100644 node_modules/mongodb/lib/mongodb/auth/mongodb_plain.js delete mode 100644 node_modules/mongodb/lib/mongodb/auth/mongodb_scram.js delete mode 100644 node_modules/mongodb/lib/mongodb/auth/mongodb_sspi.js delete mode 100644 node_modules/mongodb/lib/mongodb/auth/mongodb_x509.js delete mode 100644 node_modules/mongodb/lib/mongodb/collection.js delete mode 100644 node_modules/mongodb/lib/mongodb/collection/aggregation.js delete mode 100644 node_modules/mongodb/lib/mongodb/collection/batch/common.js delete mode 100644 node_modules/mongodb/lib/mongodb/collection/batch/ordered.js delete mode 100644 node_modules/mongodb/lib/mongodb/collection/batch/unordered.js delete mode 100644 node_modules/mongodb/lib/mongodb/collection/commands.js delete mode 100644 node_modules/mongodb/lib/mongodb/collection/core.js delete mode 100644 node_modules/mongodb/lib/mongodb/collection/geo.js delete mode 100644 node_modules/mongodb/lib/mongodb/collection/index.js delete mode 100644 node_modules/mongodb/lib/mongodb/collection/query.js delete mode 100644 node_modules/mongodb/lib/mongodb/collection/shared.js delete mode 100644 node_modules/mongodb/lib/mongodb/command_cursor.js delete mode 100644 node_modules/mongodb/lib/mongodb/commands/base_command.js delete mode 100644 node_modules/mongodb/lib/mongodb/commands/db_command.js delete mode 100644 node_modules/mongodb/lib/mongodb/commands/delete_command.js delete mode 100644 node_modules/mongodb/lib/mongodb/commands/get_more_command.js delete mode 100644 node_modules/mongodb/lib/mongodb/commands/insert_command.js delete mode 100644 node_modules/mongodb/lib/mongodb/commands/kill_cursor_command.js delete mode 100644 node_modules/mongodb/lib/mongodb/commands/query_command.js delete mode 100644 node_modules/mongodb/lib/mongodb/commands/update_command.js delete mode 100644 node_modules/mongodb/lib/mongodb/connection/base.js delete mode 100644 node_modules/mongodb/lib/mongodb/connection/connection.js delete mode 100644 node_modules/mongodb/lib/mongodb/connection/connection_pool.js delete mode 100644 node_modules/mongodb/lib/mongodb/connection/connection_utils.js delete mode 100644 node_modules/mongodb/lib/mongodb/connection/mongos.js delete mode 100644 node_modules/mongodb/lib/mongodb/connection/read_preference.js delete mode 100644 node_modules/mongodb/lib/mongodb/connection/repl_set/ha.js delete mode 100644 node_modules/mongodb/lib/mongodb/connection/repl_set/options.js delete mode 100644 node_modules/mongodb/lib/mongodb/connection/repl_set/repl_set.js delete mode 100644 node_modules/mongodb/lib/mongodb/connection/repl_set/repl_set_state.js delete mode 100644 node_modules/mongodb/lib/mongodb/connection/repl_set/strategies/ping_strategy.js delete mode 100644 node_modules/mongodb/lib/mongodb/connection/repl_set/strategies/statistics_strategy.js delete mode 100644 node_modules/mongodb/lib/mongodb/connection/server.js delete mode 100644 node_modules/mongodb/lib/mongodb/connection/server_capabilities.js delete mode 100644 node_modules/mongodb/lib/mongodb/connection/url_parser.js delete mode 100644 node_modules/mongodb/lib/mongodb/cursor.js delete mode 100644 node_modules/mongodb/lib/mongodb/cursorstream.js delete mode 100644 node_modules/mongodb/lib/mongodb/db.js delete mode 100644 node_modules/mongodb/lib/mongodb/gridfs/chunk.js delete mode 100644 node_modules/mongodb/lib/mongodb/gridfs/grid.js delete mode 100644 node_modules/mongodb/lib/mongodb/gridfs/gridstore.js delete mode 100644 node_modules/mongodb/lib/mongodb/gridfs/readstream.js delete mode 100644 node_modules/mongodb/lib/mongodb/index.js delete mode 100644 node_modules/mongodb/lib/mongodb/mongo_client.js delete mode 100644 node_modules/mongodb/lib/mongodb/responses/mongo_reply.js delete mode 100644 node_modules/mongodb/lib/mongodb/scope.js delete mode 100644 node_modules/mongodb/lib/mongodb/utils.js delete mode 100644 node_modules/mongodb/node_modules/bson/.travis.yml delete mode 100644 node_modules/mongodb/node_modules/bson/LICENSE delete mode 100644 node_modules/mongodb/node_modules/bson/Makefile delete mode 100644 node_modules/mongodb/node_modules/bson/README.md delete mode 100644 node_modules/mongodb/node_modules/bson/binding.gyp delete mode 100644 node_modules/mongodb/node_modules/bson/browser_build/bson.js delete mode 100644 node_modules/mongodb/node_modules/bson/browser_build/package.json delete mode 100644 node_modules/mongodb/node_modules/bson/build/Makefile delete mode 100644 node_modules/mongodb/node_modules/bson/build/Release/.deps/Release/bson.node.d delete mode 100644 node_modules/mongodb/node_modules/bson/build/Release/.deps/Release/obj.target/bson/ext/bson.o.d delete mode 100755 node_modules/mongodb/node_modules/bson/build/Release/bson.node delete mode 100644 node_modules/mongodb/node_modules/bson/build/Release/linker.lock delete mode 100644 node_modules/mongodb/node_modules/bson/build/Release/obj.target/bson/ext/bson.o delete mode 100644 node_modules/mongodb/node_modules/bson/build/binding.Makefile delete mode 100644 node_modules/mongodb/node_modules/bson/build/bson.target.mk delete mode 100644 node_modules/mongodb/node_modules/bson/build/config.gypi delete mode 100755 node_modules/mongodb/node_modules/bson/build/gyp-mac-tool delete mode 100644 node_modules/mongodb/node_modules/bson/build_browser.js delete mode 100644 node_modules/mongodb/node_modules/bson/builderror.log delete mode 100644 node_modules/mongodb/node_modules/bson/ext/Makefile delete mode 100644 node_modules/mongodb/node_modules/bson/ext/bson.cc delete mode 100644 node_modules/mongodb/node_modules/bson/ext/bson.h delete mode 100644 node_modules/mongodb/node_modules/bson/ext/index.js delete mode 100644 node_modules/mongodb/node_modules/bson/ext/win32/ia32/bson.node delete mode 100644 node_modules/mongodb/node_modules/bson/ext/win32/x64/bson.node delete mode 100644 node_modules/mongodb/node_modules/bson/ext/wscript delete mode 100644 node_modules/mongodb/node_modules/bson/lib/bson/binary.js delete mode 100644 node_modules/mongodb/node_modules/bson/lib/bson/binary_parser.js delete mode 100644 node_modules/mongodb/node_modules/bson/lib/bson/bson.js delete mode 100644 node_modules/mongodb/node_modules/bson/lib/bson/bson_new.js delete mode 100644 node_modules/mongodb/node_modules/bson/lib/bson/code.js delete mode 100644 node_modules/mongodb/node_modules/bson/lib/bson/db_ref.js delete mode 100644 node_modules/mongodb/node_modules/bson/lib/bson/double.js delete mode 100644 node_modules/mongodb/node_modules/bson/lib/bson/float_parser.js delete mode 100644 node_modules/mongodb/node_modules/bson/lib/bson/index.js delete mode 100644 node_modules/mongodb/node_modules/bson/lib/bson/long.js delete mode 100644 node_modules/mongodb/node_modules/bson/lib/bson/max_key.js delete mode 100644 node_modules/mongodb/node_modules/bson/lib/bson/min_key.js delete mode 100644 node_modules/mongodb/node_modules/bson/lib/bson/objectid.js delete mode 100644 node_modules/mongodb/node_modules/bson/lib/bson/symbol.js delete mode 100644 node_modules/mongodb/node_modules/bson/lib/bson/timestamp.js delete mode 100644 node_modules/mongodb/node_modules/bson/node_modules/nan/.dntrc delete mode 100644 node_modules/mongodb/node_modules/bson/node_modules/nan/CHANGELOG.md delete mode 100644 node_modules/mongodb/node_modules/bson/node_modules/nan/LICENSE delete mode 100644 node_modules/mongodb/node_modules/bson/node_modules/nan/README.md delete mode 100644 node_modules/mongodb/node_modules/bson/node_modules/nan/appveyor.yml delete mode 100644 node_modules/mongodb/node_modules/bson/node_modules/nan/include_dirs.js delete mode 100644 node_modules/mongodb/node_modules/bson/node_modules/nan/nan.h delete mode 100644 node_modules/mongodb/node_modules/bson/node_modules/nan/package.json delete mode 100644 node_modules/mongodb/node_modules/bson/package.json delete mode 100644 node_modules/mongodb/node_modules/bson/tools/gleak.js delete mode 100644 node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/MIT.LICENSE delete mode 100644 node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine-html.js delete mode 100644 node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine.css delete mode 100644 node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine.js delete mode 100644 node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine_favicon.png delete mode 100644 node_modules/mongodb/node_modules/kerberos/LICENSE delete mode 100644 node_modules/mongodb/node_modules/kerberos/README.md delete mode 100644 node_modules/mongodb/node_modules/kerberos/binding.gyp delete mode 100644 node_modules/mongodb/node_modules/kerberos/build/Makefile delete mode 100644 node_modules/mongodb/node_modules/kerberos/build/Release/.deps/Release/obj.target/kerberos/lib/kerberos.o.d.raw delete mode 100644 node_modules/mongodb/node_modules/kerberos/build/binding.Makefile delete mode 100644 node_modules/mongodb/node_modules/kerberos/build/config.gypi delete mode 100755 node_modules/mongodb/node_modules/kerberos/build/gyp-mac-tool delete mode 100644 node_modules/mongodb/node_modules/kerberos/build/kerberos.target.mk delete mode 100644 node_modules/mongodb/node_modules/kerberos/builderror.log delete mode 100644 node_modules/mongodb/node_modules/kerberos/index.js delete mode 100644 node_modules/mongodb/node_modules/kerberos/lib/auth_processes/mongodb.js delete mode 100644 node_modules/mongodb/node_modules/kerberos/lib/base64.c delete mode 100644 node_modules/mongodb/node_modules/kerberos/lib/base64.h delete mode 100644 node_modules/mongodb/node_modules/kerberos/lib/kerberos.cc delete mode 100644 node_modules/mongodb/node_modules/kerberos/lib/kerberos.h delete mode 100644 node_modules/mongodb/node_modules/kerberos/lib/kerberos.js delete mode 100644 node_modules/mongodb/node_modules/kerberos/lib/kerberos_context.cc delete mode 100644 node_modules/mongodb/node_modules/kerberos/lib/kerberos_context.h delete mode 100644 node_modules/mongodb/node_modules/kerberos/lib/kerberosgss.c delete mode 100644 node_modules/mongodb/node_modules/kerberos/lib/kerberosgss.h delete mode 100644 node_modules/mongodb/node_modules/kerberos/lib/sspi.js delete mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/base64.c delete mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/base64.h delete mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos.cc delete mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos.h delete mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos_sspi.c delete mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos_sspi.h delete mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/worker.cc delete mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/worker.h delete mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.cc delete mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.h delete mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.js delete mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.cc delete mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.h delete mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.js delete mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.cc delete mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.h delete mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.js delete mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.cc delete mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.h delete mode 100644 node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.js delete mode 100644 node_modules/mongodb/node_modules/kerberos/lib/worker.cc delete mode 100644 node_modules/mongodb/node_modules/kerberos/lib/worker.h delete mode 100644 node_modules/mongodb/node_modules/kerberos/node_modules/nan/.dntrc delete mode 100644 node_modules/mongodb/node_modules/kerberos/node_modules/nan/CHANGELOG.md delete mode 100644 node_modules/mongodb/node_modules/kerberos/node_modules/nan/LICENSE delete mode 100644 node_modules/mongodb/node_modules/kerberos/node_modules/nan/README.md delete mode 100644 node_modules/mongodb/node_modules/kerberos/node_modules/nan/appveyor.yml delete mode 100644 node_modules/mongodb/node_modules/kerberos/node_modules/nan/include_dirs.js delete mode 100644 node_modules/mongodb/node_modules/kerberos/node_modules/nan/nan.h delete mode 100644 node_modules/mongodb/node_modules/kerberos/node_modules/nan/package.json delete mode 100644 node_modules/mongodb/node_modules/kerberos/package.json delete mode 100644 node_modules/mongodb/node_modules/kerberos/test/kerberos_tests.js delete mode 100644 node_modules/mongodb/node_modules/kerberos/test/kerberos_win32_test.js delete mode 100644 node_modules/mongodb/node_modules/kerberos/test/win32/security_buffer_descriptor_tests.js delete mode 100644 node_modules/mongodb/node_modules/kerberos/test/win32/security_buffer_tests.js delete mode 100644 node_modules/mongodb/node_modules/kerberos/test/win32/security_credentials_tests.js delete mode 100644 node_modules/mongodb/node_modules/readable-stream/.npmignore delete mode 100644 node_modules/mongodb/node_modules/readable-stream/LICENSE delete mode 100644 node_modules/mongodb/node_modules/readable-stream/README.md delete mode 100644 node_modules/mongodb/node_modules/readable-stream/duplex.js delete mode 100644 node_modules/mongodb/node_modules/readable-stream/lib/_stream_duplex.js delete mode 100644 node_modules/mongodb/node_modules/readable-stream/lib/_stream_passthrough.js delete mode 100644 node_modules/mongodb/node_modules/readable-stream/lib/_stream_readable.js delete mode 100644 node_modules/mongodb/node_modules/readable-stream/lib/_stream_transform.js delete mode 100644 node_modules/mongodb/node_modules/readable-stream/lib/_stream_writable.js delete mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/README.md delete mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/float.patch delete mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/lib/util.js delete mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/package.json delete mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/util.js delete mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/LICENSE delete mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/README.md delete mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/inherits.js delete mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/inherits_browser.js delete mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/package.json delete mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/test.js delete mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/README.md delete mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/build/build.js delete mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/component.json delete mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/index.js delete mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/package.json delete mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/.npmignore delete mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/LICENSE delete mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/README.md delete mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/index.js delete mode 100644 node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/package.json delete mode 100644 node_modules/mongodb/node_modules/readable-stream/package.json delete mode 100644 node_modules/mongodb/node_modules/readable-stream/passthrough.js delete mode 100644 node_modules/mongodb/node_modules/readable-stream/readable.js delete mode 100644 node_modules/mongodb/node_modules/readable-stream/transform.js delete mode 100644 node_modules/mongodb/node_modules/readable-stream/writable.js delete mode 100755 node_modules/mongodb/package.json delete mode 100644 node_modules/neon/.npmignore delete mode 100644 node_modules/neon/CHANGELOG.markdown delete mode 100644 node_modules/neon/README.markdown delete mode 100644 node_modules/neon/neon.js delete mode 100644 node_modules/neon/package.json delete mode 100644 node_modules/neon/stdlib/bubbling_support.js delete mode 100644 node_modules/neon/stdlib/custom_event.js delete mode 100644 node_modules/neon/stdlib/custom_event_support.js delete mode 100644 node_modules/neon/stdlib/index.js delete mode 100644 node_modules/neon/stdlib/node_support.js delete mode 100644 node_modules/neon/test/neon_browser.html delete mode 100644 node_modules/neon/test/neon_stdlib_browser.html delete mode 100644 node_modules/neon/test/neon_stdlib_test.js delete mode 100644 node_modules/neon/test/neon_test.js delete mode 100644 node_modules/tellurium/CHANGELOG.md delete mode 100644 node_modules/tellurium/README.md delete mode 100644 node_modules/tellurium/build/tellurium-min.js delete mode 100644 node_modules/tellurium/package.json delete mode 100644 node_modules/tellurium/reporters/firebug_reporter.js delete mode 100644 node_modules/tellurium/spec/basic.js delete mode 100644 node_modules/tellurium/spec/browser.html delete mode 100644 node_modules/tellurium/tellurium.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ce380c6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules/* +.DS_Store diff --git a/node_modules/mongodb/.gitmodules b/node_modules/mongodb/.gitmodules deleted file mode 100644 index e69de29..0000000 diff --git a/node_modules/mongodb/.travis.yml b/node_modules/mongodb/.travis.yml deleted file mode 100644 index a55b235..0000000 --- a/node_modules/mongodb/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -language: node_js -node_js: - - 0.8 - - 0.10 - - 0.11 \ No newline at end of file diff --git a/node_modules/mongodb/CONTRIBUTING.md b/node_modules/mongodb/CONTRIBUTING.md deleted file mode 100644 index c23e426..0000000 --- a/node_modules/mongodb/CONTRIBUTING.md +++ /dev/null @@ -1,23 +0,0 @@ -## Contributing to the driver - -### Bugfixes - -- Before starting to write code, look for existing [tickets](https://jira.mongodb.org/browse/NODE) or [create one](https://jira.mongodb.org/secure/CreateIssue!default.jspa) for your specific issue under the "Node Driver" project. That way you avoid working on something that might not be of interest or that has been addressed already in a different branch. -- Fork the [repo](https://github.com/mongodb/node-mongodb-native) _or_ for small documentation changes, navigate to the source on github and click the [Edit](https://github.com/blog/844-forking-with-the-edit-button) button. -- Follow the general coding style of the rest of the project: - - 2 space tabs - - no trailing whitespace - - comma last - - inline documentation for new methods, class members, etc - - 0 space between conditionals/functions, and their parenthesis and curly braces - - `if(..) {` - - `for(..) {` - - `while(..) {` - - `function(err) {` -- Write tests and make sure they pass (execute `npm test` from the cmd line to run the test suite). - -### Documentation - -To contribute to the [API documentation](http://mongodb.github.com/node-mongodb-native/) just make your changes to the inline documentation of the appropriate [source code](https://github.com/mongodb/node-mongodb-native/tree/master/docs) in the master branch and submit a [pull request](https://help.github.com/articles/using-pull-requests/). You might also use the github [Edit](https://github.com/blog/844-forking-with-the-edit-button) button. - -If you'd like to preview your documentation changes, first commit your changes to your local master branch, then execute `make generate_docs`. Make sure you have the python documentation framework sphinx installed `easy_install sphinx`. The docs are generated under `docs/build'. If all looks good, submit a [pull request](https://help.github.com/articles/using-pull-requests/) to the master branch with your changes. diff --git a/node_modules/mongodb/LICENSE b/node_modules/mongodb/LICENSE deleted file mode 100644 index 261eeb9..0000000 --- a/node_modules/mongodb/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/node_modules/mongodb/Makefile b/node_modules/mongodb/Makefile deleted file mode 100644 index 59d2bfe..0000000 --- a/node_modules/mongodb/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -NODE = node -NPM = npm -NODEUNIT = node_modules/nodeunit/bin/nodeunit -DOX = node_modules/dox/bin/dox -name = all - -total: build_native - -test_functional: - node test/runner.js -t functional - -test_ssl: - node test/runner.js -t ssl - -test_replicaset: - node test/runner.js -t replicaset - -test_sharded: - node test/runner.js -t sharded - -test_auth: - node test/runner.js -t auth - -generate_docs: - $(NODE) dev/tools/build-docs.js - make --directory=./docs/sphinx-docs --file=Makefile html - -.PHONY: total diff --git a/node_modules/mongodb/Readme.md b/node_modules/mongodb/Readme.md deleted file mode 100644 index 5e4877d..0000000 --- a/node_modules/mongodb/Readme.md +++ /dev/null @@ -1,418 +0,0 @@ -## MongoDB Node.JS Driver - -| what | where | -|---------------|------------------------------------------------| -| documentation | http://mongodb.github.io/node-mongodb-native/ | -| apidoc | http://mongodb.github.io/node-mongodb-native/ | -| source | https://github.com/mongodb/node-mongodb-native | -| mongodb | http://www.mongodb.org/ | - -### Blogs of Engineers involved in the driver -- Christian Kvalheim [@christkv](https://twitter.com/christkv) -- Valeri Karpov [@code_barbarian](https://twitter.com/code_barbarian) - -### Bugs / Feature Requests - -Think you’ve found a bug? Want to see a new feature in node-mongodb-native? Please open a -case in our issue management tool, JIRA: - -- Create an account and login . -- Navigate to the NODE project . -- Click **Create Issue** - Please provide as much information as possible about the issue type and how to reproduce it. - -Bug reports in JIRA for all driver projects (i.e. NODE, PYTHON, CSHARP, JAVA) and the -Core Server (i.e. SERVER) project are **public**. - -### Questions and Bug Reports - - * mailing list: https://groups.google.com/forum/#!forum/node-mongodb-native - * jira: http://jira.mongodb.org/ - -### Change Log - -http://jira.mongodb.org/browse/NODE - -## Install - -To install the most recent release from npm, run: - - npm install mongodb - -That may give you a warning telling you that bugs['web'] should be bugs['url'], it would be safe to ignore it (this has been fixed in the development version) - -To install the latest from the repository, run:: - - npm install path/to/node-mongodb-native - -## Live Examples - - -## Introduction - -This is a node.js driver for MongoDB. It's a port (or close to a port) of the library for ruby at http://github.com/mongodb/mongo-ruby-driver/. - -A simple example of inserting a document. - -```javascript - var MongoClient = require('mongodb').MongoClient - , format = require('util').format; - - MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) { - if(err) throw err; - - var collection = db.collection('test_insert'); - collection.insert({a:2}, function(err, docs) { - - collection.count(function(err, count) { - console.log(format("count = %s", count)); - }); - - // Locate all the entries using find - collection.find().toArray(function(err, results) { - console.dir(results); - // Let's close the db - db.close(); - }); - }); - }) -``` - -## Data types - -To store and retrieve the non-JSON MongoDb primitives ([ObjectID](http://www.mongodb.org/display/DOCS/Object+IDs), Long, Binary, [Timestamp](http://www.mongodb.org/display/DOCS/Timestamp+data+type), [DBRef](http://www.mongodb.org/display/DOCS/Database+References#DatabaseReferences-DBRef), Code). - -In particular, every document has a unique `_id` which can be almost any type, and by default a 12-byte ObjectID is created. ObjectIDs can be represented as 24-digit hexadecimal strings, but you must convert the string back into an ObjectID before you can use it in the database. For example: - -```javascript - // Get the objectID type - var ObjectID = require('mongodb').ObjectID; - - var idString = '4e4e1638c85e808431000003'; - collection.findOne({_id: new ObjectID(idString)}, console.log) // ok - collection.findOne({_id: idString}, console.log) // wrong! callback gets undefined -``` - -Here are the constructors the non-Javascript BSON primitive types: - -```javascript - // Fetch the library - var mongo = require('mongodb'); - // Create new instances of BSON types - new mongo.Long(numberString) - new mongo.ObjectID(hexString) - new mongo.Timestamp() // the actual unique number is generated on insert. - new mongo.DBRef(collectionName, id, dbName) - new mongo.Binary(buffer) // takes a string or Buffer - new mongo.Code(code, [context]) - new mongo.Symbol(string) - new mongo.MinKey() - new mongo.MaxKey() - new mongo.Double(number) // Force double storage -``` - -### The C/C++ bson parser/serializer - -If you are running a version of this library has the C/C++ parser compiled, to enable the driver to use the C/C++ bson parser pass it the option native_parser:true like below - -```javascript - // using native_parser: - MongoClient.connect('mongodb://127.0.0.1:27017/test' - , {db: {native_parser: true}}, function(err, db) {}) -``` - -The C++ parser uses the js objects both for serialization and deserialization. - -## GitHub information - -The source code is available at http://github.com/mongodb/node-mongodb-native. -You can either clone the repository or download a tarball of the latest release. - -Once you have the source you can test the driver by running - - $ node test/runner.js -t functional - -in the main directory. You will need to have a mongo instance running on localhost for the integration tests to pass. - -## Examples - -For examples look in the examples/ directory. You can execute the examples using node. - - $ cd examples - $ node queries.js - -## GridStore - -The GridStore class allows for storage of binary files in mongoDB using the mongoDB defined files and chunks collection definition. - -For more information have a look at [Gridstore](https://github.com/mongodb/node-mongodb-native/blob/master/docs/gridfs.md) - -## Replicasets - -For more information about how to connect to a replicaset have a look at the extensive documentation [Documentation](http://mongodb.github.com/node-mongodb-native/) - -### Primary Key Factories - -Defining your own primary key factory allows you to generate your own series of id's -(this could f.ex be to use something like ISBN numbers). The generated the id needs to be a 12 byte long "string". - -Simple example below - -```javascript - var MongoClient = require('mongodb').MongoClient - , format = require('util').format; - - // Custom factory (need to provide a 12 byte array); - CustomPKFactory = function() {} - CustomPKFactory.prototype = new Object(); - CustomPKFactory.createPk = function() { - return new ObjectID("aaaaaaaaaaaa"); - } - - MongoClient.connect('mongodb://127.0.0.1:27017/test', {'pkFactory':CustomPKFactory}, function(err, db) { - if(err) throw err; - - db.dropDatabase(function(err, done) { - - db.createCollection('test_custom_key', function(err, collection) { - - collection.insert({'a':1}, function(err, docs) { - - collection.find({'_id':new ObjectID("aaaaaaaaaaaa")}).toArray(function(err, items) { - console.dir(items); - // Let's close the db - db.close(); - }); - }); - }); - }); - }); -``` - -## Documentation - -If this document doesn't answer your questions, see the source of -[Collection](https://github.com/mongodb/node-mongodb-native/blob/master/lib/mongodb/collection.js) -or [Cursor](https://github.com/mongodb/node-mongodb-native/blob/master/lib/mongodb/cursor.js), -or the documentation at MongoDB for query and update formats. - -### Find - -The find method is actually a factory method to create -Cursor objects. A Cursor lazily uses the connection the first time -you call `nextObject`, `each`, or `toArray`. - -The basic operation on a cursor is the `nextObject` method -that fetches the next matching document from the database. The convenience -methods `each` and `toArray` call `nextObject` until the cursor is exhausted. - -Signatures: - -```javascript - var cursor = collection.find(query, [fields], options); - cursor.sort(fields).limit(n).skip(m). - - cursor.nextObject(function(err, doc) {}); - cursor.each(function(err, doc) {}); - cursor.toArray(function(err, docs) {}); - - cursor.rewind() // reset the cursor to its initial state. -``` - -Useful chainable methods of cursor. These can optionally be options of `find` instead of method calls: - - * `.limit(n).skip(m)` to control paging. - * `.sort(fields)` Order by the given fields. There are several equivalent syntaxes: - * `.sort({field1: -1, field2: 1})` descending by field1, then ascending by field2. - * `.sort([['field1', 'desc'], ['field2', 'asc']])` same as above - * `.sort([['field1', 'desc'], 'field2'])` same as above - * `.sort('field1')` ascending by field1 - -Other options of `find`: - -* `fields` the fields to fetch (to avoid transferring the entire document) -* `tailable` if true, makes the cursor [tailable](http://www.mongodb.org/display/DOCS/Tailable+Cursors). -* `batchSize` The number of the subset of results to request the database -to return for every request. This should initially be greater than 1 otherwise -the database will automatically close the cursor. The batch size can be set to 1 -with `batchSize(n, function(err){})` after performing the initial query to the database. -* `hint` See [Optimization: hint](http://www.mongodb.org/display/DOCS/Optimization#Optimization-Hint). -* `explain` turns this into an explain query. You can also call -`explain()` on any cursor to fetch the explanation. -* `snapshot` prevents documents that are updated while the query is active -from being returned multiple times. See more -[details about query snapshots](http://www.mongodb.org/display/DOCS/How+to+do+Snapshotted+Queries+in+the+Mongo+Database). -* `timeout` if false, asks MongoDb not to time out this cursor after an -inactivity period. - -For information on how to create queries, see the -[MongoDB section on querying](http://www.mongodb.org/display/DOCS/Querying). - -```javascript - var MongoClient = require('mongodb').MongoClient - , format = require('util').format; - - MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) { - if(err) throw err; - - var collection = db - .collection('test') - .find({}) - .limit(10) - .toArray(function(err, docs) { - console.dir(docs); - }); - }); -``` - -### Insert - -Signature: - -```javascript - collection.insert(docs, options, [callback]); -``` - -where `docs` can be a single document or an array of documents. - -Useful options: - -* `w:1` Should always set if you have a callback. - -See also: [MongoDB docs for insert](http://www.mongodb.org/display/DOCS/Inserting). - -```javascript - var MongoClient = require('mongodb').MongoClient - , format = require('util').format; - - MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) { - if(err) throw err; - - db.collection('test').insert({hello: 'world'}, {w:1}, function(err, objects) { - if (err) console.warn(err.message); - if (err && err.message.indexOf('E11000 ') !== -1) { - // this _id was already inserted in the database - } - }); - }); -``` - -Note that there's no reason to pass a callback to the insert or update commands -unless you use the `w:1` option. If you don't specify `w:1`, then -your callback will be called immediately. - -### Update: update and insert (upsert) - -The update operation will update the first document that matches your query -(or all documents that match if you use `multi:true`). -If `w:1`, `upsert` is not set, and no documents match, your callback will return 0 documents updated. - -See the [MongoDB docs](http://www.mongodb.org/display/DOCS/Updating) for -the modifier (`$inc`, `$set`, `$push`, etc.) formats. - -Signature: - -```javascript - collection.update(criteria, objNew, options, [callback]); -``` - -Useful options: - -* `w:1` Should always set if you have a callback. -* `multi:true` If set, all matching documents are updated, not just the first. -* `upsert:true` Atomically inserts the document if no documents matched. - -Example for `update`: - -```javascript - var MongoClient = require('mongodb').MongoClient - , format = require('util').format; - - MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) { - if(err) throw err; - - db.collection('test').update({hi: 'here'}, {$set: {hi: 'there'}}, {w:1}, function(err) { - if (err) console.warn(err.message); - else console.log('successfully updated'); - }); - }); -``` - -### Find and modify - -`findAndModify` is like `update`, but it also gives the updated document to -your callback. But there are a few key differences between findAndModify and -update: - - 1. The signatures differ. - 2. You can only findAndModify a single item, not multiple items. - -Signature: - -```javascript - collection.findAndModify(query, sort, update, options, callback) -``` - -The sort parameter is used to specify which object to operate on, if more than -one document matches. It takes the same format as the cursor sort (see -Connection.find above). - -See the -[MongoDB docs for findAndModify](http://www.mongodb.org/display/DOCS/findAndModify+Command) -for more details. - -Useful options: - -* `remove:true` set to a true to remove the object before returning -* `new:true` set to true if you want to return the modified object rather than the original. Ignored for remove. -* `upsert:true` Atomically inserts the document if no documents matched. - -Example for `findAndModify`: - -```javascript - var MongoClient = require('mongodb').MongoClient - , format = require('util').format; - - MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) { - if(err) throw err; - db.collection('test').findAndModify({hello: 'world'}, [['_id','asc']], {$set: {hi: 'there'}}, {}, function(err, object) { - if (err) console.warn(err.message); - else console.dir(object); // undefined if no matching object exists. - }); - }); -``` - -### Save - -The `save` method is a shorthand for upsert if the document contains an -`_id`, or an insert if there is no `_id`. - -## Release Notes - -See HISTORY - -## Credits - -1. [10gen](http://github.com/mongodb/mongo-ruby-driver/) -2. [Google Closure Library](http://code.google.com/closure/library/) -3. [Jonas Raoni Soares Silva](http://jsfromhell.com/classes/binary-parser) - -## Contributors - -Aaron Heckmann, Christoph Pojer, Pau Ramon Revilla, Nathan White, Emmerman, Seth LaForge, Boris Filipov, Stefan Schärmeli, Tedde Lundgren, renctan, Sergey Ukustov, Ciaran Jessup, kuno, srimonti, Erik Abele, Pratik Daga, Slobodan Utvic, Kristina Chodorow, Yonathan Randolph, Brian Noguchi, Sam Epstein, James Harrison Fisher, Vladimir Dronnikov, Ben Hockey, Henrik Johansson, Simon Weare, Alex Gorbatchev, Shimon Doodkin, Kyle Mueller, Eran Hammer-Lahav, Marcin Ciszak, François de Metz, Vinay Pulim, nstielau, Adam Wiggins, entrinzikyl, Jeremy Selier, Ian Millington, Public Keating, andrewjstone, Christopher Stott, Corey Jewett, brettkiefer, Rob Holland, Senmiao Liu, heroic, gitfy - -## License - - Copyright 2009 - 2013 MongoDb Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - diff --git a/node_modules/mongodb/index.js b/node_modules/mongodb/index.js deleted file mode 100755 index 4f59e9d..0000000 --- a/node_modules/mongodb/index.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('./lib/mongodb'); diff --git a/node_modules/mongodb/lib/mongodb/admin.js b/node_modules/mongodb/lib/mongodb/admin.js deleted file mode 100644 index c1f6eb5..0000000 --- a/node_modules/mongodb/lib/mongodb/admin.js +++ /dev/null @@ -1,340 +0,0 @@ -/*! - * Module dependencies. - */ -var Collection = require('./collection').Collection, - Cursor = require('./cursor').Cursor, - DbCommand = require('./commands/db_command').DbCommand, - utils = require('./utils'); - -/** - * Allows the user to access the admin functionality of MongoDB - * - * @class Represents the Admin methods of MongoDB. - * @param {Object} db Current db instance we wish to perform Admin operations on. - * @return {Function} Constructor for Admin type. - */ -function Admin(db) { - if(!(this instanceof Admin)) return new Admin(db); - - /** - * Retrieve the server information for the current - * instance of the db client - * - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from buildInfo or null if an error occured. - * @return {null} Returns no result - * @api public - */ - this.buildInfo = function(callback) { - this.serverInfo(callback); - } - - /** - * Retrieve the server information for the current - * instance of the db client - * - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from serverInfo or null if an error occured. - * @return {null} Returns no result - * @api private - */ - this.serverInfo = function(callback) { - db.executeDbAdminCommand({buildinfo:1}, function(err, doc) { - if(err != null) return callback(err, null); - return callback(null, doc.documents[0]); - }); - } - - /** - * Retrieve this db's server status. - * - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from serverStatus or null if an error occured. - * @return {null} - * @api public - */ - this.serverStatus = function(callback) { - var self = this; - - db.executeDbAdminCommand({serverStatus: 1}, function(err, doc) { - if(err == null && doc.documents[0].ok === 1) { - callback(null, doc.documents[0]); - } else { - if(err) return callback(err, false); - return callback(utils.toError(doc.documents[0]), false); - } - }); - }; - - /** - * Retrieve the current profiling Level for MongoDB - * - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from profilingLevel or null if an error occured. - * @return {null} Returns no result - * @api public - */ - this.profilingLevel = function(callback) { - var self = this; - - db.executeDbAdminCommand({profile:-1}, function(err, doc) { - doc = doc.documents[0]; - - if(err == null && doc.ok === 1) { - var was = doc.was; - if(was == 0) return callback(null, "off"); - if(was == 1) return callback(null, "slow_only"); - if(was == 2) return callback(null, "all"); - return callback(new Error("Error: illegal profiling level value " + was), null); - } else { - err != null ? callback(err, null) : callback(new Error("Error with profile command"), null); - } - }); - }; - - /** - * Ping the MongoDB server and retrieve results - * - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from ping or null if an error occured. - * @return {null} Returns no result - * @api public - */ - this.ping = function(options, callback) { - // Unpack calls - var args = Array.prototype.slice.call(arguments, 0); - db.executeDbAdminCommand({ping: 1}, args.pop()); - } - - /** - * Authenticate against MongoDB - * - * @param {String} username The user name for the authentication. - * @param {String} password The password for the authentication. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from authenticate or null if an error occured. - * @return {null} Returns no result - * @api public - */ - this.authenticate = function(username, password, callback) { - db.authenticate(username, password, {authdb: 'admin'}, function(err, doc) { - return callback(err, doc); - }) - } - - /** - * Logout current authenticated user - * - * @param {Object} [options] Optional parameters to the command. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from logout or null if an error occured. - * @return {null} Returns no result - * @api public - */ - this.logout = function(callback) { - db.logout({authdb: 'admin'}, function(err, doc) { - return callback(err, doc); - }) - } - - /** - * Add a user to the MongoDB server, if the user exists it will - * overwrite the current password - * - * Options - * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write - * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) - * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal - * - **j**, (Boolean, default:false) write waits for journal sync before returning - * - * @param {String} username The user name for the authentication. - * @param {String} password The password for the authentication. - * @param {Object} [options] additional options during update. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from addUser or null if an error occured. - * @return {null} Returns no result - * @api public - */ - this.addUser = function(username, password, options, callback) { - var args = Array.prototype.slice.call(arguments, 2); - callback = args.pop(); - options = args.length ? args.shift() : {}; - // Set the db name to admin - options.dbName = 'admin'; - // Add user - db.addUser(username, password, options, function(err, doc) { - return callback(err, doc); - }) - } - /** - * Remove a user from the MongoDB server - * - * Options - * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write - * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) - * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal - * - **j**, (Boolean, default:false) write waits for journal sync before returning - * - * @param {String} username The user name for the authentication. - * @param {Object} [options] additional options during update. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from removeUser or null if an error occured. - * @return {null} Returns no result - * @api public - */ - this.removeUser = function(username, options, callback) { - var self = this; - var args = Array.prototype.slice.call(arguments, 1); - callback = args.pop(); - options = args.length ? args.shift() : {}; - options.dbName = 'admin'; - - db.removeUser(username, options, function(err, doc) { - return callback(err, doc); - }) - } - - /** - * Set the current profiling level of MongoDB - * - * @param {String} level The new profiling level (off, slow_only, all) - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from setProfilingLevel or null if an error occured. - * @return {null} Returns no result - * @api public - */ - this.setProfilingLevel = function(level, callback) { - var self = this; - var command = {}; - var profile = 0; - - if(level == "off") { - profile = 0; - } else if(level == "slow_only") { - profile = 1; - } else if(level == "all") { - profile = 2; - } else { - return callback(new Error("Error: illegal profiling level value " + level)); - } - - // Set up the profile number - command['profile'] = profile; - - db.executeDbAdminCommand(command, function(err, doc) { - doc = doc.documents[0]; - - if(err == null && doc.ok === 1) - return callback(null, level); - return err != null ? callback(err, null) : callback(new Error("Error with profile command"), null); - }); - }; - - /** - * Retrive the current profiling information for MongoDB - * - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from profilingInfo or null if an error occured. - * @return {null} Returns no result - * @api public - */ - this.profilingInfo = function(callback) { - try { - new Cursor(db, new Collection(db, DbCommand.SYSTEM_PROFILE_COLLECTION), {}, {}, {dbName: 'admin'}).toArray(function(err, items) { - return callback(err, items); - }); - } catch (err) { - return callback(err, null); - } - }; - - /** - * Execute a db command against the Admin database - * - * @param {Object} command A command object `{ping:1}`. - * @param {Object} [options] Optional parameters to the command. - * @param {Function} callback this will be called after executing this method. The command always return the whole result of the command as the second parameter. - * @return {null} Returns no result - * @api public - */ - this.command = function(command, options, callback) { - var self = this; - var args = Array.prototype.slice.call(arguments, 1); - callback = args.pop(); - options = args.length ? args.shift() : {}; - - // Execute a command - db.executeDbAdminCommand(command, options, function(err, doc) { - // Ensure change before event loop executes - return callback != null ? callback(err, doc) : null; - }); - } - - /** - * Validate an existing collection - * - * @param {String} collectionName The name of the collection to validate. - * @param {Object} [options] Optional parameters to the command. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from validateCollection or null if an error occured. - * @return {null} Returns no result - * @api public - */ - this.validateCollection = function(collectionName, options, callback) { - var args = Array.prototype.slice.call(arguments, 1); - callback = args.pop(); - options = args.length ? args.shift() : {}; - - var self = this; - var command = {validate: collectionName}; - var keys = Object.keys(options); - - // Decorate command with extra options - for(var i = 0; i < keys.length; i++) { - if(options.hasOwnProperty(keys[i])) { - command[keys[i]] = options[keys[i]]; - } - } - - db.command(command, function(err, doc) { - if(err != null) return callback(err, null); - - if(doc.ok === 0) - return callback(new Error("Error with validate command"), null); - if(doc.result != null && doc.result.constructor != String) - return callback(new Error("Error with validation data"), null); - if(doc.result != null && doc.result.match(/exception|corrupt/) != null) - return callback(new Error("Error: invalid collection " + collectionName), null); - if(doc.valid != null && !doc.valid) - return callback(new Error("Error: invalid collection " + collectionName), null); - - return callback(null, doc); - }); - }; - - /** - * List the available databases - * - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from listDatabases or null if an error occured. - * @return {null} Returns no result - * @api public - */ - this.listDatabases = function(callback) { - // Execute the listAllDatabases command - db.executeDbAdminCommand({listDatabases:1}, {}, function(err, doc) { - if(err != null) return callback(err, null); - return callback(null, doc.documents[0]); - }); - } - - /** - * Get ReplicaSet status - * - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from replSetGetStatus or null if an error occured. - * @return {null} - * @api public - */ - this.replSetGetStatus = function(callback) { - var self = this; - - db.executeDbAdminCommand({replSetGetStatus:1}, function(err, doc) { - if(err == null && doc.documents[0].ok === 1) - return callback(null, doc.documents[0]); - if(err) return callback(err, false); - return callback(utils.toError(doc.documents[0]), false); - }); - }; -}; - -/** - * @ignore - */ -exports.Admin = Admin; diff --git a/node_modules/mongodb/lib/mongodb/aggregation_cursor.js b/node_modules/mongodb/lib/mongodb/aggregation_cursor.js deleted file mode 100644 index 5d1cb51..0000000 --- a/node_modules/mongodb/lib/mongodb/aggregation_cursor.js +++ /dev/null @@ -1,187 +0,0 @@ -var ReadPreference = require('./connection/read_preference').ReadPreference - , Readable = require('stream').Readable || require('readable-stream').Readable - , CommandCursor = require('./command_cursor').CommandCursor - , utils = require('./utils') - , shared = require('./collection/shared') - , inherits = require('util').inherits; - -var AggregationCursor = function(collection, serverCapabilities, options) { - var pipe = []; - var self = this; - var results = null; - var _cursor_options = {}; - // Ensure we have options set up - options = options == null ? {} : options; - - // If a pipeline was provided - pipe = Array.isArray(options.pipe) ? options.pipe : pipe; - // Set passed in batchSize if provided - if(typeof options.batchSize == 'number') _cursor_options.batchSize = options.batchSize; - // Get the read Preference - var readPreference = shared._getReadConcern(collection, options); - - // Set up - Readable.call(this, {objectMode: true}); - - // Contains connection - var connection = null; - - // Set the read preference - var _options = { - readPreference: readPreference - }; - - // Actual command - var command = { - aggregate: collection.collectionName - , pipeline: pipe - , cursor: _cursor_options - } - - // If allowDiskUse is set - if(typeof options.allowDiskUse == 'boolean') - command.allowDiskUse = options.allowDiskUse; - - // Command cursor (if we support one) - var commandCursor = new CommandCursor(collection.db, collection, command); - - this.explain = function(callback) { - if(typeof callback != 'function') - throw utils.toError("AggregationCursor explain requires a callback function"); - - // Add explain options - _options.explain = true; - // Execute aggregation pipeline - collection.aggregate(pipe, _options, function(err, results) { - if(err) return callback(err, null); - callback(null, results); - }); - } - - this.get = function(callback) { - if(typeof callback != 'function') - throw utils.toError("AggregationCursor get requires a callback function"); - // Checkout a connection - var _connection = collection.db.serverConfig.checkoutReader(_options.readPreference); - // Fall back - if(!_connection.serverCapabilities.hasAggregationCursor) { - return collection.aggregate(pipe, _options, function(err, results) { - if(err) return callback(err); - callback(null, results); - }); - } - - // Execute get using command Cursor - commandCursor.get({connection: _connection}, callback); - } - - this.getOne = function(callback) { - if(typeof callback != 'function') - throw utils.toError("AggregationCursor getOne requires a callback function"); - // Set the limit to 1 - pipe.push({$limit: 1}); - // For now we have no cursor command so let's just wrap existing results - collection.aggregate(pipe, _options, function(err, results) { - if(err) return callback(err); - callback(null, results[0]); - }); - } - - this.each = function(callback) { - // Checkout a connection if we have none - if(!connection) - connection = collection.db.serverConfig.checkoutReader(_options.readPreference); - - // Fall back - if(!connection.serverCapabilities.hasAggregationCursor) { - return collection.aggregate(pipe, _options, function(err, _results) { - if(err) return callback(err); - - while(_results.length > 0) { - callback(null, _results.shift()); - } - - callback(null, null); - }); - } - - // Execute each using command Cursor - commandCursor.each({connection: connection}, function(err, doc) { - callback(err, doc); - }); - } - - this.next = function(callback) { - if(typeof callback != 'function') - throw utils.toError("AggregationCursor next requires a callback function"); - - // Checkout a connection if we have none - if(!connection) - connection = collection.db.serverConfig.checkoutReader(_options.readPreference); - - // Fall back - if(!connection.serverCapabilities.hasAggregationCursor) { - if(!results) { - // For now we have no cursor command so let's just wrap existing results - return collection.aggregate(pipe, _options, function(err, _results) { - if(err) return callback(err); - results = _results; - - // Ensure we don't issue undefined - var item = results.shift(); - callback(null, item ? item : null); - }); - } - - // Ensure we don't issue undefined - var item = results.shift(); - // Return the item - return callback(null, item ? item : null); - } - - // Execute next using command Cursor - commandCursor.next({connection: connection}, callback); - } - - // - // Close method - // - this.close = function(callback) { - if(typeof callback != 'function') - throw utils.toError("AggregationCursor close requires a callback function"); - - // Checkout a connection if we have none - if(!connection) - connection = collection.db.serverConfig.checkoutReader(_options.readPreference); - - // Fall back - if(!connection.serverCapabilities.hasAggregationCursor) { - return callback(null, null); - } - - // Execute next using command Cursor - commandCursor.close(callback); - } - - // - // Stream method - // - this._read = function(n) { - self.next(function(err, result) { - if(err) { - self.emit('error', err); - return self.push(null); - } - - self.push(result); - }); - } -} - -// Inherit from Readable -if(Readable != null) { - inherits(AggregationCursor, Readable); -} - -// Exports the Aggregation Framework -exports.AggregationCursor = AggregationCursor; diff --git a/node_modules/mongodb/lib/mongodb/auth/mongodb_cr.js b/node_modules/mongodb/lib/mongodb/auth/mongodb_cr.js deleted file mode 100644 index 3484dc3..0000000 --- a/node_modules/mongodb/lib/mongodb/auth/mongodb_cr.js +++ /dev/null @@ -1,81 +0,0 @@ -var DbCommand = require('../commands/db_command').DbCommand - , utils = require('../utils') - , crypto = require('crypto'); - -var authenticate = function(db, username, password, authdb, options, callback) { - var numberOfConnections = 0; - var errorObject = null; - var numberOfValidConnections = 0; - var credentialsValid = false; - options = options || {}; - - if(options['connection'] != null) { - //if a connection was explicitly passed on options, then we have only one... - numberOfConnections = 1; - } else { - // Get the amount of connections in the pool to ensure we have authenticated all comments - numberOfConnections = db.serverConfig.allRawConnections().length; - options['onAll'] = true; - } - - // Return connection option - options.returnConnection = true; - - // Execute nonce command - db.command({'getnonce':1}, options, function(err, result, connection) { - // Execute on all the connections - if(err == null) { - // Nonce used to make authentication request with md5 hash - var nonce = result.nonce; - - // Use node md5 generator - var md5 = crypto.createHash('md5'); - // Generate keys used for authentication - md5.update(username + ":mongo:" + password); - var hash_password = md5.digest('hex'); - // Final key - md5 = crypto.createHash('md5'); - md5.update(nonce + username + hash_password); - var key = md5.digest('hex'); - - // Creat cmd - var cmd = {'authenticate':1, 'user':username, 'nonce':nonce, 'key':key}; - - // Execute command - db.db(authdb).command(cmd, {connection:connection}, function(err, result) { - // Count down - numberOfConnections = numberOfConnections - 1; - - // Ensure we save any error - if(err) { - errorObject = err; - } else { - credentialsValid = true; - numberOfValidConnections = numberOfValidConnections + 1; - } - - // Work around the case where the number of connections are 0 - if(numberOfConnections <= 0 && typeof callback == 'function') { - var internalCallback = callback; - callback = null; - - if(errorObject == null && credentialsValid) { - db.serverConfig.auth.add('MONGODB-CR', db.databaseName, username, password, authdb); - // Return callback - internalCallback(errorObject, true); - } else if(numberOfValidConnections > 0 && numberOfValidConnections != numberOfConnections - && credentialsValid) { - // One or more servers failed on auth (f.ex secondary hanging on foreground indexing) - db.serverConfig.auth.add('MONGODB-CR', db.databaseName, username, password, authdb); - // Return callback - internalCallback(errorObject, true); - } else { - internalCallback(errorObject, false); - } - } - }); - } - }); -} - -exports.authenticate = authenticate; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/auth/mongodb_gssapi.js b/node_modules/mongodb/lib/mongodb/auth/mongodb_gssapi.js deleted file mode 100644 index e088d19..0000000 --- a/node_modules/mongodb/lib/mongodb/auth/mongodb_gssapi.js +++ /dev/null @@ -1,172 +0,0 @@ -var DbCommand = require('../commands/db_command').DbCommand - , utils = require('../utils') - , format = require('util').format; - -// Kerberos class -var Kerberos = null; -var MongoAuthProcess = null; -// Try to grab the Kerberos class -try { - Kerberos = require('kerberos').Kerberos - // Authentication process for Mongo - MongoAuthProcess = require('kerberos').processes.MongoAuthProcess -} catch(err) {} - -var authenticate = function(db, username, password, authdb, options, callback) { - var numberOfConnections = 0; - var errorObject = null; - var numberOfValidConnections = 0; - var credentialsValid = false; - options = options || {}; - - // We don't have the Kerberos library - if(Kerberos == null) return callback(new Error("Kerberos library is not installed")); - - if(options['connection'] != null) { - //if a connection was explicitly passed on options, then we have only one... - numberOfConnections = 1; - } else { - // Get the amount of connections in the pool to ensure we have authenticated all comments - numberOfConnections = db.serverConfig.allRawConnections().length; - options['onAll'] = true; - } - - // Grab all the connections - var connections = options['connection'] != null ? [options['connection']] : db.serverConfig.allRawConnections(); - var gssapiServiceName = options['gssapiServiceName'] || 'mongodb'; - - // Authenticate all connections - for(var i = 0; i < numberOfConnections; i++) { - - // Start Auth process for a connection - GSSAPIInitialize(db, username, password, authdb, gssapiServiceName, connections[i], function(err, result) { - // Adjust number of connections left to connect - numberOfConnections = numberOfConnections - 1; - - // Ensure we save any error - if(err) { - errorObject = err; - } else { - credentialsValid = true; - numberOfValidConnections = numberOfValidConnections + 1; - } - - // Work around the case where the number of connections are 0 - if(numberOfConnections <= 0 && typeof callback == 'function') { - var internalCallback = callback; - callback = null; - - // We are done - if(errorObject == null && numberOfConnections == 0) { - // We authenticated correctly save the credentials - db.serverConfig.auth.add('GSSAPI', db.databaseName, username, password, authdb, gssapiServiceName); - // Return valid callback - return internalCallback(null, true); - } else if(numberOfValidConnections > 0 && numberOfValidConnections != numberOfConnections - && credentialsValid) { - // We authenticated correctly save the credentials - db.serverConfig.auth.add('GSSAPI', db.databaseName, username, password, authdb, gssapiServiceName); - // Return valid callback - return internalCallback(null, true); - } else { - return internalCallback(errorObject, false); - } - } - }); - } -} - -// -// Initialize step -var GSSAPIInitialize = function(db, username, password, authdb, gssapiServiceName, connection, callback) { - // Create authenticator - var mongo_auth_process = new MongoAuthProcess(connection.socketOptions.host, connection.socketOptions.port, gssapiServiceName); - - // Perform initialization - mongo_auth_process.init(username, password, function(err, context) { - if(err) return callback(err, false); - - // Perform the first step - mongo_auth_process.transition('', function(err, payload) { - if(err) return callback(err, false); - - // Call the next db step - MongoDBGSSAPIFirstStep(mongo_auth_process, payload, db, username, password, authdb, connection, callback); - }); - }); -} - -// -// Perform first step against mongodb -var MongoDBGSSAPIFirstStep = function(mongo_auth_process, payload, db, username, password, authdb, connection, callback) { - // Build the sasl start command - var command = { - saslStart: 1 - , mechanism: 'GSSAPI' - , payload: payload - , autoAuthorize: 1 - }; - - // Execute first sasl step - db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) { - if(err) return callback(err, false); - // Get the payload - doc = doc.documents[0]; - var db_payload = doc.payload; - - mongo_auth_process.transition(doc.payload, function(err, payload) { - if(err) return callback(err, false); - - // MongoDB API Second Step - MongoDBGSSAPISecondStep(mongo_auth_process, payload, doc, db, username, password, authdb, connection, callback); - }); - }); -} - -// -// Perform first step against mongodb -var MongoDBGSSAPISecondStep = function(mongo_auth_process, payload, doc, db, username, password, authdb, connection, callback) { - // Build Authentication command to send to MongoDB - var command = { - saslContinue: 1 - , conversationId: doc.conversationId - , payload: payload - }; - - // Execute the command - db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) { - if(err) return callback(err, false); - - // Get the result document - doc = doc.documents[0]; - - // Call next transition for kerberos - mongo_auth_process.transition(doc.payload, function(err, payload) { - if(err) return callback(err, false); - - // Call the last and third step - MongoDBGSSAPIThirdStep(mongo_auth_process, payload, doc, db, username, password, authdb, connection, callback); - }); - }); -} - -var MongoDBGSSAPIThirdStep = function(mongo_auth_process, payload, doc, db, username, password, authdb, connection, callback) { - // Build final command - var command = { - saslContinue: 1 - , conversationId: doc.conversationId - , payload: payload - }; - - // Let's finish the auth process against mongodb - db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) { - if(err) return callback(err, false); - - mongo_auth_process.transition(null, function(err, payload) { - if(err) return callback(err, false); - callback(null, true); - }); - }); -} - -exports.authenticate = authenticate; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/auth/mongodb_plain.js b/node_modules/mongodb/lib/mongodb/auth/mongodb_plain.js deleted file mode 100644 index d2555cd..0000000 --- a/node_modules/mongodb/lib/mongodb/auth/mongodb_plain.js +++ /dev/null @@ -1,79 +0,0 @@ -var DbCommand = require('../commands/db_command').DbCommand - , utils = require('../utils') - , crypto = require('crypto') - , Binary = require('bson').Binary - , format = require('util').format; - -var authenticate = function(db, username, password, options, callback) { - var numberOfConnections = 0; - var errorObject = null; - var numberOfValidConnections = 0; - var credentialsValid = false; - options = options || {}; - - if(options['connection'] != null) { - //if a connection was explicitly passed on options, then we have only one... - numberOfConnections = 1; - } else { - // Get the amount of connections in the pool to ensure we have authenticated all comments - numberOfConnections = db.serverConfig.allRawConnections().length; - options['onAll'] = true; - } - - // Create payload - var payload = new Binary(format("\x00%s\x00%s", username, password)); - - // Let's start the sasl process - var command = { - saslStart: 1 - , mechanism: 'PLAIN' - , payload: payload - , autoAuthorize: 1 - }; - - // Grab all the connections - var connections = options['connection'] != null ? [options['connection']] : db.serverConfig.allRawConnections(); - - // Authenticate all connections - for(var i = 0; i < numberOfConnections; i++) { - var connection = connections[i]; - // Execute first sasl step - db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, result) { - // Count down - numberOfConnections = numberOfConnections - 1; - - // Ensure we save any error - if(err) { - errorObject = err; - } else if(result.documents[0].err != null || result.documents[0].errmsg != null){ - errorObject = utils.toError(result.documents[0]); - } else { - credentialsValid = true; - numberOfValidConnections = numberOfValidConnections + 1; - } - - // Work around the case where the number of connections are 0 - if(numberOfConnections <= 0 && typeof callback == 'function') { - var internalCallback = callback; - callback = null; - - if(errorObject == null && credentialsValid) { - // We authenticated correctly save the credentials - db.serverConfig.auth.add('PLAIN', db.databaseName, username, password); - // Return callback - internalCallback(errorObject, true); - } else if(numberOfValidConnections > 0 && numberOfValidConnections != numberOfConnections - && credentialsValid) { - // We authenticated correctly save the credentials - db.serverConfig.auth.add('PLAIN', db.databaseName, username, password); - // Return callback - internalCallback(errorObject, true); - } else { - internalCallback(errorObject, false); - } - } - }); - } -} - -exports.authenticate = authenticate; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/auth/mongodb_scram.js b/node_modules/mongodb/lib/mongodb/auth/mongodb_scram.js deleted file mode 100644 index 9c08686..0000000 --- a/node_modules/mongodb/lib/mongodb/auth/mongodb_scram.js +++ /dev/null @@ -1,250 +0,0 @@ -var DbCommand = require('../commands/db_command').DbCommand - , utils = require('../utils') - , crypto = require('crypto') - , Binary = require('bson').Binary - , f = require('util').format; - -var authenticate = function(db, username, password, authdb, options, callback) { - var numberOfConnections = 0; - var errorObject = null; - var numberOfValidConnections = 0; - var credentialsValid = false; - options = options || {}; - - // Grab all the connections - var connections = options['connection'] != null ? [options['connection']] : db.serverConfig.allRawConnections().slice(0); - if(connections.length > 1) { - options['onAll'] = true; - } - - // Total connections - var count = connections.length; - if(count == 0) return callback(null, null); - - // Valid connections - var numberOfValidConnections = 0; - var credentialsValid = false; - var errorObject = null; - - // For each connection we need to authenticate - while(connections.length > 0) { - // Execute MongoCR - var executeScram = function(connection) { - // Clean up the user - username = username.replace('=', "=3D").replace(',', '=2C'); - - // Create a random nonce - var nonce = crypto.randomBytes(24).toString('base64'); - // var nonce = 'MsQUY9iw0T9fx2MUEz6LZPwGuhVvWAhc' - var firstBare = f("n=%s,r=%s", username, nonce); - - // Build command structure - var cmd = { - saslStart: 1 - , mechanism: 'SCRAM-SHA-1' - , payload: new Binary(f("n,,%s", firstBare)) - , autoAuthorize: 1 - } - - // Handle the error - var handleError = function(err, r) { - if(err) { - errorObject = err; return false; - } else if(r['$err']) { - errorObject = r; return false; - } else if(r['errmsg']) { - errorObject = r; return false; - } else { - credentialsValid = true; - numberOfValidConnections = numberOfValidConnections + 1; - } - - return true - } - - // Finish up - var finish = function(_count, _numberOfValidConnections) { - if(_count == 0 && _numberOfValidConnections > 0) { - db.serverConfig.auth.add('SCRAM-SHA-1', db.databaseName, username, password, authdb); - // Return correct authentication - return callback(null, true); - } else if(_count == 0) { - if(errorObject == null) errorObject = utils.toError(f("failed to authenticate using scram")); - return callback(errorObject, false); - } - } - - var handleEnd = function(_err, _r) { - // Handle any error - handleError(_err, _r) - // Adjust the number of connections - count = count - 1; - // Execute the finish - finish(count, numberOfValidConnections); - } - - // Execute start sasl command - db.db(authdb).command(cmd, { connection: connection }, function(err, r) { - // Do we have an error, handle it - if(handleError(err, r) == false) { - count = count - 1; - - if(count == 0 && numberOfValidConnections > 0) { - // Store the auth details - addAuthSession(new AuthSession(db, username, password)); - // Return correct authentication - return callback(null, true); - } else if(count == 0) { - if(errorObject == null) errorObject = utils.toError(f("failed to authenticate using scram")); - return callback(errorObject, false); - } - - return; - } - - // Get the dictionary - var dict = parsePayload(r.payload.value()) - - // Unpack dictionary - var iterations = parseInt(dict.i, 10); - var salt = dict.s; - var rnonce = dict.r; - - // Set up start of proof - var withoutProof = f("c=biws,r=%s", rnonce); - var passwordDig = passwordDigest(username, password); - var saltedPassword = hi(passwordDig - , new Buffer(salt, 'base64') - , iterations); - - // Create the client key - var hmac = crypto.createHmac('sha1', saltedPassword); - hmac.update(new Buffer("Client Key")); - var clientKey = hmac.digest(); - - // Create the stored key - var hash = crypto.createHash('sha1'); - hash.update(clientKey); - var storedKey = hash.digest(); - - // Create the authentication message - var authMsg = [firstBare, r.payload.value().toString('base64'), withoutProof].join(','); - - // Create client signature - var hmac = crypto.createHmac('sha1', storedKey); - hmac.update(new Buffer(authMsg)); - var clientSig = hmac.digest(); - - // Create client proof - var clientProof = f("p=%s", new Buffer(xor(clientKey, clientSig)).toString('base64')); - - // Create client final - var clientFinal = [withoutProof, clientProof].join(','); - - // Generate server key - var hmac = crypto.createHmac('sha1', saltedPassword); - hmac.update(new Buffer('Server Key')) - var serverKey = hmac.digest(); - - // Generate server signature - var hmac = crypto.createHmac('sha1', serverKey); - hmac.update(new Buffer(authMsg)) - var serverSig = hmac.digest(); - - // - // Create continue message - var cmd = { - saslContinue: 1 - , conversationId: r.conversationId - , payload: new Binary(new Buffer(clientFinal)) - } - - // - // Execute sasl continue - db.db(authdb).command(cmd, { connection: connection }, function(err, r) { - if(r.done == false) { - var cmd = { - saslContinue: 1 - , conversationId: r.conversationId - , payload: new Buffer(0) - } - - db.db(authdb).command(cmd, { connection: connection }, function(err, r) { - handleEnd(err, r); - }); - } else { - handleEnd(err, r); - } - }); - }); - } - - // Get the connection - executeScram(connections.shift()); - } -} - -var parsePayload = function(payload) { - var dict = {}; - var parts = payload.split(','); - - for(var i = 0; i < parts.length; i++) { - var valueParts = parts[i].split('='); - dict[valueParts[0]] = valueParts[1]; - } - - return dict; -} - -var passwordDigest = function(username, password) { - if(typeof username != 'string') throw utils.toError("username must be a string"); - if(typeof password != 'string') throw utils.toError("password must be a string"); - if(password.length == 0) throw utils.toError("password cannot be empty"); - // Use node md5 generator - var md5 = crypto.createHash('md5'); - // Generate keys used for authentication - md5.update(username + ":mongo:" + password); - return md5.digest('hex'); -} - -// XOR two buffers -var xor = function(a, b) { - if (!Buffer.isBuffer(a)) a = new Buffer(a) - if (!Buffer.isBuffer(b)) b = new Buffer(b) - var res = [] - if (a.length > b.length) { - for (var i = 0; i < b.length; i++) { - res.push(a[i] ^ b[i]) - } - } else { - for (var i = 0; i < a.length; i++) { - res.push(a[i] ^ b[i]) - } - } - return new Buffer(res); -} - -// Create a final digest -var hi = function(data, salt, iterations) { - // Create digest - var digest = function(msg) { - var hmac = crypto.createHmac('sha1', data); - hmac.update(msg); - var result = hmac.digest() - return result; - } - - // Create variables - salt = Buffer.concat([salt, new Buffer('\x00\x00\x00\x01')]) - var ui = digest(salt); - var u1 = ui; - - for(var i = 0; i < iterations - 1; i++) { - u1 = digest(u1); - ui = xor(ui, u1); - } - - return ui; -} - -exports.authenticate = authenticate; diff --git a/node_modules/mongodb/lib/mongodb/auth/mongodb_sspi.js b/node_modules/mongodb/lib/mongodb/auth/mongodb_sspi.js deleted file mode 100644 index 13a87ea..0000000 --- a/node_modules/mongodb/lib/mongodb/auth/mongodb_sspi.js +++ /dev/null @@ -1,156 +0,0 @@ -var DbCommand = require('../commands/db_command').DbCommand - , utils = require('../utils') - , format = require('util').format; - -// Kerberos class -var Kerberos = null; -var MongoAuthProcess = null; -// Try to grab the Kerberos class -try { - Kerberos = require('kerberos').Kerberos - // Authentication process for Mongo - MongoAuthProcess = require('kerberos').processes.MongoAuthProcess -} catch(err) {} - -var authenticate = function(db, username, password, authdb, options, callback) { - var numberOfConnections = 0; - var errorObject = null; - var numberOfValidConnections = 0; - var credentialsValid = false; - options = options || {}; - - // We don't have the Kerberos library - if(Kerberos == null) return callback(new Error("Kerberos library is not installed")); - - if(options['connection'] != null) { - //if a connection was explicitly passed on options, then we have only one... - numberOfConnections = 1; - } else { - // Get the amount of connections in the pool to ensure we have authenticated all comments - numberOfConnections = db.serverConfig.allRawConnections().length; - options['onAll'] = true; - } - - // Set the sspi server name - var gssapiServiceName = options['gssapiServiceName'] || 'mongodb'; - - // Grab all the connections - var connections = db.serverConfig.allRawConnections(); - - // Authenticate all connections - for(var i = 0; i < numberOfConnections; i++) { - // Start Auth process for a connection - SSIPAuthenticate(db, username, password, authdb, gssapiServiceName, connections[i], function(err, result) { - // Adjust number of connections left to connect - numberOfConnections = numberOfConnections - 1; - - // Ensure we save any error - if(err) { - errorObject = err; - } else { - credentialsValid = true; - numberOfValidConnections = numberOfValidConnections + 1; - } - - // Work around the case where the number of connections are 0 - if(numberOfConnections <= 0 && typeof callback == 'function') { - var internalCallback = callback; - callback = null; - - if(errorObject == null) { - // We authenticated correctly save the credentials - db.serverConfig.auth.add('GSSAPI', db.databaseName, username, password, authdb, gssapiServiceName); - // Return valid callback - return internalCallback(null, true); - } else if(numberOfValidConnections > 0 && numberOfValidConnections != numberOfConnections - && credentialsValid) { - // We authenticated correctly save the credentials - db.serverConfig.auth.add('GSSAPI', db.databaseName, username, password, authdb, gssapiServiceName); - // Return valid callback - return internalCallback(null, true); - } else { - return internalCallback(errorObject, false); - } - } - }); - } -} - -var SSIPAuthenticate = function(db, username, password, authdb, service_name, connection, callback) { - // -------------------------------------------------------------- - // Async Version - // -------------------------------------------------------------- - var command = { - saslStart: 1 - , mechanism: 'GSSAPI' - , payload: '' - , autoAuthorize: 1 - }; - - // Create authenticator - var mongo_auth_process = new MongoAuthProcess(connection.socketOptions.host, connection.socketOptions.port, service_name); - - // Execute first sasl step - db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) { - if(err) return callback(err); - doc = doc.documents[0]; - - mongo_auth_process.init(username, password, function(err) { - if(err) return callback(err); - - mongo_auth_process.transition(doc.payload, function(err, payload) { - if(err) return callback(err); - - // Perform the next step against mongod - var command = { - saslContinue: 1 - , conversationId: doc.conversationId - , payload: payload - }; - - // Execute the command - db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) { - if(err) return callback(err); - doc = doc.documents[0]; - - mongo_auth_process.transition(doc.payload, function(err, payload) { - if(err) return callback(err); - - // Perform the next step against mongod - var command = { - saslContinue: 1 - , conversationId: doc.conversationId - , payload: payload - }; - - // Execute the command - db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) { - if(err) return callback(err); - doc = doc.documents[0]; - - mongo_auth_process.transition(doc.payload, function(err, payload) { - // Perform the next step against mongod - var command = { - saslContinue: 1 - , conversationId: doc.conversationId - , payload: payload - }; - - // Execute the command - db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) { - if(err) return callback(err); - doc = doc.documents[0]; - - if(doc.done) return callback(null, true); - callback(new Error("Authentication failed"), false); - }); - }); - }); - }); - }); - }); - }); - }); -} - -exports.authenticate = authenticate; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/auth/mongodb_x509.js b/node_modules/mongodb/lib/mongodb/auth/mongodb_x509.js deleted file mode 100644 index 8b8b7c2..0000000 --- a/node_modules/mongodb/lib/mongodb/auth/mongodb_x509.js +++ /dev/null @@ -1,68 +0,0 @@ -var DbCommand = require('../commands/db_command').DbCommand - , utils = require('../utils') - , Binary = require('bson').Binary - , format = require('util').format; - -var authenticate = function(db, username, password, options, callback, t) { - var numberOfConnections = 0; - var errorObject = null; - var numberOfValidConnections = 0; - var credentialsValid = false; - options = options || {}; - - if(options['connection'] != null) { - //if a connection was explicitly passed on options, then we have only one... - numberOfConnections = 1; - } else { - // Get the amount of connections in the pool to ensure we have authenticated all comments - numberOfConnections = db.serverConfig.allRawConnections().length; - options['onAll'] = true; - } - - // Let's start the sasl process - var command = { - authenticate: 1 - , mechanism: 'MONGODB-X509' - , user: username - }; - - // Grab all the connections - var connections = options['connection'] != null ? [options['connection']] : db.serverConfig.allRawConnections(); - - // Authenticate all connections - for(var i = 0; i < numberOfConnections; i++) { - var connection = connections[i]; - // Execute first sasl step - db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, result) { - // Count down - numberOfConnections = numberOfConnections - 1; - - // Ensure we save any error - if(err) { - errorObject = err; - } else if(result.documents[0].err != null || result.documents[0].errmsg != null){ - errorObject = utils.toError(result.documents[0]); - } else { - credentialsValid = true; - numberOfValidConnections = numberOfValidConnections + 1; - } - - // Work around the case where the number of connections are 0 - if(numberOfConnections <= 0 && typeof callback == 'function') { - var internalCallback = callback; - callback = null; - - if(errorObject == null && credentialsValid) { - // We authenticated correctly save the credentials - db.serverConfig.auth.add('MONGODB-X509', db.databaseName, username, password); - // Return callback - internalCallback(errorObject, true); - } else { - internalCallback(errorObject, false); - } - } - }); - } -} - -exports.authenticate = authenticate; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/collection.js b/node_modules/mongodb/lib/mongodb/collection.js deleted file mode 100644 index b8e8a70..0000000 --- a/node_modules/mongodb/lib/mongodb/collection.js +++ /dev/null @@ -1,676 +0,0 @@ -/** - * Module dependencies. - * @ignore - */ -var InsertCommand = require('./commands/insert_command').InsertCommand - , QueryCommand = require('./commands/query_command').QueryCommand - , DeleteCommand = require('./commands/delete_command').DeleteCommand - , UpdateCommand = require('./commands/update_command').UpdateCommand - , DbCommand = require('./commands/db_command').DbCommand - , ObjectID = require('bson').ObjectID - , Code = require('bson').Code - , Cursor = require('./cursor').Cursor - , utils = require('./utils') - , shared = require('./collection/shared') - , core = require('./collection/core') - , query = require('./collection/query') - , index = require('./collection/index') - , geo = require('./collection/geo') - , commands = require('./collection/commands') - , aggregation = require('./collection/aggregation') - , unordered = require('./collection/batch/unordered') - , ordered = require('./collection/batch/ordered'); - -/** - * Create a new Collection instance (INTERNAL TYPE, do not instantiate directly) - * - * Options - * - **readPreference** {String}, the prefered read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). - * - **slaveOk** {Boolean, default:false}, Allow reads from secondaries. - * - **serializeFunctions** {Boolean, default:false}, serialize functions on the document. - * - **raw** {Boolean, default:false}, perform all operations using raw bson objects. - * - **pkFactory** {Object}, object overriding the basic ObjectID primary key generation. - * - * @class Represents a Collection - * @param {Object} db db instance. - * @param {String} collectionName collection name. - * @param {Object} [pkFactory] alternative primary key factory. - * @param {Object} [options] additional options for the collection. - * @return {Object} a collection instance. - */ -function Collection (db, collectionName, pkFactory, options) { - if(!(this instanceof Collection)) return new Collection(db, collectionName, pkFactory, options); - - shared.checkCollectionName(collectionName); - - this.db = db; - this.collectionName = collectionName; - this.internalHint = null; - this.opts = options != null && ('object' === typeof options) ? options : {}; - this.slaveOk = options == null || options.slaveOk == null ? db.slaveOk : options.slaveOk; - this.serializeFunctions = options == null || options.serializeFunctions == null ? db.serializeFunctions : options.serializeFunctions; - this.raw = options == null || options.raw == null ? db.raw : options.raw; - - // Assign the right collection level readPreference - if(options && options.readPreference) { - this.readPreference = options.readPreference; - } else if(this.db.options.readPreference) { - this.readPreference = this.db.options.readPreference; - } else if(this.db.serverConfig.options.readPreference) { - this.readPreference = this.db.serverConfig.options.readPreference; - } - - // Set custom primary key factory if provided - this.pkFactory = pkFactory == null - ? ObjectID - : pkFactory; - - // Server Capabilities - this.serverCapabilities = this.db.serverConfig._serverCapabilities; -} - -/** - * Inserts a single document or a an array of documents into MongoDB. - * - * Options - * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write - * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) - * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal - * - **j**, (Boolean, default:false) write waits for journal sync before returning - * - **continueOnError/keepGoing** {Boolean, default:false}, keep inserting documents even if one document has an error, *mongodb 1.9.1 >*. - * - **serializeFunctions** {Boolean, default:false}, serialize functions on the document. - * - **forceServerObjectId** {Boolean, default:false}, let server assign ObjectId instead of the driver - * - **checkKeys** {Boolean, default:true}, allows for disabling of document key checking (WARNING OPENS YOU UP TO INJECTION ATTACKS) - * - **fullResult** {Boolean, default:false}, returns the full result document (document returned will differ by server version) - * - * @param {Array|Object} docs - * @param {Object} [options] optional options for insert command - * @param {Function} [callback] optional callback for the function, must be provided when using a writeconcern - * @return {Collection} - * @api public - */ -Collection.prototype.insert = function() { return core.insert; }(); - -/** - * Removes documents specified by `selector` from the db. - * - * Options - * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write - * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) - * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal - * - **j**, (Boolean, default:false) write waits for journal sync before returning - * - **single** {Boolean, default:false}, removes the first document found. - * - **fullResult** {Boolean, default:false}, returns the full result document (document returned will differ by server version) - * - * @param {Object} [selector] optional select, no selector is equivalent to removing all documents. - * @param {Object} [options] additional options during remove. - * @param {Function} [callback] must be provided if you performing a remove with a writeconcern - * @return {null} - * @api public - */ -Collection.prototype.remove = function() { return core.remove; }(); - -/** - * Renames the collection. - * - * Options - * - **dropTarget** {Boolean, default:false}, drop the target name collection if it previously exists. - * - * @param {String} newName the new name of the collection. - * @param {Object} [options] returns option results. - * @param {Function} callback the callback accepting the result - * @return {null} - * @api public - */ -Collection.prototype.rename = function() { return commands.rename; }(); - -/** - * Save a document. Simple full document replacement function. Not recommended for efficiency, use atomic - * operators and update instead for more efficient operations. - * - * Options - * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write - * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) - * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal - * - **j**, (Boolean, default:false) write waits for journal sync before returning - * - * @param {Object} [doc] the document to save - * @param {Object} [options] additional options during remove. - * @param {Function} [callback] must be provided if you performing an update with a writeconcern - * @return {null} - * @api public - */ -Collection.prototype.save = function() { return core.save; }(); - -/** - * Updates documents. - * - * Options - * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write - * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) - * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal - * - **j**, (Boolean, default:false) write waits for journal sync before returning - * - **upsert** {Boolean, default:false}, perform an upsert operation. - * - **multi** {Boolean, default:false}, update all documents matching the selector. - * - **serializeFunctions** {Boolean, default:false}, serialize functions on the document. - * - **checkKeys** {Boolean, default:true}, allows for disabling of document key checking (WARNING OPENS YOU UP TO INJECTION ATTACKS) - * - **fullResult** {Boolean, default:false}, returns the full result document (document returned will differ by server version) - * - * @param {Object} selector the query to select the document/documents to be updated - * @param {Object} document the fields/vals to be updated, or in the case of an upsert operation, inserted. - * @param {Object} [options] additional options during update. - * @param {Function} [callback] must be provided if you performing an update with a writeconcern - * @return {null} - * @api public - */ -Collection.prototype.update = function() { return core.update; }(); - -/** - * The distinct command returns returns a list of distinct values for the given key across a collection. - * - * Options - * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). - * - * @param {String} key key to run distinct against. - * @param {Object} [query] option query to narrow the returned objects. - * @param {Object} [options] additional options during update. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from distinct or null if an error occured. - * @return {null} - * @api public - */ -Collection.prototype.distinct = function() { return commands.distinct; }(); - -/** - * Count number of matching documents in the db to a query. - * - * Options - * - **skip** {Number}, The number of documents to skip for the count. - * - **limit** {Number}, The limit of documents to count. - * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). - * - * @param {Object} [query] query to filter by before performing count. - * @param {Object} [options] additional options during count. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the count method or null if an error occured. - * @return {null} - * @api public - */ -Collection.prototype.count = function() { return commands.count; }(); - -/** - * Drop the collection - * - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the drop method or null if an error occured. - * @return {null} - * @api public - */ -Collection.prototype.drop = function drop(callback) { - this.db.dropCollection(this.collectionName, callback); -}; - -/** - * Find and update a document. - * - * Options - * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write - * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) - * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal - * - **j**, (Boolean, default:false) write waits for journal sync before returning - * - **remove** {Boolean, default:false}, set to true to remove the object before returning. - * - **upsert** {Boolean, default:false}, perform an upsert operation. - * - **new** {Boolean, default:false}, set to true if you want to return the modified object rather than the original. Ignored for remove. - * - * @param {Object} query query object to locate the object to modify - * @param {Array} sort - if multiple docs match, choose the first one in the specified sort order as the object to manipulate - * @param {Object} doc - the fields/vals to be updated - * @param {Object} [options] additional options during update. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the findAndModify method or null if an error occured. - * @return {null} - * @api public - */ -Collection.prototype.findAndModify = function() { return core.findAndModify; }(); - -/** - * Find and remove a document - * - * Options - * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write - * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) - * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal - * - **j**, (Boolean, default:false) write waits for journal sync before returning - * - * @param {Object} query query object to locate the object to modify - * @param {Array} sort - if multiple docs match, choose the first one in the specified sort order as the object to manipulate - * @param {Object} [options] additional options during update. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the findAndRemove method or null if an error occured. - * @return {null} - * @api public - */ -Collection.prototype.findAndRemove = function() { return core.findAndRemove; }(); - -/** - * Creates a cursor for a query that can be used to iterate over results from MongoDB - * - * Various argument possibilities - * - callback? - * - selector, callback?, - * - selector, fields, callback? - * - selector, options, callback? - * - selector, fields, options, callback? - * - selector, fields, skip, limit, callback? - * - selector, fields, skip, limit, timeout, callback? - * - * Options - * - **limit** {Number, default:0}, sets the limit of documents returned in the query. - * - **sort** {Array | Object}, set to sort the documents coming back from the query. Array of indexes, [['a', 1]] etc. - * - **fields** {Object}, the fields to return in the query. Object of fields to include or exclude (not both), {'a':1} - * - **skip** {Number, default:0}, set to skip N documents ahead in your query (useful for pagination). - * - **hint** {Object}, tell the query to use specific indexes in the query. Object of indexes to use, {'_id':1} - * - **explain** {Boolean, default:false}, explain the query instead of returning the data. - * - **snapshot** {Boolean, default:false}, snapshot query. - * - **timeout** {Boolean, default:false}, specify if the cursor can timeout. - * - **tailable** {Boolean, default:false}, specify if the cursor is tailable. - * - **tailableRetryInterval** {Number, default:100}, specify the miliseconds between getMores on tailable cursor. - * - **numberOfRetries** {Number, default:5}, specify the number of times to retry the tailable cursor. - * - **awaitdata** {Boolean, default:false} allow the cursor to wait for data, only applicable for tailable cursor. - * - **oplogReplay** {Boolean, default:false} sets an internal flag, only applicable for tailable cursor. - * - **exhaust** {Boolean, default:false} have the server send all the documents at once as getMore packets, not recommended. - * - **batchSize** {Number, default:0}, set the batchSize for the getMoreCommand when iterating over the query results. - * - **returnKey** {Boolean, default:false}, only return the index key. - * - **maxScan** {Number}, Limit the number of items to scan. - * - **min** {Number}, Set index bounds. - * - **max** {Number}, Set index bounds. - * - **showDiskLoc** {Boolean, default:false}, Show disk location of results. - * - **comment** {String}, You can put a $comment field on a query to make looking in the profiler logs simpler. - * - **raw** {Boolean, default:false}, Return all BSON documents as Raw Buffer documents. - * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference ((ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). - * - **numberOfRetries** {Number, default:5}, if using awaidata specifies the number of times to retry on timeout. - * - **partial** {Boolean, default:false}, specify if the cursor should return partial results when querying against a sharded system - * - **maxTimeMS** {Number}, number of miliseconds to wait before aborting the query. - * - * @param {Object|ObjectID} query query object to locate the object to modify - * @param {Object} [options] additional options during update. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the find method or null if an error occured. - * @return {Cursor} returns a cursor to the query - * @api public - */ -Collection.prototype.find = function() { return query.find; }(); - -/** - * Finds a single document based on the query - * - * Various argument possibilities - * - callback? - * - selector, callback?, - * - selector, fields, callback? - * - selector, options, callback? - * - selector, fields, options, callback? - * - selector, fields, skip, limit, callback? - * - selector, fields, skip, limit, timeout, callback? - * - * Options - * - **limit** {Number, default:0}, sets the limit of documents returned in the query. - * - **sort** {Array | Object}, set to sort the documents coming back from the query. Array of indexes, [['a', 1]] etc. - * - **fields** {Object}, the fields to return in the query. Object of fields to include or exclude (not both), {'a':1} - * - **skip** {Number, default:0}, set to skip N documents ahead in your query (useful for pagination). - * - **hint** {Object}, tell the query to use specific indexes in the query. Object of indexes to use, {'_id':1} - * - **explain** {Boolean, default:false}, explain the query instead of returning the data. - * - **snapshot** {Boolean, default:false}, snapshot query. - * - **timeout** {Boolean, default:false}, specify if the cursor can timeout. - * - **tailable** {Boolean, default:false}, specify if the cursor is tailable. - * - **batchSize** {Number, default:0}, set the batchSize for the getMoreCommand when iterating over the query results. - * - **returnKey** {Boolean, default:false}, only return the index key. - * - **maxScan** {Number}, Limit the number of items to scan. - * - **min** {Number}, Set index bounds. - * - **max** {Number}, Set index bounds. - * - **showDiskLoc** {Boolean, default:false}, Show disk location of results. - * - **comment** {String}, You can put a $comment field on a query to make looking in the profiler logs simpler. - * - **raw** {Boolean, default:false}, Return all BSON documents as Raw Buffer documents. - * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). - * - **partial** {Boolean, default:false}, specify if the cursor should return partial results when querying against a sharded system - * - **maxTimeMS** {Number}, number of miliseconds to wait before aborting the query. - * - * @param {Object|ObjectID} query query object to locate the object to modify - * @param {Object} [options] additional options during update. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the findOne method or null if an error occured. - * @return {Cursor} returns a cursor to the query - * @api public - */ -Collection.prototype.findOne = function() { return query.findOne; }(); - -/** - * Creates an index on the collection. - * - * Options - * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write - * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) - * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal - * - **j**, (Boolean, default:false) write waits for journal sync before returning - * - **unique** {Boolean, default:false}, creates an unique index. - * - **sparse** {Boolean, default:false}, creates a sparse index. - * - **background** {Boolean, default:false}, creates the index in the background, yielding whenever possible. - * - **min** {Number}, for geospatial indexes set the lower bound for the co-ordinates. - * - **max** {Number}, for geospatial indexes set the high bound for the co-ordinates. - * - **v** {Number}, specify the format version of the indexes. - * - **expireAfterSeconds** {Number}, allows you to expire data on indexes applied to a data (MongoDB 2.2 or higher) - * - **name** {String}, override the autogenerated index name (useful if the resulting name is larger than 128 bytes) - * - * @param {Object} fieldOrSpec fieldOrSpec that defines the index. - * @param {Object} [options] additional options during update. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the createIndex method or null if an error occured. - * @return {null} - * @api public - */ -Collection.prototype.createIndex = function() { return index.createIndex; }(); - -/** - * Ensures that an index exists, if it does not it creates it - * - * Options - * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write - * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) - * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal - * - **j**, (Boolean, default:false) write waits for journal sync before returning - * - **unique** {Boolean, default:false}, creates an unique index. - * - **sparse** {Boolean, default:false}, creates a sparse index. - * - **background** {Boolean, default:false}, creates the index in the background, yielding whenever possible. - * - **min** {Number}, for geospatial indexes set the lower bound for the co-ordinates. - * - **max** {Number}, for geospatial indexes set the high bound for the co-ordinates. - * - **v** {Number}, specify the format version of the indexes. - * - **expireAfterSeconds** {Number}, allows you to expire data on indexes applied to a data (MongoDB 2.2 or higher) - * - **name** {String}, override the autogenerated index name (useful if the resulting name is larger than 128 bytes) - * - * @param {Object} fieldOrSpec fieldOrSpec that defines the index. - * @param {Object} [options] additional options during update. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the ensureIndex method or null if an error occured. - * @return {null} - * @api public - */ -Collection.prototype.ensureIndex = function() { return index.ensureIndex; }(); - -/** - * Retrieves this collections index info. - * - * Options - * - **full** {Boolean, default:false}, returns the full raw index information. - * - * @param {Object} [options] additional options during update. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the indexInformation method or null if an error occured. - * @return {null} - * @api public - */ -Collection.prototype.indexInformation = function() { return index.indexInformation; }(); - -/** - * Drops an index from this collection. - * - * @param {String} name - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the dropIndex method or null if an error occured. - * @return {null} - * @api public - */ -Collection.prototype.dropIndex = function dropIndex (name, options, callback) { - if(typeof options == 'function') { - callback = options; - options = {}; - } - // Execute dropIndex command - this.db.dropIndex(this.collectionName, name, options, callback); -}; - -/** - * Drops all indexes from this collection. - * - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the dropAllIndexes method or null if an error occured. - * @return {null} - * @api public - */ -Collection.prototype.dropAllIndexes = function() { return index.dropAllIndexes; }(); - -/** - * Drops all indexes from this collection. - * - * @deprecated - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the dropIndexes method or null if an error occured. - * @return {null} - * @api private - */ -Collection.prototype.dropIndexes = function() { return Collection.prototype.dropAllIndexes; }(); - -/** - * Reindex all indexes on the collection - * Warning: reIndex is a blocking operation (indexes are rebuilt in the foreground) and will be slow for large collections. - * - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the reIndex method or null if an error occured. - * @return {null} - * @api public -**/ -Collection.prototype.reIndex = function(options, callback) { - if(typeof options == 'function') { - callback = options; - options = {}; - } - // Execute reIndex - this.db.reIndex(this.collectionName, options, callback); -} - -/** - * Run Map Reduce across a collection. Be aware that the inline option for out will return an array of results not a collection. - * - * Options - * - **out** {Object}, sets the output target for the map reduce job. *{inline:1} | {replace:'collectionName'} | {merge:'collectionName'} | {reduce:'collectionName'}* - * - **query** {Object}, query filter object. - * - **sort** {Object}, sorts the input objects using this key. Useful for optimization, like sorting by the emit key for fewer reduces. - * - **limit** {Number}, number of objects to return from collection. - * - **keeptemp** {Boolean, default:false}, keep temporary data. - * - **finalize** {Function | String}, finalize function. - * - **scope** {Object}, can pass in variables that can be access from map/reduce/finalize. - * - **jsMode** {Boolean, default:false}, it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X. - * - **verbose** {Boolean, default:false}, provide statistics on job execution time. - * - **readPreference** {String, only for inline results}, the preferred read preference, require('mongodb').ReadPreference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). - * - * @param {Function|String} map the mapping function. - * @param {Function|String} reduce the reduce function. - * @param {Objects} [options] options for the map reduce job. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the mapReduce method or null if an error occured. - * @return {null} - * @api public - */ -Collection.prototype.mapReduce = function() { return aggregation.mapReduce; }(); - -/** - * Run a group command across a collection - * - * Options - * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). - * - * @param {Object|Array|Function|Code} keys an object, array or function expressing the keys to group by. - * @param {Object} condition an optional condition that must be true for a row to be considered. - * @param {Object} initial initial value of the aggregation counter object. - * @param {Function|Code} reduce the reduce function aggregates (reduces) the objects iterated - * @param {Function|Code} finalize an optional function to be run on each item in the result set just before the item is returned. - * @param {Boolean} command specify if you wish to run using the internal group command or using eval, default is true. - * @param {Object} [options] additional options during update. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the group method or null if an error occured. - * @return {null} - * @api public - */ -Collection.prototype.group = function() { return aggregation.group; }(); - -/** - * Returns the options of the collection. - * - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the options method or null if an error occured. - * @return {null} - * @api public - */ -Collection.prototype.options = function() { return commands.options; }(); - -/** - * Returns if the collection is a capped collection - * - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the isCapped method or null if an error occured. - * @return {null} - * @api public - */ -Collection.prototype.isCapped = function() { return commands.isCapped; }(); - -/** - * Checks if one or more indexes exist on the collection - * - * @param {String|Array} indexNames check if one or more indexes exist on the collection. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the indexExists method or null if an error occured. - * @return {null} - * @api public - */ -Collection.prototype.indexExists = function() { return index.indexExists; }(); - -/** - * Execute the geoNear command to search for items in the collection - * - * Options - * - **num** {Number}, max number of results to return. - * - **minDistance** {Number}, include results starting at minDistance from a point (2.6 or higher) - * - **maxDistance** {Number}, include results up to maxDistance from the point. - * - **distanceMultiplier** {Number}, include a value to multiply the distances with allowing for range conversions. - * - **query** {Object}, filter the results by a query. - * - **spherical** {Boolean, default:false}, perform query using a spherical model. - * - **uniqueDocs** {Boolean, default:false}, the closest location in a document to the center of the search region will always be returned MongoDB > 2.X. - * - **includeLocs** {Boolean, default:false}, include the location data fields in the top level of the results MongoDB > 2.X. - * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference ((ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). - * - * @param {Number} x point to search on the x axis, ensure the indexes are ordered in the same order. - * @param {Number} y point to search on the y axis, ensure the indexes are ordered in the same order. - * @param {Objects} [options] options for the map reduce job. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the geoNear method or null if an error occured. - * @return {null} - * @api public - */ -Collection.prototype.geoNear = function() { return geo.geoNear; }(); - -/** - * Execute a geo search using a geo haystack index on a collection. - * - * Options - * - **maxDistance** {Number}, include results up to maxDistance from the point. - * - **search** {Object}, filter the results by a query. - * - **limit** {Number}, max number of results to return. - * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference ((ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). - * - * @param {Number} x point to search on the x axis, ensure the indexes are ordered in the same order. - * @param {Number} y point to search on the y axis, ensure the indexes are ordered in the same order. - * @param {Objects} [options] options for the map reduce job. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the geoHaystackSearch method or null if an error occured. - * @return {null} - * @api public - */ -Collection.prototype.geoHaystackSearch = function() { return geo.geoHaystackSearch; }(); - -/** - * Retrieve all the indexes on the collection. - * - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the indexes method or null if an error occured. - * @return {null} - * @api public - */ -Collection.prototype.indexes = function indexes(callback) { - this.db.indexInformation(this.collectionName, {full:true}, callback); -} - -/** - * Execute an aggregation framework pipeline against the collection, needs MongoDB >= 2.2 - * - * Options - * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference ((ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). - * - **cursor** {Object}, return the query as cursor, on 2.6 > it returns as a real cursor on pre 2.6 it returns as an emulated cursor. - * - **cursor.batchSize** {Number}, the batchSize for the cursor - * - **out** {String}, the collection name to where to write the results from the aggregation (MongoDB 2.6 or higher). Warning any existing collection will be overwritten. - * - **explain** {Boolean, default:false}, explain returns the aggregation execution plan (requires mongodb 2.6 >). - * - **allowDiskUse** {Boolean, default:false}, allowDiskUse lets the server know if it can use disk to store temporary results for the aggregation (requires mongodb 2.6 >). - * - * @param {Array} array containing all the aggregation framework commands for the execution. - * @param {Object} [options] additional options during update. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the aggregate method or null if an error occured. - * @return {null} - * @api public - */ -Collection.prototype.aggregate = function() { return aggregation.aggregate; }(); - -/** - * Get all the collection statistics. - * - * Options - * - **scale** {Number}, divide the returned sizes by scale value. - * - **readPreference** {String}, the preferred read preference, require('mongodb').ReadPreference ((ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). - * - * @param {Objects} [options] options for the stats command. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the stats method or null if an error occured. - * @return {null} - * @api public - */ -Collection.prototype.stats = function() { return commands.stats; }(); - -/** - * Initiate a Out of order batch write operation. All operations will be buffered into insert/update/remove commands executed out of order. - * - * Options - * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write - * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) - * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal - * - **j**, (Boolean, default:false) write waits for journal sync before returning - * - * @param {Objects} [options] options for the initializeUnorderedBatch - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. The second argument will be a UnorderedBulkOperation object. - * @return {UnorderedBulkOperation} - * @api public - */ -Collection.prototype.initializeUnorderedBulkOp = function() { return unordered.initializeUnorderedBulkOp; }(); - -/** - * Initiate an In order bulk write operation, operations will be serially executed in the order they are added, creating a new operation for each switch in types. - * - * Options - * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write - * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) - * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal - * - **j**, (Boolean, default:false) write waits for journal sync before returning - * - * @param {Objects} [options] options for the initializeOrderedBulkOp - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. The second argument will be a OrderedBulkOperation object. - * @return {OrderedBulkOperation} - * @api public - */ -Collection.prototype.initializeOrderedBulkOp = function() { return ordered.initializeOrderedBulkOp; }(); - -/** - * Return N number of parallel cursors for a collection allowing parallel reading of entire collection. There are - * no ordering guarantees for returned results. - * - * Options - * - **readPreference** {String}, the prefered read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). - * - **batchSize** {Number, default:0}, set the batchSize for the getMoreCommand when iterating over the query results. - * - **numCursors**, {Number, 1} the maximum number of parallel command cursors to return (the number of returned cursors will be in the range 1:numCursors) - * - * @param {Objects} [options] options for the initializeOrderedBulkOp - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. The second argument will be an array of CommandCursor instances. - * @return {OrderedBulkOperation} - * @api public - */ -Collection.prototype.parallelCollectionScan = function() { return query.parallelCollectionScan; }(); - -/** - * @ignore - */ -Object.defineProperty(Collection.prototype, "hint", { - enumerable: true - , get: function () { - return this.internalHint; - } - , set: function (v) { - this.internalHint = shared.normalizeHintField(v); - } -}); - -/** - * Expose. - */ -exports.Collection = Collection; diff --git a/node_modules/mongodb/lib/mongodb/collection/aggregation.js b/node_modules/mongodb/lib/mongodb/collection/aggregation.js deleted file mode 100644 index 41c884c..0000000 --- a/node_modules/mongodb/lib/mongodb/collection/aggregation.js +++ /dev/null @@ -1,318 +0,0 @@ -var shared = require('./shared') - , utils = require('../utils') - , AggregationCursor = require('../aggregation_cursor').AggregationCursor - , Code = require('bson').Code - , DbCommand = require('../commands/db_command').DbCommand; - -/** - * Functions that are passed as scope args must - * be converted to Code instances. - * @ignore - */ -function processScope (scope) { - if (!utils.isObject(scope)) { - return scope; - } - - var keys = Object.keys(scope); - var i = keys.length; - var key; - var new_scope = {}; - - while (i--) { - key = keys[i]; - if ('function' == typeof scope[key]) { - new_scope[key] = new Code(String(scope[key])); - } else { - new_scope[key] = processScope(scope[key]); - } - } - - return new_scope; -} - -var pipe = function() { - return new AggregationCursor(this, this.serverCapabilities); -} - -var mapReduce = function mapReduce (map, reduce, options, callback) { - if ('function' === typeof options) callback = options, options = {}; - // Out must allways be defined (make sure we don't break weirdly on pre 1.8+ servers) - if(null == options.out) { - throw new Error("the out option parameter must be defined, see mongodb docs for possible values"); - } - - if ('function' === typeof map) { - map = map.toString(); - } - - if ('function' === typeof reduce) { - reduce = reduce.toString(); - } - - if ('function' === typeof options.finalize) { - options.finalize = options.finalize.toString(); - } - - var mapCommandHash = { - mapreduce: this.collectionName - , map: map - , reduce: reduce - }; - - // Add any other options passed in - for (var name in options) { - if ('scope' == name) { - mapCommandHash[name] = processScope(options[name]); - } else { - mapCommandHash[name] = options[name]; - } - } - - // Set read preference if we set one - var readPreference = shared._getReadConcern(this, options); - - // If we have a read preference and inline is not set as output fail hard - if((readPreference != false && readPreference != 'primary') - && options['out'] && (options['out'].inline != 1 && options['out'] != 'inline')) { - readPreference = 'primary'; - } - - // self - var self = this; - var cmd = DbCommand.createDbCommand(this.db, mapCommandHash); - - this.db._executeQueryCommand(cmd, {readPreference:readPreference}, function (err, result) { - if(err) return callback(err); - if(!result || !result.documents || result.documents.length == 0) - return callback(Error("command failed to return results"), null) - - // Check if we have an error - if(1 != result.documents[0].ok || result.documents[0].err || result.documents[0].errmsg) { - return callback(utils.toError(result.documents[0])); - } - - // Create statistics value - var stats = {}; - if(result.documents[0].timeMillis) stats['processtime'] = result.documents[0].timeMillis; - if(result.documents[0].counts) stats['counts'] = result.documents[0].counts; - if(result.documents[0].timing) stats['timing'] = result.documents[0].timing; - - // invoked with inline? - if(result.documents[0].results) { - // If we wish for no verbosity - if(options['verbose'] == null || !options['verbose']) { - return callback(null, result.documents[0].results); - } - return callback(null, result.documents[0].results, stats); - } - - // The returned collection - var collection = null; - - // If we have an object it's a different db - if(result.documents[0].result != null && typeof result.documents[0].result == 'object') { - var doc = result.documents[0].result; - collection = self.db.db(doc.db).collection(doc.collection); - } else { - // Create a collection object that wraps the result collection - collection = self.db.collection(result.documents[0].result) - } - - // If we wish for no verbosity - if(options['verbose'] == null || !options['verbose']) { - return callback(err, collection); - } - - // Return stats as third set of values - callback(err, collection, stats); - }); -}; - -/** - * Group function helper - * @ignore - */ -var groupFunction = function () { - var c = db[ns].find(condition); - var map = new Map(); - var reduce_function = reduce; - - while (c.hasNext()) { - var obj = c.next(); - var key = {}; - - for (var i = 0, len = keys.length; i < len; ++i) { - var k = keys[i]; - key[k] = obj[k]; - } - - var aggObj = map.get(key); - - if (aggObj == null) { - var newObj = Object.extend({}, key); - aggObj = Object.extend(newObj, initial); - map.put(key, aggObj); - } - - reduce_function(obj, aggObj); - } - - return { "result": map.values() }; -}.toString(); - -var group = function group(keys, condition, initial, reduce, finalize, command, options, callback) { - var args = Array.prototype.slice.call(arguments, 3); - callback = args.pop(); - // Fetch all commands - reduce = args.length ? args.shift() : null; - finalize = args.length ? args.shift() : null; - command = args.length ? args.shift() : null; - options = args.length ? args.shift() || {} : {}; - - // Make sure we are backward compatible - if(!(typeof finalize == 'function')) { - command = finalize; - finalize = null; - } - - if (!Array.isArray(keys) && keys instanceof Object && typeof(keys) !== 'function' && !(keys instanceof Code)) { - keys = Object.keys(keys); - } - - if(typeof reduce === 'function') { - reduce = reduce.toString(); - } - - if(typeof finalize === 'function') { - finalize = finalize.toString(); - } - - // Set up the command as default - command = command == null ? true : command; - - // Execute using the command - if(command) { - var reduceFunction = reduce instanceof Code - ? reduce - : new Code(reduce); - - var selector = { - group: { - 'ns': this.collectionName - , '$reduce': reduceFunction - , 'cond': condition - , 'initial': initial - , 'out': "inline" - } - }; - - // if finalize is defined - if(finalize != null) selector.group['finalize'] = finalize; - // Set up group selector - if ('function' === typeof keys || keys instanceof Code) { - selector.group.$keyf = keys instanceof Code - ? keys - : new Code(keys); - } else { - var hash = {}; - keys.forEach(function (key) { - hash[key] = 1; - }); - selector.group.key = hash; - } - - // Set read preference if we set one - var readPreference = shared._getReadConcern(this, options); - // Execute command - this.db.command(selector, {readPreference: readPreference}, function(err, result) { - if(err) return callback(err, null); - callback(null, result.retval); - }); - } else { - // Create execution scope - var scope = reduce != null && reduce instanceof Code - ? reduce.scope - : {}; - - scope.ns = this.collectionName; - scope.keys = keys; - scope.condition = condition; - scope.initial = initial; - - // Pass in the function text to execute within mongodb. - var groupfn = groupFunction.replace(/ reduce;/, reduce.toString() + ';'); - - this.db.eval(new Code(groupfn, scope), function (err, results) { - if (err) return callback(err, null); - callback(null, results.result || results); - }); - } -}; - -var aggregate = function(pipeline, options, callback) { - var args = Array.prototype.slice.call(arguments, 0); - callback = args.pop(); - var self = this; - - // If we have any of the supported options in the options object - var opts = args[args.length - 1] || {}; - options = opts.readPreference - || opts.explain - || opts.cursor - || opts.out - || opts.allowDiskUse ? args.pop() : {} - // If the callback is the option (as for cursor override it) - if(typeof callback == 'object' && callback != null) options = callback; - - // Convert operations to an array - if(!Array.isArray(args[0])) { - pipeline = []; - // Push all the operations to the pipeline - for(var i = 0; i < args.length; i++) pipeline.push(args[i]); - } - - // Is the user requesting a cursor - if(options.cursor != null && options.out == null) { - // Set the aggregation cursor options - var agg_cursor_options = options.cursor; - agg_cursor_options.pipe = pipeline; - agg_cursor_options.allowDiskUse = options.allowDiskUse == null ? false : options.allowDiskUse; - // Return the aggregation cursor - return new AggregationCursor(this, this.serverCapabilities, agg_cursor_options); - } - - // If out was specified - if(typeof options.out == 'string') { - pipeline.push({$out: options.out}); - } - - // Build the command - var command = { aggregate : this.collectionName, pipeline : pipeline}; - // If we have allowDiskUse defined - if(options.allowDiskUse) command.allowDiskUse = options.allowDiskUse; - - // Ensure we have the right read preference inheritance - options.readPreference = shared._getReadConcern(this, options); - // If explain has been specified add it - if(options.explain) command.explain = options.explain; - // Execute the command - this.db.command(command, options, function(err, result) { - if(err) { - callback(err); - } else if(result['err'] || result['errmsg']) { - callback(utils.toError(result)); - } else if(typeof result == 'object' && result['serverPipeline']) { - callback(null, result['serverPipeline']); - } else if(typeof result == 'object' && result['stages']) { - callback(null, result['stages']); - } else { - callback(null, result.result); - } - }); -} - -exports.mapReduce = mapReduce; -exports.group = group; -exports.aggregate = aggregate; -exports.pipe = pipe; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/collection/batch/common.js b/node_modules/mongodb/lib/mongodb/collection/batch/common.js deleted file mode 100644 index c31c364..0000000 --- a/node_modules/mongodb/lib/mongodb/collection/batch/common.js +++ /dev/null @@ -1,439 +0,0 @@ -var utils = require('../../utils'); - -// Error codes -var UNKNOWN_ERROR = 8; -var INVALID_BSON_ERROR = 22; -var WRITE_CONCERN_ERROR = 64; -var MULTIPLE_ERROR = 65; - -// Insert types -var INSERT = 1; -var UPDATE = 2; -var REMOVE = 3 - -/** - * Helper function to define properties - */ -var defineReadOnlyProperty = function(self, name, value) { - Object.defineProperty(self, name, { - enumerable: true - , get: function() { - return value; - } - }); -} - -/** - * Keeps the state of a unordered batch so we can rewrite the results - * correctly after command execution - */ -var Batch = function(batchType, originalZeroIndex) { - this.originalZeroIndex = originalZeroIndex; - this.currentIndex = 0; - this.originalIndexes = []; - this.batchType = batchType; - this.operations = []; - this.size = 0; -} - -/** - * Wraps a legacy operation so we can correctly rewrite it's error - */ -var LegacyOp = function(batchType, operation, index) { - this.batchType = batchType; - this.index = index; - this.operation = operation; -} - -/** - * Create a new BatchWriteResult instance (INTERNAL TYPE, do not instantiate directly) - * - * @class Represents a BatchWriteResult - * @property **ok** {boolean} did bulk operation correctly execute - * @property **nInserted** {number} number of inserted documents - * @property **nUpdated** {number} number of documents updated logically - * @property **nUpserted** {number} number of upserted documents - * @property **nModified** {number} number of documents updated physically on disk - * @property **nRemoved** {number} number of removed documents - * @param {Object} batchResult internal data structure with results. - * @return {BatchWriteResult} a BatchWriteResult instance - */ -var BatchWriteResult = function(bulkResult) { - defineReadOnlyProperty(this, "ok", bulkResult.ok); - defineReadOnlyProperty(this, "nInserted", bulkResult.nInserted); - defineReadOnlyProperty(this, "nUpserted", bulkResult.nUpserted); - defineReadOnlyProperty(this, "nMatched", bulkResult.nMatched); - defineReadOnlyProperty(this, "nModified", bulkResult.nModified); - defineReadOnlyProperty(this, "nRemoved", bulkResult.nRemoved); - - /** - * Return an array of upserted ids - * - * @return {Array} - * @api public - */ - this.getUpsertedIds = function() { - return bulkResult.upserted; - } - - /** - * Return the upserted id at position x - * - * @param {Number} index the number of the upserted id to return, returns undefined if no result for passed in index - * @return {Array} - * @api public - */ - this.getUpsertedIdAt = function(index) { - return bulkResult.upserted[index]; - } - - /** - * Return raw internal result - * - * @return {Object} - * @api public - */ - this.getRawResponse = function() { - return bulkResult; - } - - /** - * Returns true if the bulk operation contains a write error - * - * @return {Boolean} - * @api public - */ - this.hasWriteErrors = function() { - return bulkResult.writeErrors.length > 0; - } - - /** - * Returns the number of write errors off the bulk operation - * - * @return {Number} - * @api public - */ - this.getWriteErrorCount = function() { - return bulkResult.writeErrors.length; - } - - /** - * Returns a specific write error object - * - * @return {WriteError} - * @api public - */ - this.getWriteErrorAt = function(index) { - if(index < bulkResult.writeErrors.length) { - return bulkResult.writeErrors[index]; - } - return null; - } - - /** - * Retrieve all write errors - * - * @return {Array} - * @api public - */ - this.getWriteErrors = function() { - return bulkResult.writeErrors; - } - - /** - * Retrieve lastOp if available - * - * @return {Array} - * @api public - */ - this.getLastOp = function() { - return bulkResult.lastOp; - } - - /** - * Retrieve the write concern error if any - * - * @return {WriteConcernError} - * @api public - */ - this.getWriteConcernError = function() { - if(bulkResult.writeConcernErrors.length == 0) { - return null; - } else if(bulkResult.writeConcernErrors.length == 1) { - // Return the error - return bulkResult.writeConcernErrors[0]; - } else { - - // Combine the errors - var errmsg = ""; - for(var i = 0; i < bulkResult.writeConcernErrors.length; i++) { - var err = bulkResult.writeConcernErrors[i]; - errmsg = errmsg + err.errmsg; - - // TODO: Something better - if(i == 0) errmsg = errmsg + " and "; - } - - return new WriteConcernError({ errmsg : errmsg, code : WRITE_CONCERN_ERROR }); - } - } - - this.toJSON = function() { - return bulkResult; - } - - this.toString = function() { - return "BatchWriteResult(" + this.toJSON(bulkResult) + ")"; - } - - this.isOk = function() { - return bulkResult.ok == 1; - } -} - -/** - * Wraps a write concern error - */ -var WriteConcernError = function(err) { - if(!(this instanceof WriteConcernError)) return new WriteConcernError(err); - - // Define properties - defineReadOnlyProperty(this, "code", err.code); - defineReadOnlyProperty(this, "errmsg", err.errmsg); - - this.toJSON = function() { - return {code: err.code, errmsg: err.errmsg}; - } - - this.toString = function() { - return "WriteConcernError(" + err.errmsg + ")"; - } -} - -/** - * Wraps the error - */ -var WriteError = function(err) { - if(!(this instanceof WriteError)) return new WriteError(err); - - // Define properties - defineReadOnlyProperty(this, "code", err.code); - defineReadOnlyProperty(this, "index", err.index); - defineReadOnlyProperty(this, "errmsg", err.errmsg); - - // - // Define access methods - this.getOperation = function() { - return err.op; - } - - this.toJSON = function() { - return {code: err.code, index: err.index, errmsg: err.errmsg, op: err.op}; - } - - this.toString = function() { - return "WriteError(" + JSON.stringify(this.toJSON()) + ")"; - } -} - -/** - * Merges results into shared data structure - */ -var mergeBatchResults = function(ordered, batch, bulkResult, err, result) { - // If we have an error set the result to be the err object - if(err) { - result = err; - } - - // Do we have a top level error stop processing and return - if(result.ok == 0 && bulkResult.ok == 1) { - bulkResult.ok = 0; - bulkResult.error = utils.toError(result); - return; - } else if(result.ok == 0 && bulkResult.ok == 0) { - return; - } - - // Add lastop if available - if(result.lastOp) { - bulkResult.lastOp = result.lastOp; - } - - // If we have an insert Batch type - if(batch.batchType == INSERT && result.n) { - bulkResult.nInserted = bulkResult.nInserted + result.n; - } - - // If we have an insert Batch type - if(batch.batchType == REMOVE && result.n) { - bulkResult.nRemoved = bulkResult.nRemoved + result.n; - } - - var nUpserted = 0; - - // We have an array of upserted values, we need to rewrite the indexes - if(Array.isArray(result.upserted)) { - nUpserted = result.upserted.length; - - for(var i = 0; i < result.upserted.length; i++) { - bulkResult.upserted.push({ - index: result.upserted[i].index + batch.originalZeroIndex - , _id: result.upserted[i]._id - }); - } - } else if(result.upserted) { - - nUpserted = 1; - - bulkResult.upserted.push({ - index: batch.originalZeroIndex - , _id: result.upserted - }); - } - - // If we have an update Batch type - if(batch.batchType == UPDATE && result.n) { - var nModified = result.nModified; - bulkResult.nUpserted = bulkResult.nUpserted + nUpserted; - bulkResult.nMatched = bulkResult.nMatched + (result.n - nUpserted); - - if(typeof nModified == 'number') { - bulkResult.nModified = bulkResult.nModified + nModified; - } else { - bulkResult.nModified = null; - } - } - - if(Array.isArray(result.writeErrors)) { - for(var i = 0; i < result.writeErrors.length; i++) { - - var writeError = { - index: batch.originalZeroIndex + result.writeErrors[i].index - , code: result.writeErrors[i].code - , errmsg: result.writeErrors[i].errmsg - , op: batch.operations[result.writeErrors[i].index] - }; - - bulkResult.writeErrors.push(new WriteError(writeError)); - } - } - - if(result.writeConcernError) { - bulkResult.writeConcernErrors.push(new WriteConcernError(result.writeConcernError)); - } -} - -// -// Merge a legacy result into the master results -var mergeLegacyResults = function(_ordered, _op, _batch, _results, _result, _index) { - // If we have an error already - if(_results.ok == 0) return false; - // Handle error - if((_result.errmsg || _result.err || _result instanceof Error) && _result.wtimeout != true) { - // && ((_result.wtimeout == null && _result.jnote == null && _result.wnote == null)) || _result.err == "norepl") { - var code = _result.code || UNKNOWN_ERROR; // Returned error code or unknown code - var errmsg = _result.errmsg || _result.err; - errmsg = errmsg || _result.message; - - // Result is replication issue, rewrite error to match write command - if(_result.wnote || _result.wtimeout || _result.jnote) { - // Set the code to replication error - code = WRITE_CONCERN_ERROR; - // Ensure we get the right error message - errmsg = _result.wnote || errmsg; - errmsg = _result.jnote || errmsg; - } - - // - // We have an error that is a show stopper, 16544 and 13 are auth errors that should stop processing - if(_result.wnote - || _result.jnote == "journaling not enabled on this server" - || _result.err == "norepl" - || _result.code == 16544 - || _result.code == 13) { - _results.ok = 0; - _results.error = utils.toError({code: code, errmsg: errmsg}); - return false; - } - - // Create a write error - var errResult = new WriteError({ - index: _index - , code: code - , errmsg: errmsg - , op: _op - }); - - // Err details - _results.writeErrors.push(errResult); - - // Check if we any errors - if(_ordered == true - && _result.jnote == null - && _result.wnote == null - && _result.wtimeout == null) { - return false; - } - } else if(_batch.batchType == INSERT) { - _results.nInserted = _results.nInserted + 1; - } else if(_batch.batchType == UPDATE) { - // If we have an upserted value or if the user provided a custom _id value - if(_result.upserted || (!_result.updatedExisting && _result.upserted == null)) { - _results.nUpserted = _results.nUpserted + 1; - } else { - _results.nMatched = _results.nMatched + _result.n; - _results.nModified = null; - } - } else if(_batch.batchType == REMOVE) { - _results.nRemoved = _results.nRemoved + _result; - } - - // We have a write concern error, add a write concern error to the results - if(_result.wtimeout != null || _result.jnote != null || _result.wnote != null) { - var error = _result.err || _result.errmsg || _result.wnote || _result.jnote || _result.wtimeout; - var code = _result.code || WRITE_CONCERN_ERROR; - // Push a write concern error to the list - _results.writeConcernErrors.push(new WriteConcernError({errmsg: error, code: code})); - } - - // We have an upserted field (might happen with a write concern error) - if(_result.upserted) { - _results.upserted.push({ - index: _index - , _id: _result.upserted - }) - } else if(!_result.updatedExisting && _result.upserted == null && _op.q && _op.q._id) { - _results.upserted.push({ - index: _index - , _id: _op.q._id - }) - } -} - -// -// Clone the options -var cloneOptions = function(options) { - var clone = {}; - var keys = Object.keys(options); - for(var i = 0; i < keys.length; i++) { - clone[keys[i]] = options[keys[i]]; - } - - return clone; -} - -// Exports symbols -exports.BatchWriteResult = BatchWriteResult; -exports.WriteError = WriteError; -exports.Batch = Batch; -exports.LegacyOp = LegacyOp; -exports.mergeBatchResults = mergeBatchResults; -exports.cloneOptions = cloneOptions; -exports.mergeLegacyResults = mergeLegacyResults; -exports.INVALID_BSON_ERROR = INVALID_BSON_ERROR; -exports.WRITE_CONCERN_ERROR = WRITE_CONCERN_ERROR; -exports.MULTIPLE_ERROR = MULTIPLE_ERROR; -exports.UNKNOWN_ERROR = UNKNOWN_ERROR; -exports.INSERT = INSERT; -exports.UPDATE = UPDATE; -exports.REMOVE = REMOVE; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/collection/batch/ordered.js b/node_modules/mongodb/lib/mongodb/collection/batch/ordered.js deleted file mode 100644 index 6fe275f..0000000 --- a/node_modules/mongodb/lib/mongodb/collection/batch/ordered.js +++ /dev/null @@ -1,530 +0,0 @@ -var shared = require('../shared') - , common = require('./common') - , utils = require('../../utils') - , hasWriteCommands = utils.hasWriteCommands - , WriteError = common.WriteError - , BatchWriteResult = common.BatchWriteResult - , LegacyOp = common.LegacyOp - , ObjectID = require('bson').ObjectID - , Batch = common.Batch - , mergeBatchResults = common.mergeBatchResults; - -/** - * Create a new OrderedBulkOperation instance (INTERNAL TYPE, do not instantiate directly) - * - * Options - * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write - * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) - * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal - * - **j**, (Boolean, default:false) write waits for journal sync before returning - * - * @class Represents a OrderedBulkOperation - * @param {Object} collection collection instance. - * @param {Object} [options] additional options for the collection. - * @return {Object} a ordered bulk operation instance. - */ -function OrderedBulkOperation (collection, options) { - options = options == null ? {} : options; - // TODO Bring from driver information in isMaster - var self = this; - var executed = false; - - // Current item - var currentOp = null; - - // Handle to the bson serializer, used to calculate running sizes - var db = collection.db; - var bson = db.bson; - - // Namespace for the operation - var namespace = collection.collectionName; - - // Set max byte size - var maxWriteBatchSize = db.serverConfig.checkoutWriter().maxWriteBatchSize || 1000; - var maxBatchSizeBytes = db.serverConfig.checkoutWriter().maxBsonSize; - - // Get the write concern - var writeConcern = shared._getWriteConcern(collection, options); - - // Current batch - var currentBatch = null; - var currentIndex = 0; - var currentBatchSize = 0; - var currentBatchSizeBytes = 0; - var batches = []; - - // Final results - var bulkResult = { - ok: 1 - , writeErrors: [] - , writeConcernErrors: [] - , nInserted: 0 - , nUpserted: 0 - , nMatched: 0 - , nModified: 0 - , nRemoved: 0 - , upserted: [] - }; - - // Specify a full class so we can generate documentation correctly - var FindOperators = function() { - /** - * Add a single update document to the bulk operation - * - * @param {Object} doc update operations - * @return {OrderedBulkOperation} - * @api public - */ - this.update = function(updateDocument) { - // Perform upsert - var upsert = typeof currentOp.upsert == 'boolean' ? currentOp.upsert : false; - - // Establish the update command - var document = { - q: currentOp.selector - , u: updateDocument - , multi: true - , upsert: upsert - } - - // Clear out current Op - currentOp = null; - // Add the update document to the list - return addToOperationsList(self, common.UPDATE, document); - } - - /** - * Add a single update one document to the bulk operation - * - * @param {Object} doc update operations - * @return {OrderedBulkOperation} - * @api public - */ - this.updateOne = function(updateDocument) { - // Perform upsert - var upsert = typeof currentOp.upsert == 'boolean' ? currentOp.upsert : false; - - // Establish the update command - var document = { - q: currentOp.selector - , u: updateDocument - , multi: false - , upsert: upsert - } - - // Clear out current Op - currentOp = null; - // Add the update document to the list - return addToOperationsList(self, common.UPDATE, document); - } - - /** - * Add a replace one operation to the bulk operation - * - * @param {Object} doc the new document to replace the existing one with - * @return {OrderedBulkOperation} - * @api public - */ - this.replaceOne = function(updateDocument) { - this.updateOne(updateDocument); - } - - /** - * Upsert modifier for update bulk operation - * - * @return {OrderedBulkOperation} - * @api public - */ - this.upsert = function() { - currentOp.upsert = true; - return this; - } - - /** - * Add a remove one operation to the bulk operation - * - * @param {Object} doc selector for the removal of documents - * @return {OrderedBulkOperation} - * @api public - */ - this.removeOne = function() { - // Establish the update command - var document = { - q: currentOp.selector - , limit: 1 - } - - // Clear out current Op - currentOp = null; - // Add the remove document to the list - return addToOperationsList(self, common.REMOVE, document); - } - - /** - * Add a remove operation to the bulk operation - * - * @param {Object} doc selector for the single document to remove - * @return {OrderedBulkOperation} - * @api public - */ - this.remove = function() { - // Establish the update command - var document = { - q: currentOp.selector - , limit: 0 - } - - // Clear out current Op - currentOp = null; - // Add the remove document to the list - return addToOperationsList(self, common.REMOVE, document); - } - } - - /** - * Add a single insert document to the bulk operation - * - * @param {Object} doc the document to insert - * @return {OrderedBulkOperation} - * @api public - */ - this.insert = function(document) { - if(document._id == null) document._id = new ObjectID(); - return addToOperationsList(self, common.INSERT, document); - } - - var getOrderedCommand = function(_self, _namespace, _docType, _operationDocuments) { - // Set up the types of operation - if(_docType == common.INSERT) { - return { - insert: _namespace - , documents: _operationDocuments - , ordered:true - } - } else if(_docType == common.UPDATE) { - return { - update: _namespace - , updates: _operationDocuments - , ordered:true - }; - } else if(_docType == common.REMOVE) { - return { - delete: _namespace - , deletes: _operationDocuments - , ordered:true - }; - } - } - - // Add to internal list of documents - var addToOperationsList = function(_self, docType, document) { - // Get the bsonSize - var bsonSize = bson.calculateObjectSize(document, false); - // Throw error if the doc is bigger than the max BSON size - if(bsonSize >= maxBatchSizeBytes) throw utils.toError("document is larger than the maximum size " + maxBatchSizeBytes); - // Create a new batch object if we don't have a current one - if(currentBatch == null) currentBatch = new Batch(docType, currentIndex); - - // Check if we need to create a new batch - if(((currentBatchSize + 1) >= maxWriteBatchSize) - || ((currentBatchSizeBytes + currentBatchSizeBytes) >= maxBatchSizeBytes) - || (currentBatch.batchType != docType)) { - // Save the batch to the execution stack - batches.push(currentBatch); - - // Create a new batch - currentBatch = new Batch(docType, currentIndex); - - // Reset the current size trackers - currentBatchSize = 0; - currentBatchSizeBytes = 0; - } else { - // Update current batch size - currentBatchSize = currentBatchSize + 1; - currentBatchSizeBytes = currentBatchSizeBytes + bsonSize; - } - - // We have an array of documents - if(Array.isArray(document)) { - throw utils.toError("operation passed in cannot be an Array"); - } else { - currentBatch.originalIndexes.push(currentIndex); - currentBatch.operations.push(document) - currentIndex = currentIndex + 1; - } - - // Return self - return _self; - } - - /** - * Initiate a find operation for an update/updateOne/remove/removeOne/replaceOne - * - * @param {Object} doc - * @return {OrderedBulkOperation} - * @api public - */ - this.find = function(selector) { - if (!selector) { - throw utils.toError("Bulk find operation must specify a selector"); - } - - // Save a current selector - currentOp = { - selector: selector - } - - return new FindOperators(); - } - - // - // Execute next write command in a chain - var executeCommands = function(callback) { - if(batches.length == 0) { - return callback(null, new BatchWriteResult(bulkResult)); - } - - // Ordered execution of the command - var batch = batches.shift(); - - // Build the command - var cmd = null; - - // Generate the right update - if(batch.batchType == common.UPDATE) { - cmd = { update: namespace, updates: batch.operations, ordered: true } - } else if(batch.batchType == common.INSERT) { - cmd = { insert: namespace, documents: batch.operations, ordered: true } - } else if(batch.batchType == common.REMOVE) { - cmd = { delete: namespace, deletes: batch.operations, ordered: true } - } - - // If we have a write concern - if(writeConcern != null) { - cmd.writeConcern = writeConcern; - } - - // Execute it - db.command(cmd, function(err, result) { - // Merge the results together - var mergeResult = mergeBatchResults(true, batch, bulkResult, err, result); - if(mergeResult != null) { - return callback(null, new BatchWriteResult(bulkResult)); - } - - // If we had a serious error - if(bulkResult.ok == 0) { - return callback(bulkResult.error, null); - } - - // If we are ordered and have errors and they are - // not all replication errors terminate the operation - if(bulkResult.writeErrors.length > 0) { - return callback(null, new BatchWriteResult(bulkResult)); - } - - // Execute the next command in line - executeCommands(callback); - }); - } - - // - // Execute the inserts - var executeInserts = function(_collection, _batch, _result, _callback) { - if(_batch.operations.length == 0) { - return _callback(null, _result); - } - - // Get the first update - var document = _batch.operations.shift(); - var index = _batch.originalIndexes.shift(); - - // Options for the update operation - var options = writeConcern || {}; - - // Execute the update - _collection.insert(document, options, function(err, r) { - // If we have don't have w:0 merge the result - if(options.w == null || options.w != 0) { - // Merge the results in - var result = common.mergeLegacyResults(true, document, _batch, bulkResult, err || r, index); - - if(result == false) { - return _callback(null, new BatchWriteResult(bulkResult)); - } - } - - // Update the index - _batch.currentIndex = _batch.currentIndex + 1; - - // Execute the next insert - executeInserts(_collection, _batch, _result, _callback); - }); - } - - // - // Execute updates - var executeUpdates = function(_collection, _batch, _result, _callback) { - if(_batch.operations.length == 0) { - return _callback(null, _result); - } - - // Get the first update - var update = _batch.operations.shift(); - var index = _batch.originalIndexes.shift(); - - // Options for the update operation - var options = writeConcern != null ? common.cloneOptions(writeConcern) : {}; - - // Add any additional options - if(update.multi) options.multi = update.multi; - if(update.upsert) options.upsert = update.upsert; - - // Execute the update - _collection.update(update.q, update.u, options, function(err, r, full) { - // If we have don't have w:0 merge the result - if(options.w == null || options.w != 0) { - // Merge the results in - var result = common.mergeLegacyResults(true, update, _batch, bulkResult, err || full, index); - if(result == false) { - return _callback(null, new BatchWriteResult(bulkResult)); - } - } - - // Update the index - _batch.currentIndex = _batch.currentIndex + 1; - - // Execute the next insert - executeUpdates(_collection, _batch, _result, _callback); - }); - } - - // - // Execute updates - var executeRemoves = function(_collection, _batch, _result, _callback) { - if(_batch.operations.length == 0) { - return _callback(null, _result); - } - - // Get the first update - var remove = _batch.operations.shift(); - var index = _batch.originalIndexes.shift(); - - // Options for the update operation - var options = writeConcern != null ? common.cloneOptions(writeConcern) : {}; - - // Add any additional options - options.single = remove.limit == 1 ? true : false; - - // Execute the update - _collection.remove(remove.q, options, function(err, r) { - // If we have don't have w:0 merge the result - if(options.w == null || options.w != 0) { - // Merge the results in - var result = common.mergeLegacyResults(true, remove, _batch, bulkResult, err || r, index); - if(result == false) { - return _callback(null, new BatchWriteResult(bulkResult)); - } - } - - // Update the index - _batch.currentIndex = _batch.currentIndex + 1; - - // Execute the next insert - executeRemoves(_collection, _batch, _result, _callback); - }); - } - - // - // Execute all operation in backwards compatible fashion - var backwardsCompatibilityExecuteCommands = function(callback) { - if(batches.length == 0) { - return callback(null, new BatchWriteResult(bulkResult)); - } - - // Ordered execution of the command - var batch = batches.shift(); - - // Process the legacy operations - var processLegacyOperations = function(err, results) { - // If we have any errors stop executing - if(bulkResult.writeErrors.length > 0) { - return callback(null, new BatchWriteResult(bulkResult)); - } - - // If we have a top level error stop - if(bulkResult.ok == 0) { - return callback(bulkResult.error, null); - } - - // Execute the next step - backwardsCompatibilityExecuteCommands(callback); - } - - // Execute an insert batch - if(batch.batchType == common.INSERT) { - return executeInserts(collection, batch, {n: 0}, processLegacyOperations); - } - - // Execute an update batch - if(batch.batchType == common.UPDATE) { - return executeUpdates(collection, batch, {n: 0}, processLegacyOperations); - } - - // Execute an update batch - if(batch.batchType == common.REMOVE) { - return executeRemoves(collection, batch, {n: 0}, processLegacyOperations); - } - } - - /** - * Execute the ordered bulk operation - * - * Options - * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write - * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) - * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal - * - **j**, (Boolean, default:false) write waits for journal sync before returning - * - * @param {Object} [options] additional options during update. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from from the ordered bulk operation. - * @return {null} - * @api public - */ - this.execute = function(_writeConcern, callback) { - if(executed) throw new utils.toError("batch cannot be re-executed"); - if(typeof _writeConcern == 'function') { - callback = _writeConcern; - } else { - writeConcern = _writeConcern; - } - - // If we have current batch - if(currentBatch) batches.push(currentBatch); - - // If we have no operations in the bulk raise an error - if(batches.length == 0) { - throw utils.toError("Invalid Operation, No operations in bulk"); - } - - // Check if we support bulk commands, override if needed to use legacy ops - if(hasWriteCommands(db.serverConfig.checkoutWriter())) - return executeCommands(callback); - - // Set nModified to null as we don't support this field - bulkResult.nModified = null; - - // Run in backward compatibility mode - backwardsCompatibilityExecuteCommands(callback); - } -} - -/** - * Returns an unordered batch object - * - */ -var initializeOrderedBulkOp = function(options) { - return new OrderedBulkOperation(this, options); -} - -exports.initializeOrderedBulkOp = initializeOrderedBulkOp; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/collection/batch/unordered.js b/node_modules/mongodb/lib/mongodb/collection/batch/unordered.js deleted file mode 100644 index 0024708..0000000 --- a/node_modules/mongodb/lib/mongodb/collection/batch/unordered.js +++ /dev/null @@ -1,576 +0,0 @@ -var shared = require('../shared') - , common = require('./common') - , utils = require('../../utils') - , hasWriteCommands = utils.hasWriteCommands - , WriteError = common.WriteError - , BatchWriteResult = common.BatchWriteResult - , LegacyOp = common.LegacyOp - , ObjectID = require('bson').ObjectID - , Batch = common.Batch - , mergeBatchResults = common.mergeBatchResults; - -/** - * Create a new UnorderedBulkOperation instance (INTERNAL TYPE, do not instantiate directly) - * - * Options - * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write - * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) - * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal - * - **j**, (Boolean, default:false) write waits for journal sync before returning - * - * @class Represents a UnorderedBulkOperation - * @param {Object} collection collection instance. - * @param {Object} [options] additional options for the collection. - * @return {Object} a ordered bulk operation instance. - */ -var UnorderedBulkOperation = function(collection, options) { - options = options == null ? {} : options; - - // Contains reference to self - var self = this; - // Get the namesspace for the write operations - var namespace = collection.collectionName; - // Used to mark operation as executed - var executed = false; - - // Current item - // var currentBatch = null; - var currentOp = null; - var currentIndex = 0; - var currentBatchSize = 0; - var currentBatchSizeBytes = 0; - var batches = []; - - // The current Batches for the different operations - var currentInsertBatch = null; - var currentUpdateBatch = null; - var currentRemoveBatch = null; - - // Handle to the bson serializer, used to calculate running sizes - var db = collection.db; - var bson = db.bson; - - // Set max byte size - var maxBatchSizeBytes = db.serverConfig.checkoutWriter().maxBsonSize; - var maxWriteBatchSize = db.serverConfig.checkoutWriter().maxWriteBatchSize || 1000; - - // Get the write concern - var writeConcern = shared._getWriteConcern(collection, options); - - // Final results - var bulkResult = { - ok: 1 - , writeErrors: [] - , writeConcernErrors: [] - , nInserted: 0 - , nUpserted: 0 - , nMatched: 0 - , nModified: 0 - , nRemoved: 0 - , upserted: [] - }; - - // Specify a full class so we can generate documentation correctly - var FindOperators = function() { - /** - * Add a single update document to the bulk operation - * - * @param {Object} doc update operations - * @return {UnorderedBulkOperation} - * @api public - */ - this.update = function(updateDocument) { - // Perform upsert - var upsert = typeof currentOp.upsert == 'boolean' ? currentOp.upsert : false; - - // Establish the update command - var document = { - q: currentOp.selector - , u: updateDocument - , multi: true - , upsert: upsert - } - - // Clear out current Op - currentOp = null; - // Add the update document to the list - return addToOperationsList(self, common.UPDATE, document); - } - - /** - * Add a single update one document to the bulk operation - * - * @param {Object} doc update operations - * @return {UnorderedBulkOperation} - * @api public - */ - this.updateOne = function(updateDocument) { - // Perform upsert - var upsert = typeof currentOp.upsert == 'boolean' ? currentOp.upsert : false; - - // Establish the update command - var document = { - q: currentOp.selector - , u: updateDocument - , multi: false - , upsert: upsert - } - - // Clear out current Op - currentOp = null; - // Add the update document to the list - return addToOperationsList(self, common.UPDATE, document); - } - - /** - * Add a replace one operation to the bulk operation - * - * @param {Object} doc the new document to replace the existing one with - * @return {UnorderedBulkOperation} - * @api public - */ - this.replaceOne = function(updateDocument) { - this.updateOne(updateDocument); - } - - /** - * Upsert modifier for update bulk operation - * - * @return {UnorderedBulkOperation} - * @api public - */ - this.upsert = function() { - currentOp.upsert = true; - return this; - } - - /** - * Add a remove one operation to the bulk operation - * - * @param {Object} doc selector for the removal of documents - * @return {UnorderedBulkOperation} - * @api public - */ - this.removeOne = function() { - // Establish the update command - var document = { - q: currentOp.selector - , limit: 1 - } - - // Clear out current Op - currentOp = null; - // Add the remove document to the list - return addToOperationsList(self, common.REMOVE, document); - } - - /** - * Add a remove operation to the bulk operation - * - * @param {Object} doc selector for the single document to remove - * @return {UnorderedBulkOperation} - * @api public - */ - this.remove = function() { - // Establish the update command - var document = { - q: currentOp.selector - , limit: 0 - } - - // Clear out current Op - currentOp = null; - // Add the remove document to the list - return addToOperationsList(self, common.REMOVE, document); - } - } - - // - // Add to the operations list - // - var addToOperationsList = function(_self, docType, document) { - // Get the bsonSize - var bsonSize = bson.calculateObjectSize(document, false); - // Throw error if the doc is bigger than the max BSON size - if(bsonSize >= maxBatchSizeBytes) throw utils.toError("document is larger than the maximum size " + maxBatchSizeBytes); - // Holds the current batch - var currentBatch = null; - // Get the right type of batch - if(docType == common.INSERT) { - currentBatch = currentInsertBatch; - } else if(docType == common.UPDATE) { - currentBatch = currentUpdateBatch; - } else if(docType == common.REMOVE) { - currentBatch = currentRemoveBatch; - } - - // Create a new batch object if we don't have a current one - if(currentBatch == null) currentBatch = new Batch(docType, currentIndex); - - // Check if we need to switch batch type - if(currentBatch.batchType != docType) { - // Save current batch - batches.push(currentBatch); - // Create a new batch - currentBatch = new Batch(docType, currentIndex); - - // Reset the current size trackers - currentBatchSize = 0; - currentBatchSizeBytes = 0; - } - - // Check if we need to create a new batch - if(((currentBatchSize + 1) >= maxWriteBatchSize) - || ((currentBatchSizeBytes + currentBatchSizeBytes) >= maxBatchSizeBytes) - || (currentBatch.batchType != docType)) { - // Save the batch to the execution stack - batches.push(currentBatch); - - // Create a new batch - currentBatch = new Batch(docType, currentIndex); - - // Reset the current size trackers - currentBatchSize = 0; - currentBatchSizeBytes = 0; - } else { - // Update current batch size - currentBatchSize = currentBatchSize + 1; - currentBatchSizeBytes = currentBatchSizeBytes + bsonSize; - } - - // We have an array of documents - if(Array.isArray(document)) { - throw utils.toError("operation passed in cannot be an Array"); - } else { - currentBatch.operations.push(document); - currentBatch.originalIndexes.push(currentIndex); - currentIndex = currentIndex + 1; - } - - // Save back the current Batch to the right type - if(docType == common.INSERT) { - currentInsertBatch = currentBatch; - } else if(docType == common.UPDATE) { - currentUpdateBatch = currentBatch; - } else if(docType == common.REMOVE) { - currentRemoveBatch = currentBatch; - } - - // Update current batch size - currentBatchSize = currentBatchSize + 1; - currentBatchSizeBytes = currentBatchSizeBytes + bsonSize; - - // Return self - return _self; - } - - /** - * Add a single insert document to the bulk operation - * - * @param {Object} doc the document to insert - * @return {UnorderedBulkOperation} - * @api public - */ - this.insert = function(document) { - if(document._id == null) document._id = new ObjectID(); - return addToOperationsList(self, common.INSERT, document); - } - - /** - * Initiate a find operation for an update/updateOne/remove/removeOne/replaceOne - * - * @param {Object} selector the selector used to locate documents for the operation - * @return {UnorderedBulkOperation} - * @api public - */ - this.find = function(selector) { - if (!selector) { - throw utils.toError("Bulk find operation must specify a selector"); - } - - // Save a current selector - currentOp = { - selector: selector - } - - return new FindOperators(); - } - - // - // Execute the command - var executeBatch = function(batch, callback) { - // Contains the command we are going to execute - var cmd = null; - - // Generate the right update - if(batch.batchType == common.UPDATE) { - cmd = { update: namespace, updates: batch.operations, ordered: false } - } else if(batch.batchType == common.INSERT) { - cmd = { insert: namespace, documents: batch.operations, ordered: false } - } else if(batch.batchType == common.REMOVE) { - cmd = { delete: namespace, deletes: batch.operations, ordered: false } - } - - // If we have a write concern - if(writeConcern != null) { - cmd.writeConcern = writeConcern; - } - - // Execute the write command - db.command(cmd, function(err, result) { - callback(null, mergeBatchResults(false, batch, bulkResult, err, result)); - }); - } - - // - // Execute all the commands - var executeBatches = function(callback) { - var numberOfCommandsToExecute = batches.length; - // Execute over all the batches - for(var i = 0; i < batches.length; i++) { - executeBatch(batches[i], function(err, result) { - numberOfCommandsToExecute = numberOfCommandsToExecute - 1; - - // Execute - if(numberOfCommandsToExecute == 0) { - // If we have an error stop - if(bulkResult.ok == 0 && callback) { - return callback(bulkResult.error, null); - } - - callback(null, new BatchWriteResult(bulkResult)); - } - }); - } - } - - /** - * Execute the unordered bulk operation - * - * Options - * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write - * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) - * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal - * - **j**, (Boolean, default:false) write waits for journal sync before returning - * - * @param {Object} [options] additional options during update. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from from the unordered bulk operation. - * @return {null} - * @api public - */ - this.execute = function(_writeConcern, callback) { - if(executed) throw utils.toError("batch cannot be re-executed"); - if(typeof _writeConcern == 'function') { - callback = _writeConcern; - } else { - writeConcern = _writeConcern; - } - - // If we have current batch - if(currentInsertBatch) batches.push(currentInsertBatch); - if(currentUpdateBatch) batches.push(currentUpdateBatch); - if(currentRemoveBatch) batches.push(currentRemoveBatch); - - // If we have no operations in the bulk raise an error - if(batches.length == 0) { - throw utils.toError("Invalid Operation, No operations in bulk"); - } - - // Check if we support bulk commands - if(hasWriteCommands(db.serverConfig.checkoutWriter())) - return executeBatches(function(err, result) { - callback(err, result); - }); - - // Set nModified to null as we don't support this field - bulkResult.nModified = null; - - // Run in backward compatibility mode - backwardsCompatibilityExecuteCommands(function(err, result) { - callback(err, result); - }); - } - - // - // Execute the inserts - var executeInserts = function(_collection, _batch, _result, _callback) { - var totalNumberOfInserts = _batch.operations.length; - - // Options for the update operation - var batchOptions = writeConcern || {}; - - // Execute the op - var executeLegacyInsert = function(_i, _op, _options, __callback) { - // Execute the update - _collection.insert(_op.operation, _options, function(err, r) { - // If we have don't have w:0 merge the result - if(_options.w == null || _options.w != 0) { - // Merge the results in - var result = common.mergeLegacyResults(false, _op.operation, _batch, bulkResult, err || r, _op.index); - if(result == false) { - return _callback(null, new BatchWriteResult(bulkResult)); - } - } - - __callback(null, _result); - }); - } - - // Execute all the insert operations - for(var i = 0; i < _batch.operations.length; i++) { - var legacyOp = new LegacyOp(_batch.batchType, _batch.operations[i], _batch.originalIndexes[i]); - executeLegacyInsert(i, legacyOp, batchOptions, function(err, result) { - totalNumberOfInserts = totalNumberOfInserts - 1; - - // No more inserts - if(totalNumberOfInserts == 0) { - _callback(null, _result); - } - }); - } - } - - // - // Execute updates - var executeUpdates = function(_collection, _batch, _result, _callback) { - var totalNumberOfUpdates = _batch.operations.length; - // Options for the update operation - var batchOptions = writeConcern || {}; - - // Execute the op - var executeLegacyUpdate = function(_i, _op, _options, __callback) { - var options = common.cloneOptions(batchOptions); - - // Add any additional options - if(_op.operation.multi != null) options.multi = _op.operation.multi ? true : false; - if(_op.operation.upsert != null) options.upsert = _op.operation.upsert; - - // Execute the update - _collection.update(_op.operation.q, _op.operation.u, options, function(err, r, full) { - // If we have don't have w:0 merge the result - if(options.w == null || options.w != 0) { - // Merge the results in - var result = common.mergeLegacyResults(false, _op.operation, _batch, bulkResult, err || full, _op.index); - if(result == false) { - return _callback(null, new BatchWriteResult(bulkResult)); - } - } - - return __callback(null, _result); - }); - } - - // Execute all the insert operations - for(var i = 0; i < _batch.operations.length; i++) { - var legacyOp = new LegacyOp(_batch.batchType, _batch.operations[i], _batch.originalIndexes[i]); - executeLegacyUpdate(i, legacyOp, options, function(err, result) { - totalNumberOfUpdates = totalNumberOfUpdates - 1; - - // No more inserts - if(totalNumberOfUpdates == 0) { - _callback(null, _result); - } - }); - } - } - - // - // Execute updates - var executeRemoves = function(_collection, _batch, _result, _callback) { - var totalNumberOfRemoves = _batch.operations.length; - // Options for the update operation - var batchOptions = writeConcern || {}; - - // Execute the op - var executeLegacyRemove = function(_i, _op, _options, __callback) { - var options = common.cloneOptions(batchOptions); - - // Add any additional options - if(_op.operation.limit != null) options.single = _op.operation.limit == 1 ? true : false; - - // Execute the update - _collection.remove(_op.operation.q, options, function(err, r) { - // If we have don't have w:0 merge the result - if(options.w == null || options.w != 0) { - // Merge the results in - var result = common.mergeLegacyResults(false, _op.operation, _batch, bulkResult, err || r, _op.index); - if(result == false) { - return _callback(null, new BatchWriteResult(bulkResult)); - } - } - - return __callback(null, _result); - }); - } - - // Execute all the insert operations - for(var i = 0; i < _batch.operations.length; i++) { - var legacyOp = new LegacyOp(_batch.batchType, _batch.operations[i], _batch.originalIndexes[i]); - executeLegacyRemove(i, legacyOp, options, function(err, result) { - totalNumberOfRemoves = totalNumberOfRemoves - 1; - - // No more inserts - if(totalNumberOfRemoves == 0) { - _callback(null, _result); - } - }); - } - } - - // - // Execute all operation in backwards compatible fashion - var backwardsCompatibilityExecuteCommands = function(callback) { - if(batches.length == 0) { - return callback(null, new BatchWriteResult(bulkResult)); - } - - // Ordered execution of the command - var batch = batches.shift(); - - // Process the legacy operations - var processLegacyOperations = function(err, results) { - // Merge the results together - var mergeResult = mergeBatchResults(false, batch, bulkResult, err, results); - if(mergeResult != null) { - return callback(null, mergeResult) - } - - // If we have an error stop - if(bulkResult.ok == 0 && callback) { - var internalCallback = callback; - callback = null; - return internalCallback(bulkResult.error, null); - } else if(bulkResult.ok == 0 && callback == null) { - return; - } - - // Execute the next step - backwardsCompatibilityExecuteCommands(callback); - } - - // Execute an insert batch - if(batch.batchType == common.INSERT) { - return executeInserts(collection, batch, {n: 0}, processLegacyOperations); - } - - // Execute an update batch - if(batch.batchType == common.UPDATE) { - return executeUpdates(collection, batch, {n: 0}, processLegacyOperations); - } - - // Execute an update batch - if(batch.batchType == common.REMOVE) { - return executeRemoves(collection, batch, {n: 0}, processLegacyOperations); - } - } -} - -/** - * Returns an unordered batch object - * - */ -var initializeUnorderedBulkOp = function(options) { - return new UnorderedBulkOperation(this, options); -} - -exports.initializeUnorderedBulkOp = initializeUnorderedBulkOp; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/collection/commands.js b/node_modules/mongodb/lib/mongodb/collection/commands.js deleted file mode 100644 index 91632d0..0000000 --- a/node_modules/mongodb/lib/mongodb/collection/commands.js +++ /dev/null @@ -1,139 +0,0 @@ -var shared = require('./shared') - , utils = require('../utils') - , f = require('util').format - , DbCommand = require('../commands/db_command').DbCommand; - -var stats = function stats(options, callback) { - var args = Array.prototype.slice.call(arguments, 0); - callback = args.pop(); - // Fetch all commands - options = args.length ? args.shift() || {} : {}; - - // Build command object - var commandObject = { - collStats:this.collectionName, - } - - // Check if we have the scale value - if(options['scale'] != null) commandObject['scale'] = options['scale']; - - // Ensure we have the right read preference inheritance - options.readPreference = shared._getReadConcern(this, options); - - // Execute the command - this.db.command(commandObject, options, callback); -} - -var count = function count(query, options, callback) { - var args = Array.prototype.slice.call(arguments, 0); - callback = args.pop(); - query = args.length ? args.shift() || {} : {}; - options = args.length ? args.shift() || {} : {}; - var skip = options.skip; - var limit = options.limit; - var hint = options.hint; - var maxTimeMS = options.maxTimeMS; - - // Final query - var cmd = { - 'count': this.collectionName - , 'query': query - , 'fields': null - }; - - // Add limit and skip if defined - if(typeof skip == 'number') cmd.skip = skip; - if(typeof limit == 'number') cmd.limit = limit; - if(hint) cmd.hint = hint; - - // Ensure we have the right read preference inheritance - options.readPreference = shared._getReadConcern(this, options); - - // Execute the command - this.db.command(cmd, options, function(err, result) { - if(err) return callback(err); - callback(null, result.n); - }); -}; - -var distinct = function distinct(key, query, options, callback) { - var args = Array.prototype.slice.call(arguments, 1); - callback = args.pop(); - query = args.length ? args.shift() || {} : {}; - options = args.length ? args.shift() || {} : {}; - var maxTimeMS = options.maxTimeMS; - - var cmd = { - 'distinct': this.collectionName - , 'key': key - , 'query': query - }; - - // Ensure we have the right read preference inheritance - options.readPreference = shared._getReadConcern(this, options); - - // Execute the command - this.db.command(cmd, options, function(err, result) { - if(err) return callback(err); - callback(null, result.values); - }); -}; - -var rename = function rename (newName, options, callback) { - var self = this; - if(typeof options == 'function') { - callback = options; - options = {} - } - - // Get collection class - var Collection = require('../collection').Collection; - // Ensure the new name is valid - shared.checkCollectionName(newName); - - // Build the command - var renameCollection = self.db.databaseName + "." + self.collectionName; - var toCollection = self.db.databaseName + "." + newName; - var dropTarget = typeof options.dropTarget == 'boolean' ? options.dropTarget : false; - var cmd = {'renameCollection':renameCollection, 'to':toCollection, 'dropTarget':dropTarget}; - - // Execute against admin - self.db.admin().command(cmd, options, function(err, result) { - if(err) return callback(err, null); - var doc = result.documents[0]; - // We have an error - if(doc.errmsg) return callback(utils.toError(doc), null); - try { - return callback(null, new Collection(self.db, newName, self.db.pkFactory)); - } catch(err) { - return callback(utils.toError(err), null); - } - }); -}; - -var options = function options(callback) { - var self = this; - - self.db.listCollections(self.collectionName, function(err, collections) { - if(err) return callback(err); - if(collections.length == 0) return callback(utils.toError(f("collection %s.%s not found", self.db.databaseName, self.collectionName))); - callback(err, collections[0].options || null); - }); -}; - -var isCapped = function isCapped(callback) { - this.options(function(err, document) { - if(err != null) { - callback(err); - } else { - callback(null, document && document.capped); - } - }); -}; - -exports.stats = stats; -exports.count = count; -exports.distinct = distinct; -exports.rename = rename; -exports.options = options; -exports.isCapped = isCapped; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/collection/core.js b/node_modules/mongodb/lib/mongodb/collection/core.js deleted file mode 100644 index 76583a9..0000000 --- a/node_modules/mongodb/lib/mongodb/collection/core.js +++ /dev/null @@ -1,800 +0,0 @@ -var InsertCommand = require('../commands/insert_command').InsertCommand - , DeleteCommand = require('../commands/delete_command').DeleteCommand - , UpdateCommand = require('../commands/update_command').UpdateCommand - , DbCommand = require('../commands/db_command').DbCommand - , utils = require('../utils') - , hasWriteCommands = require('../utils').hasWriteCommands - , shared = require('./shared'); - -/** - * Precompiled regexes - * @ignore - **/ -var eErrorMessages = /No matching object found/; - -// *************************************************** -// Insert function -// *************************************************** -var insert = function insert (docs, options, callback) { - if ('function' === typeof options) callback = options, options = {}; - if(options == null) options = {}; - if(!('function' === typeof callback)) callback = null; - - // Get a connection - var connection = this.db.serverConfig.checkoutWriter(); - var useLegacyOps = options.useLegacyOps == null || options.useLegacyOps == false ? false : true; - // If we support write commands let's perform the insert using it - if(!useLegacyOps && hasWriteCommands(connection) - && !Buffer.isBuffer(docs) - && !(Array.isArray(docs) && docs.length > 0 && Buffer.isBuffer(docs[0]))) { - insertWithWriteCommands(this, Array.isArray(docs) ? docs : [docs], options, callback); - return this - } - - // Backwards compatibility - insertAll(this, Array.isArray(docs) ? docs : [docs], options, callback); - return this; -}; - -// -// Uses the new write commands available from 2.6 > -// -var insertWithWriteCommands = function(self, docs, options, callback) { - // Get the intended namespace for the operation - var namespace = self.collectionName; - - // Ensure we have no \x00 bytes in the name causing wrong parsing - if(!!~namespace.indexOf("\x00")) { - return callback(new Error("namespace cannot contain a null character"), null); - } - - // Check if we have passed in continue on error - var continueOnError = typeof options['keepGoing'] == 'boolean' - ? options['keepGoing'] : false; - continueOnError = typeof options['continueOnError'] == 'boolean' - ? options['continueOnError'] : continueOnError; - - // Do we serialzie functions - var serializeFunctions = typeof options.serializeFunctions != 'boolean' - ? self.serializeFunctions : options.serializeFunctions; - - // Checkout a write connection - var connection = self.db.serverConfig.checkoutWriter(); - - // Do we return the actual result document - var fullResult = typeof options.fullResult == 'boolean' ? options.fullResult : false; - - // Collect errorOptions - var errorOptions = shared._getWriteConcern(self, options); - - // If we have a write command with no callback and w:0 fail - if(errorOptions.w && errorOptions.w != 0 && callback == null) { - throw new Error("writeConcern requires callback") - } - - // Add the documents and decorate them with id's if they have none - for(var index = 0, len = docs.length; index < len; ++index) { - var doc = docs[index]; - - // Add id to each document if it's not already defined - if (!(Buffer.isBuffer(doc)) - && doc['_id'] == null - && self.db.forceServerObjectId != true - && options.forceServerObjectId != true) { - doc['_id'] = self.pkFactory.createPk(); - } - } - - // Single document write - if(docs.length == 1) { - // Create the write command - var write_command = { - insert: namespace - , writeConcern: errorOptions - , ordered: !continueOnError - , documents: docs - } - - // Execute the write command - return self.db.command(write_command - , { connection:connection - , checkKeys: typeof options.checkKeys == 'boolean' ? options.checkKeys : true - , serializeFunctions: serializeFunctions - , writeCommand: true } - , function(err, result) { - if(errorOptions.w == 0 && typeof callback == 'function') return callback(null, null); - if(errorOptions.w == 0) return; - if(callback == null) return; - if(err != null) { - return callback(err, null); - } - - // Result has an error - if(!result.ok || Array.isArray(result.writeErrors) && result.writeErrors.length > 0) { - var error = utils.toError(result.writeErrors[0].errmsg); - error.code = result.writeErrors[0].code; - error.err = result.writeErrors[0].errmsg; - - if (fullResult) return callback(error, result != null ? result.getRawResponse() : null); - // Return the error - return callback(error, null); - } - - if(fullResult) return callback(null, result); - // Return the results for a whole batch - callback(null, docs) - }); - } else { - try { - // Multiple document write (use bulk) - var bulk = !continueOnError ? self.initializeOrderedBulkOp() : self.initializeUnorderedBulkOp(); - // Add all the documents - for(var i = 0; i < docs.length;i++) { - bulk.insert(docs[i]); - } - - // Execute the command - bulk.execute(errorOptions, function(err, result) { - if(errorOptions.w == 0 && typeof callback == 'function') return callback(null, null); - if(errorOptions.w == 0) return; - if(callback == null) return; - if(err) return callback(err, null); - if(result.hasWriteErrors()) { - var error = result.getWriteErrors()[0]; - error.code = result.getWriteErrors()[0].code; - error.err = result.getWriteErrors()[0].errmsg; - - if (fullResult) return callback(error, result != null ? result.getRawResponse() : null); - // Return the error - return callback(error, null); - } - - if(fullResult) return callback(null, result != null ? result.getRawResponse() : null); - // Return the results for a whole batch - callback(null, docs) - }); - } catch(err) { - callback(utils.toError(err), null); - } - } -} - -// -// Uses pre 2.6 OP_INSERT wire protocol -// -var insertAll = function insertAll (self, docs, options, callback) { - if('function' === typeof options) callback = options, options = {}; - if(options == null) options = {}; - if(!('function' === typeof callback)) callback = null; - - // Insert options (flags for insert) - var insertFlags = {}; - // If we have a mongodb version >= 1.9.1 support keepGoing attribute - if(options['keepGoing'] != null) { - insertFlags['keepGoing'] = options['keepGoing']; - } - - // If we have a mongodb version >= 1.9.1 support keepGoing attribute - if(options['continueOnError'] != null) { - insertFlags['continueOnError'] = options['continueOnError']; - } - - // DbName - var dbName = options['dbName']; - // If no dbname defined use the db one - if(dbName == null) { - dbName = self.db.databaseName; - } - - // Either use override on the function, or go back to default on either the collection - // level or db - if(options['serializeFunctions'] != null) { - insertFlags['serializeFunctions'] = options['serializeFunctions']; - } else { - insertFlags['serializeFunctions'] = self.serializeFunctions; - } - - // Get checkKeys value - var checkKeys = typeof options.checkKeys != 'boolean' ? true : options.checkKeys; - - // Do we return the actual result document - var fullResult = typeof options.fullResult == 'boolean' ? options.fullResult : false; - - // Pass in options - var insertCommand = new InsertCommand( - self.db - , dbName + "." + self.collectionName, checkKeys, insertFlags); - - // Add the documents and decorate them with id's if they have none - for(var index = 0, len = docs.length; index < len; ++index) { - var doc = docs[index]; - - // Add id to each document if it's not already defined - if (!(Buffer.isBuffer(doc)) - && doc['_id'] == null - && self.db.forceServerObjectId != true - && options.forceServerObjectId != true) { - doc['_id'] = self.pkFactory.createPk(); - } - - insertCommand.add(doc); - } - - // Collect errorOptions - var errorOptions = shared._getWriteConcern(self, options); - // Default command options - var commandOptions = {}; - // If safe is defined check for error message - if(shared._hasWriteConcern(errorOptions) && typeof callback == 'function') { - // Set safe option - commandOptions['safe'] = errorOptions; - // If we have an error option - if(typeof errorOptions == 'object') { - var keys = Object.keys(errorOptions); - for(var i = 0; i < keys.length; i++) { - commandOptions[keys[i]] = errorOptions[keys[i]]; - } - } - - // If we have a passed in connection use it - if(options.connection) { - commandOptions.connection = options.connection; - } - - // Execute command with safe options (rolls up both command and safe command into one and executes them on the same connection) - self.db._executeInsertCommand(insertCommand, commandOptions, handleWriteResults(function (err, results) { - if(err) return callback(err, null); - if(results == null) return callback(new Error("command failed to return result")); - if(fullResult) return callback(null, results); - callback(null, docs); - })); - } else if(shared._hasWriteConcern(errorOptions) && callback == null) { - throw new Error("Cannot use a writeConcern without a provided callback"); - } else { - // Execute the call without a write concern - var result = self.db._executeInsertCommand(insertCommand, commandOptions); - // If no callback just return - if(!callback) return; - // If error return error - if(result instanceof Error) { - return callback(result); - } - - // Otherwise just return - return callback(null, docs); - } -}; - -// *************************************************** -// Remove function -// *************************************************** -var removeWithWriteCommands = function(self, selector, options, callback) { - if('function' === typeof selector) { - callback = selector; - selector = options = {}; - } else if ('function' === typeof options) { - callback = options; - options = {}; - } - - // Get the intended namespace for the operation - var namespace = self.collectionName; - - // Ensure we have no \x00 bytes in the name causing wrong parsing - if(!!~namespace.indexOf("\x00")) { - return callback(new Error("namespace cannot contain a null character"), null); - } - - // Set default empty selector if none - selector = selector == null ? {} : selector; - - // Check if we have passed in continue on error - var continueOnError = typeof options['keepGoing'] == 'boolean' - ? options['keepGoing'] : false; - continueOnError = typeof options['continueOnError'] == 'boolean' - ? options['continueOnError'] : continueOnError; - - // Do we serialzie functions - var serializeFunctions = typeof options.serializeFunctions != 'boolean' - ? self.serializeFunctions : options.serializeFunctions; - - // Checkout a write connection - var connection = self.db.serverConfig.checkoutWriter(); - - // Figure out the value of top - var limit = options.single == true ? 1 : 0; - var upsert = typeof options.upsert == 'boolean' ? options.upsert : false; - - // Do we return the actual result document - var fullResult = typeof options.fullResult == 'boolean' ? options.fullResult : false; - - // Collect errorOptions - var errorOptions = shared._getWriteConcern(self, options); - - // If we have a write command with no callback and w:0 fail - if(errorOptions.w && errorOptions.w != 0 && callback == null) { - throw new Error("writeConcern requires callback") - } - - // Create the write command - var write_command = { - delete: namespace, - writeConcern: errorOptions, - ordered: !continueOnError, - deletes: [{ - q : selector, - limit: limit - }] - } - - // Execute the write command - self.db.command(write_command - , { connection:connection - , checkKeys: false - , serializeFunctions: serializeFunctions - , writeCommand: true } - , function(err, result) { - if(errorOptions.w == 0 && typeof callback == 'function') return callback(null, null); - if(errorOptions.w == 0) return; - if(callback == null) return; - if(err != null) { - return callback(err, null); - } - - // Result has an error - if(!result.ok || Array.isArray(result.writeErrors) && result.writeErrors.length > 0) { - var error = utils.toError(result.writeErrors[0].errmsg); - error.code = result.writeErrors[0].code; - error.err = result.writeErrors[0].errmsg; - // Return the error - return callback(error, null); - } - - if(fullResult) return callback(null, result); - // Backward compatibility format - var r = backWardsCompatibiltyResults(result, 'remove'); - // Return the results for a whole batch - callback(null, r.n, r) - }); -} - -var remove = function remove(selector, options, callback) { - if('function' === typeof options) callback = options, options = null; - if(options == null) options = {}; - if(!('function' === typeof callback)) callback = null; - - // Get a connection - var connection = this.db.serverConfig.checkoutWriter(); - var useLegacyOps = options.useLegacyOps == null || options.useLegacyOps == false ? false : true; - - // If we support write commands let's perform the insert using it - if(!useLegacyOps && hasWriteCommands(connection) && !Buffer.isBuffer(selector)) { - return removeWithWriteCommands(this, selector, options, callback); - } - - if ('function' === typeof selector) { - callback = selector; - selector = options = {}; - } else if ('function' === typeof options) { - callback = options; - options = {}; - } - - // Ensure options - if(options == null) options = {}; - if(!('function' === typeof callback)) callback = null; - // Ensure we have at least an empty selector - selector = selector == null ? {} : selector; - // Set up flags for the command, if we have a single document remove - var flags = 0 | (options.single ? 1 : 0); - - // Do we return the actual result document - var fullResult = typeof options.fullResult == 'boolean' ? options.fullResult : false; - - // DbName - var dbName = options['dbName']; - // If no dbname defined use the db one - if(dbName == null) { - dbName = this.db.databaseName; - } - - // Create a delete command - var deleteCommand = new DeleteCommand( - this.db - , dbName + "." + this.collectionName - , selector - , flags); - - var self = this; - var errorOptions = shared._getWriteConcern(self, options); - - // Execute the command, do not add a callback as it's async - if(shared._hasWriteConcern(errorOptions) && typeof callback == 'function') { - // Insert options - var commandOptions = {}; - // Set safe option - commandOptions['safe'] = true; - // If we have an error option - if(typeof errorOptions == 'object') { - var keys = Object.keys(errorOptions); - for(var i = 0; i < keys.length; i++) { - commandOptions[keys[i]] = errorOptions[keys[i]]; - } - } - - // If we have a passed in connection use it - if(options.connection) { - commandOptions.connection = options.connection; - } - - // Execute command with safe options (rolls up both command and safe command into one and executes them on the same connection) - this.db._executeRemoveCommand(deleteCommand, commandOptions, handleWriteResults(function (err, results) { - if(err) return callback(err, null); - if(results == null) return callback(new Error("command failed to return result")); - if(fullResult) return callback(null, results); - callback(null, results[0].n); - })); - } else if(shared._hasWriteConcern(errorOptions) && callback == null) { - throw new Error("Cannot use a writeConcern without a provided callback"); - } else { - var result = this.db._executeRemoveCommand(deleteCommand); - // If no callback just return - if (!callback) return; - // If error return error - if (result instanceof Error) { - return callback(result); - } - // Otherwise just return - return callback(); - } -}; - -// *************************************************** -// Save function -// *************************************************** -var save = function save(doc, options, callback) { - if('function' === typeof options) callback = options, options = null; - if(options == null) options = {}; - if(!('function' === typeof callback)) callback = null; - // Throw an error if attempting to perform a bulk operation - if(Array.isArray(doc)) throw new Error("doc parameter must be a single document"); - // Extract the id, if we have one we need to do a update command - var id = doc['_id']; - var commandOptions = shared._getWriteConcern(this, options); - if(options.connection) commandOptions.connection = options.connection; - if(typeof options.fullResult == 'boolean') commandOptions.fullResult = options.fullResult; - - if(id != null) { - commandOptions.upsert = true; - this.update({ _id: id }, doc, commandOptions, callback); - } else { - this.insert(doc, commandOptions, callback && function (err, docs) { - if(err) return callback(err, null); - - if(Array.isArray(docs)) { - callback(err, docs[0]); - } else { - callback(err, docs); - } - }); - } -}; - -// *************************************************** -// Update document function -// *************************************************** -var updateWithWriteCommands = function(self, selector, document, options, callback) { - if('function' === typeof options) callback = options, options = null; - if(options == null) options = {}; - if(!('function' === typeof callback)) callback = null; - - // Get the intended namespace for the operation - var namespace = self.collectionName; - - // Ensure we have no \x00 bytes in the name causing wrong parsing - if(!!~namespace.indexOf("\x00")) { - return callback(new Error("namespace cannot contain a null character"), null); - } - - // If we are not providing a selector or document throw - if(selector == null || typeof selector != 'object') - return callback(new Error("selector must be a valid JavaScript object")); - if(document == null || typeof document != 'object') - return callback(new Error("document must be a valid JavaScript object")); - - // Check if we have passed in continue on error - var continueOnError = typeof options['keepGoing'] == 'boolean' - ? options['keepGoing'] : false; - continueOnError = typeof options['continueOnError'] == 'boolean' - ? options['continueOnError'] : continueOnError; - - // Do we serialzie functions - var serializeFunctions = typeof options.serializeFunctions != 'boolean' - ? self.serializeFunctions : options.serializeFunctions; - - // Checkout a write connection - var connection = self.db.serverConfig.checkoutWriter(); - - // Figure out the value of top - var multi = typeof options.multi == 'boolean' ? options.multi : false; - var upsert = typeof options.upsert == 'boolean' ? options.upsert : false; - - // Do we return the actual result document - var fullResult = typeof options.fullResult == 'boolean' ? options.fullResult : false; - - // Collect errorOptions - var errorOptions = shared._getWriteConcern(self, options); - - // If we have a write command with no callback and w:0 fail - if(errorOptions.w && errorOptions.w != 0 && callback == null) { - throw new Error("writeConcern requires callback") - } - - // Create the write command - var write_command = { - update: namespace, - writeConcern: errorOptions, - ordered: !continueOnError, - updates: [{ - q : selector, - u: document, - multi: multi, - upsert: upsert - }] - } - - // Check if we have a checkKeys override - var checkKeys = typeof options.checkKeys == 'boolean' ? options.checkKeys : false; - - // Execute the write command - self.db.command(write_command - , { connection:connection - , checkKeys: checkKeys - , serializeFunctions: serializeFunctions - , writeCommand: true } - , function(err, result) { - if(errorOptions.w == 0 && typeof callback == 'function') return callback(null, null); - if(errorOptions.w == 0) return; - if(callback == null) return; - - if(errorOptions.w == 0 && typeof callback == 'function') return callback(null, null); - if(errorOptions.w == 0) return; - if(callback == null) return; - if(err != null) { - return callback(err, null); - } - - // Result has an error - if(!result.ok || Array.isArray(result.writeErrors) && result.writeErrors.length > 0) { - var error = utils.toError(result.writeErrors[0].errmsg); - error.code = result.writeErrors[0].code; - error.err = result.writeErrors[0].errmsg; - return callback(error, null); - } - - if(fullResult) return callback(null, result); - // Backward compatibility format - var r = backWardsCompatibiltyResults(result, 'update'); - // Return the results for a whole batch - callback(null, r.n, r) - }); -} - -var backWardsCompatibiltyResults = function(result, op) { - // Upserted - var upsertedValue = null; - var finalResult = null; - var updatedExisting = true; - - // We have a single document upserted result - if(Array.isArray(result.upserted) || result.upserted != null) { - updatedExisting = false; - upsertedValue = result.upserted; - } - - // Final result - if(op == 'remove' || op == 'insert') { - finalResult = {ok: true, n: result.n} - } else { - finalResult = {ok: true, n: result.n, updatedExisting: updatedExisting} - } - - if(upsertedValue != null) finalResult.upserted = upsertedValue; - return finalResult; -} - -var handleWriteResults = function handleWriteResults(callback) { - return function(err, error) { - var documents = error && error.documents; - if(!callback) return; - // We have an error - if(err) return callback(err, null); - // If no document something is terribly wrong - if(error == null) return callback(utils.toError("MongoDB did not return a response")); - // Handle the case where no result was returned - if(error != null && documents == null) { - if(typeof error.err == 'string') { - return callback(utils.toError(error.err)); - } else if(typeof error.errmsg == 'string') { - return callback(utils.toError(error.errmsg)); - } else { - return callback(utils.toError("Unknown MongoDB error")); - } - } - - // Handler normal cases - if(documents[0].err || documents[0].errmsg) { - callback(utils.toError(documents[0])); - } else if(documents[0].jnote || documents[0].wtimeout) { - callback(utils.toError(documents[0])); - } else { - callback(err, documents); - } - } -} - -var update = function update(selector, document, options, callback) { - if('function' === typeof options) callback = options, options = null; - if(options == null) options = {}; - if(!('function' === typeof callback)) callback = null; - - // Get a connection - var connection = options.connection || this.db.serverConfig.checkoutWriter(); - var useLegacyOps = options.useLegacyOps == null || options.useLegacyOps == false ? false : true; - // If we support write commands let's perform the insert using it - if(!useLegacyOps && hasWriteCommands(connection) && !Buffer.isBuffer(selector) && !Buffer.isBuffer(document)) { - return updateWithWriteCommands(this, selector, document, options, callback); - } - - // DbName - var dbName = options['dbName']; - // If no dbname defined use the db one - if(dbName == null) { - dbName = this.db.databaseName; - } - - // If we are not providing a selector or document throw - if(selector == null || typeof selector != 'object') return callback(new Error("selector must be a valid JavaScript object")); - if(document == null || typeof document != 'object') return callback(new Error("document must be a valid JavaScript object")); - - // Do we return the actual result document - var fullResult = typeof options.fullResult == 'boolean' ? options.fullResult : false; - - // Either use override on the function, or go back to default on either the collection - // level or db - if(options['serializeFunctions'] != null) { - options['serializeFunctions'] = options['serializeFunctions']; - } else { - options['serializeFunctions'] = this.serializeFunctions; - } - - // Build the options command - var updateCommand = new UpdateCommand( - this.db - , dbName + "." + this.collectionName - , selector - , document - , options); - - var self = this; - // Unpack the error options if any - var errorOptions = shared._getWriteConcern(this, options); - // If safe is defined check for error message - if(shared._hasWriteConcern(errorOptions) && typeof callback == 'function') { - // Insert options - var commandOptions = {}; - // Set safe option - commandOptions['safe'] = errorOptions; - // If we have an error option - if(typeof errorOptions == 'object') { - var keys = Object.keys(errorOptions); - for(var i = 0; i < keys.length; i++) { - commandOptions[keys[i]] = errorOptions[keys[i]]; - } - } - - // If we have a passed in connection use it - if(options.connection) { - commandOptions.connection = options.connection; - } - - // Execute command with safe options (rolls up both command and safe command into one and executes them on the same connection) - this.db._executeUpdateCommand(updateCommand, commandOptions, handleWriteResults(function(err, results) { - if(err) return callback(err, null); - if(results == null) return callback(new Error("command failed to return result")); - if(fullResult) return callback(null, results); - callback(null, results[0].n, results[0]); - })); - } else if(shared._hasWriteConcern(errorOptions) && callback == null) { - throw new Error("Cannot use a writeConcern without a provided callback"); - } else { - // Execute update - var result = this.db._executeUpdateCommand(updateCommand); - // If no callback just return - if (!callback) return; - // If error return error - if (result instanceof Error) { - return callback(result); - } - - // Otherwise just return - return callback(); - } -}; - -// *************************************************** -// findAndModify function -// *************************************************** -var findAndModify = function findAndModify (query, sort, doc, options, callback) { - var args = Array.prototype.slice.call(arguments, 1); - callback = args.pop(); - sort = args.length ? args.shift() || [] : []; - doc = args.length ? args.shift() : null; - options = args.length ? args.shift() || {} : {}; - var self = this; - - var queryObject = { - 'findandmodify': this.collectionName - , 'query': query - }; - - sort = utils.formattedOrderClause(sort); - if (sort) { - queryObject.sort = sort; - } - - queryObject.new = options.new ? 1 : 0; - queryObject.remove = options.remove ? 1 : 0; - queryObject.upsert = options.upsert ? 1 : 0; - - if (options.fields) { - queryObject.fields = options.fields; - } - - if (doc && !options.remove) { - queryObject.update = doc; - } - - // Checkout a write connection - options.connection = self.db.serverConfig.checkoutWriter(); - - // Either use override on the function, or go back to default on either the collection - // level or db - if(options['serializeFunctions'] != null) { - options['serializeFunctions'] = options['serializeFunctions']; - } else { - options['serializeFunctions'] = this.serializeFunctions; - } - - // No check on the documents - options.checkKeys = false; - - // Execute the command - this.db.command(queryObject - , options, function(err, result) { - if(err) return callback(err, null); - return callback(null, result.value, result); - }); -} - -// *************************************************** -// findAndRemove function -// *************************************************** -var findAndRemove = function(query, sort, options, callback) { - var args = Array.prototype.slice.call(arguments, 1); - callback = args.pop(); - sort = args.length ? args.shift() || [] : []; - options = args.length ? args.shift() || {} : {}; - // Add the remove option - options['remove'] = true; - // Execute the callback - this.findAndModify(query, sort, null, options, callback); -} - -// Map methods -exports.insert = insert; -exports.remove = remove; -exports.save = save; -exports.update = update; -exports.findAndModify = findAndModify; -exports.findAndRemove = findAndRemove; diff --git a/node_modules/mongodb/lib/mongodb/collection/geo.js b/node_modules/mongodb/lib/mongodb/collection/geo.js deleted file mode 100644 index 05d0c59..0000000 --- a/node_modules/mongodb/lib/mongodb/collection/geo.js +++ /dev/null @@ -1,78 +0,0 @@ -var shared = require('./shared') - , utils = require('../utils'); - -var geoNear = function geoNear(x, y, options, callback) { - var point = typeof(x) == 'object' && x - , args = Array.prototype.slice.call(arguments, point?1:2); - - callback = args.pop(); - // Fetch all commands - options = args.length ? args.shift() || {} : {}; - - // Build command object - var commandObject = { - geoNear:this.collectionName, - near: point || [x, y] - } - - // Ensure we have the right read preference inheritance - options.readPreference = shared._getReadConcern(this, options); - - // Exclude readPreference and existing options to prevent user from - // shooting themselves in the foot - var exclude = { - readPreference: true, - geoNear: true, - near: true - }; - - commandObject = utils.decorateCommand(commandObject, options, exclude); - - // Execute the command - this.db.command(commandObject, options, function (err, res) { - if (err) { - callback(err); - } else if (res.err || res.errmsg) { - callback(utils.toError(res)); - } else { - // should we only be returning res.results here? Not sure if the user - // should see the other return information - callback(null, res); - } - }); -} - -var geoHaystackSearch = function geoHaystackSearch(x, y, options, callback) { - var args = Array.prototype.slice.call(arguments, 2); - callback = args.pop(); - // Fetch all commands - options = args.length ? args.shift() || {} : {}; - - // Build command object - var commandObject = { - geoSearch:this.collectionName, - near: [x, y] - } - - // Remove read preference from hash if it exists - commandObject = utils.decorateCommand(commandObject, options, {readPreference: true}); - - // Ensure we have the right read preference inheritance - options.readPreference = shared._getReadConcern(this, options); - - // Execute the command - this.db.command(commandObject, options, function (err, res) { - if (err) { - callback(err); - } else if (res.err || res.errmsg) { - callback(utils.toError(res)); - } else { - // should we only be returning res.results here? Not sure if the user - // should see the other return information - callback(null, res); - } - }); -} - -exports.geoNear = geoNear; -exports.geoHaystackSearch = geoHaystackSearch; diff --git a/node_modules/mongodb/lib/mongodb/collection/index.js b/node_modules/mongodb/lib/mongodb/collection/index.js deleted file mode 100644 index dda9cc8..0000000 --- a/node_modules/mongodb/lib/mongodb/collection/index.js +++ /dev/null @@ -1,72 +0,0 @@ -var _getWriteConcern = require('./shared')._getWriteConcern; - -var createIndex = function createIndex (fieldOrSpec, options, callback) { - // Clean up call - var args = Array.prototype.slice.call(arguments, 1); - callback = args.pop(); - options = args.length ? args.shift() || {} : {}; - options = typeof callback === 'function' ? options : callback; - options = options == null ? {} : options; - - // Collect errorOptions - var errorOptions = _getWriteConcern(this, options); - // Execute create index - this.db.createIndex(this.collectionName, fieldOrSpec, options, callback); -}; - -var indexExists = function indexExists(indexes, callback) { - this.indexInformation(function(err, indexInformation) { - // If we have an error return - if(err != null) return callback(err, null); - // Let's check for the index names - if(Array.isArray(indexes)) { - for(var i = 0; i < indexes.length; i++) { - if(indexInformation[indexes[i]] == null) { - return callback(null, false); - } - } - - // All keys found return true - return callback(null, true); - } else { - return callback(null, indexInformation[indexes] != null); - } - }); -} - -var dropAllIndexes = function dropIndexes (callback) { - this.db.dropIndex(this.collectionName, '*', function (err, result) { - if(err) return callback(err, false); - callback(null, true); - }); -}; - -var indexInformation = function indexInformation (options, callback) { - // Unpack calls - var args = Array.prototype.slice.call(arguments, 0); - callback = args.pop(); - options = args.length ? args.shift() || {} : {}; - // Call the index information - this.db.indexInformation(this.collectionName, options, callback); -}; - -var ensureIndex = function ensureIndex (fieldOrSpec, options, callback) { - // Clean up call - if (typeof callback === 'undefined' && typeof options === 'function') { - callback = options; - options = {}; - } - - if (options == null) { - options = {}; - } - - // Execute create index - this.db.ensureIndex(this.collectionName, fieldOrSpec, options, callback); -}; - -exports.createIndex = createIndex; -exports.indexExists = indexExists; -exports.dropAllIndexes = dropAllIndexes; -exports.indexInformation = indexInformation; -exports.ensureIndex = ensureIndex; diff --git a/node_modules/mongodb/lib/mongodb/collection/query.js b/node_modules/mongodb/lib/mongodb/collection/query.js deleted file mode 100644 index ebff44d..0000000 --- a/node_modules/mongodb/lib/mongodb/collection/query.js +++ /dev/null @@ -1,218 +0,0 @@ -var ObjectID = require('bson').ObjectID - , Long = require('bson').Long - , DbCommand = require('../commands/db_command').DbCommand - , CommandCursor = require('../command_cursor').CommandCursor - , Scope = require('../scope').Scope - , shared = require('./shared') - , utils = require('../utils'); - -var testForFields = { - limit: 1, sort: 1, fields:1, skip: 1, hint: 1, explain: 1, snapshot: 1, timeout: 1, tailable: 1, tailableRetryInterval: 1 - , numberOfRetries: 1, awaitdata: 1, exhaust: 1, batchSize: 1, returnKey: 1, maxScan: 1, min: 1, max: 1, showDiskLoc: 1 - , comment: 1, raw: 1, readPreference: 1, partial: 1, read: 1, dbName: 1, oplogReplay: 1, connection: 1, maxTimeMS: 1 -}; - -// -// Find method -// -var find = function find () { - var options - , args = Array.prototype.slice.call(arguments, 0) - , has_callback = typeof args[args.length - 1] === 'function' - , has_weird_callback = typeof args[0] === 'function' - , callback = has_callback ? args.pop() : (has_weird_callback ? args.shift() : null) - , len = args.length - , selector = len >= 1 ? args[0] : {} - , fields = len >= 2 ? args[1] : undefined; - - if(len === 1 && has_weird_callback) { - // backwards compat for callback?, options case - selector = {}; - options = args[0]; - } - - if(len === 2 && !Array.isArray(fields)) { - var fieldKeys = Object.keys(fields); - var is_option = false; - - for(var i = 0; i < fieldKeys.length; i++) { - if(testForFields[fieldKeys[i]] != null) { - is_option = true; - break; - } - } - - if(is_option) { - options = fields; - fields = undefined; - } else { - options = {}; - } - } else if(len === 2 && Array.isArray(fields) && !Array.isArray(fields[0])) { - var newFields = {}; - // Rewrite the array - for(var i = 0; i < fields.length; i++) { - newFields[fields[i]] = 1; - } - // Set the fields - fields = newFields; - } - - if(3 === len) { - options = args[2]; - } - - // Ensure selector is not null - selector = selector == null ? {} : selector; - // Validate correctness off the selector - var object = selector; - if(Buffer.isBuffer(object)) { - var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24; - if(object_size != object.length) { - var error = new Error("query selector raw message size does not match message header size [" + object.length + "] != [" + object_size + "]"); - error.name = 'MongoError'; - throw error; - } - } - - // Validate correctness of the field selector - var object = fields; - if(Buffer.isBuffer(object)) { - var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24; - if(object_size != object.length) { - var error = new Error("query fields raw message size does not match message header size [" + object.length + "] != [" + object_size + "]"); - error.name = 'MongoError'; - throw error; - } - } - - // Check special case where we are using an objectId - if(selector instanceof ObjectID || (selector != null && selector._bsontype == 'ObjectID')) { - selector = {_id:selector}; - } - - // If it's a serialized fields field we need to just let it through - // user be warned it better be good - if(options && options.fields && !(Buffer.isBuffer(options.fields))) { - fields = {}; - - if(Array.isArray(options.fields)) { - if(!options.fields.length) { - fields['_id'] = 1; - } else { - for (var i = 0, l = options.fields.length; i < l; i++) { - fields[options.fields[i]] = 1; - } - } - } else { - fields = options.fields; - } - } - - if (!options) options = {}; - - var newOptions = {}; - // Make a shallow copy of options - for (var key in options) { - newOptions[key] = options[key]; - } - - newOptions.skip = len > 3 ? args[2] : options.skip ? options.skip : 0; - newOptions.limit = len > 3 ? args[3] : options.limit ? options.limit : 0; - newOptions.raw = options.raw != null && typeof options.raw === 'boolean' ? options.raw : this.raw; - newOptions.hint = options.hint != null ? shared.normalizeHintField(options.hint) : this.internalHint; - newOptions.timeout = len == 5 ? args[4] : typeof options.timeout === 'undefined' ? undefined : options.timeout; - // If we have overridden slaveOk otherwise use the default db setting - newOptions.slaveOk = options.slaveOk != null ? options.slaveOk : this.db.slaveOk; - - // Set option - var o = newOptions; - // Support read/readPreference - if(o["read"] != null) o["readPreference"] = o["read"]; - // If no readPreference specified set the collection level readPreference - o.readPreference = o.readPreference ? o.readPreference : this.readPreference; - // If still no readPreference specified set the db level - o.readPreference = o.readPreference ? o.readPreference : this.db.options.readPreference; - // Set slaveok if needed - if(o.readPreference == "secondary" || o.read == "secondaryOnly") o.slaveOk = true; - - // Ensure the query is an object - if(selector != null && typeof selector != 'object') { - throw utils.toError("query selector must be an object"); - } - - // Set the selector - o.selector = selector; - - // Create precursor - var scope = new Scope(this, {}, fields, o); - // Callback for backward compatibility - if(callback) return callback(null, scope.find(selector)); - // Return the pre cursor object - return scope.find(selector); -}; - -var findOne = function findOne () { - var self = this; - var args = Array.prototype.slice.call(arguments, 0); - var callback = args.pop(); - var cursor = this.find.apply(this, args).limit(-1).batchSize(1); - - // Return the item - cursor.nextObject(function(err, item) { - if(err != null) return callback(utils.toError(err), null); - callback(null, item); - }); -}; - -var parallelCollectionScan = function parallelCollectionScan (options, callback) { - var self = this; - - if(typeof options == 'function') { - callback = options; - options = {numCursors: 1}; - } - - // Set number of cursors to 1 - options.numCursors = options.numCursors || 1; - options.batchSize = options.batchSize || 1000; - - // Set read preference if we set one - options.readPreference = shared._getReadConcern(this, options); - - // Create command object - var commandObject = { - parallelCollectionScan: this.collectionName - , numCursors: options.numCursors - } - - // Execute the command - this.db.command(commandObject, options, function(err, result) { - if(err) return callback(err, null); - if(result == null) return callback(new Error("no result returned for parallelCollectionScan"), null); - - var cursors = []; - // Create command cursors for each item - for(var i = 0; i < result.cursors.length; i++) { - var rawId = result.cursors[i].cursor.id - // Convert cursorId to Long if needed - var cursorId = typeof rawId == 'number' ? Long.fromNumber(rawId) : rawId; - - // Command cursor options - var commandOptions = { - batchSize: options.batchSize - , cursorId: cursorId - , items: result.cursors[i].cursor.firstBatch - } - - // Add a command cursor - cursors.push(new CommandCursor(self.db, self, {}, commandOptions)); - } - - callback(null, cursors); - }); -} - -exports.find = find; -exports.findOne = findOne; -exports.parallelCollectionScan = parallelCollectionScan; diff --git a/node_modules/mongodb/lib/mongodb/collection/shared.js b/node_modules/mongodb/lib/mongodb/collection/shared.js deleted file mode 100644 index 77eae03..0000000 --- a/node_modules/mongodb/lib/mongodb/collection/shared.js +++ /dev/null @@ -1,120 +0,0 @@ -// *************************************************** -// Write concerns -// *************************************************** -var _hasWriteConcern = function(errorOptions) { - return errorOptions == true - || errorOptions.w > 0 - || errorOptions.w == 'majority' - || errorOptions.j == true - || errorOptions.journal == true - || errorOptions.fsync == true -} - -var _setWriteConcernHash = function(options) { - var finalOptions = {}; - if(options.w != null) finalOptions.w = options.w; - if(options.journal == true) finalOptions.j = options.journal; - if(options.j == true) finalOptions.j = options.j; - if(options.fsync == true) finalOptions.fsync = options.fsync; - if(options.wtimeout != null) finalOptions.wtimeout = options.wtimeout; - return finalOptions; -} - -var _getWriteConcern = function(self, options) { - // Final options - var finalOptions = {w:1}; - // Local options verification - if(options.w != null || typeof options.j == 'boolean' || typeof options.journal == 'boolean' || typeof options.fsync == 'boolean') { - finalOptions = _setWriteConcernHash(options); - } else if(typeof options.safe == "boolean") { - finalOptions = {w: (options.safe ? 1 : 0)}; - } else if(options.safe != null && typeof options.safe == 'object') { - finalOptions = _setWriteConcernHash(options.safe); - } else if(self.opts.w != null || typeof self.opts.j == 'boolean' || typeof self.opts.journal == 'boolean' || typeof self.opts.fsync == 'boolean') { - finalOptions = _setWriteConcernHash(self.opts); - } else if(typeof self.opts.safe == "boolean") { - finalOptions = {w: (self.opts.safe ? 1 : 0)}; - } else if(self.db.safe.w != null || typeof self.db.safe.j == 'boolean' || typeof self.db.safe.journal == 'boolean' || typeof self.db.safe.fsync == 'boolean') { - finalOptions = _setWriteConcernHash(self.db.safe); - } else if(self.db.options.w != null || typeof self.db.options.j == 'boolean' || typeof self.db.options.journal == 'boolean' || typeof self.db.options.fsync == 'boolean') { - finalOptions = _setWriteConcernHash(self.db.options); - } else if(typeof self.db.safe == "boolean") { - finalOptions = {w: (self.db.safe ? 1 : 0)}; - } - - // Ensure we don't have an invalid combination of write concerns - if(finalOptions.w < 1 - && (finalOptions.journal == true || finalOptions.j == true || finalOptions.fsync == true)) throw new Error("No acknowlegement using w < 1 cannot be combined with journal:true or fsync:true"); - - // Return the options - return finalOptions; -} - -var _getReadConcern = function(self, options) { - if(options.readPreference) return options.readPreference; - if(self.readPreference) return self.readPreference; - if(self.db.readPreference) return self.readPreference; - return 'primary'; -} - -/** - * @ignore - */ -var checkCollectionName = function checkCollectionName (collectionName) { - if('string' !== typeof collectionName) { - throw Error("collection name must be a String"); - } - - if(!collectionName || collectionName.indexOf('..') != -1) { - throw Error("collection names cannot be empty"); - } - - if(collectionName.indexOf('$') != -1 && - collectionName.match(/((^\$cmd)|(oplog\.\$main))/) == null) { - throw Error("collection names must not contain '$'"); - } - - if(collectionName.match(/^\.|\.$/) != null) { - throw Error("collection names must not start or end with '.'"); - } - - // Validate that we are not passing 0x00 in the colletion name - if(!!~collectionName.indexOf("\x00")) { - throw new Error("collection names cannot contain a null character"); - } -}; - - -/** - * Normalizes a `hint` argument. - * - * @param {String|Object|Array} hint - * @return {Object} - * @api private - */ -var normalizeHintField = function normalizeHintField(hint) { - var finalHint = null; - - if(typeof hint == 'string') { - finalHint = hint; - } else if(Array.isArray(hint)) { - finalHint = {}; - - hint.forEach(function(param) { - finalHint[param] = 1; - }); - } else if(hint != null && typeof hint == 'object') { - finalHint = {}; - for (var name in hint) { - finalHint[name] = hint[name]; - } - } - - return finalHint; -}; - -exports._getWriteConcern = _getWriteConcern; -exports._hasWriteConcern = _hasWriteConcern; -exports._getReadConcern = _getReadConcern; -exports.checkCollectionName = checkCollectionName; -exports.normalizeHintField = normalizeHintField; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/command_cursor.js b/node_modules/mongodb/lib/mongodb/command_cursor.js deleted file mode 100644 index d248b22..0000000 --- a/node_modules/mongodb/lib/mongodb/command_cursor.js +++ /dev/null @@ -1,362 +0,0 @@ -var Long = require('bson').Long - , Readable = require('stream').Readable || require('readable-stream').Readable - , GetMoreCommand = require('./commands/get_more_command').GetMoreCommand - , inherits = require('util').inherits; - -var CommandCursor = function(db, collection, command, options) { - // Ensure empty options if no options passed - options = options || {}; - - // Set up - Readable.call(this, {objectMode: true}); - - // Default cursor id is 0 - var cursorId = options.cursorId || Long.fromInt(0); - var zeroCursor = Long.fromInt(0); - var state = 'init'; - var batchSize = options.batchSize || 0; - - // Hardcode batch size - if(command && command.cursor) { - batchSize = command.cursor.batchSize || 0; - } - - // BatchSize - var raw = options.raw || false; - var readPreference = options.readPreference || 'primary'; - - // Checkout a connection - var connection = db.serverConfig.checkoutReader(readPreference); - // MaxTimeMS - var maxTimeMS = options.maxTimeMS; - - // Contains all the items - var items = options.items || null; - - // Execute getmore - var getMore = function(callback) { - // Resolve more of the cursor using the getMore command - var getMoreCommand = new GetMoreCommand(db - , db.databaseName + "." + collection.collectionName - , batchSize - , cursorId - ); - - // Set up options - var command_options = { connection:connection }; - - // Execute the getMore Command - db._executeQueryCommand(getMoreCommand, command_options, function(err, result) { - if(err) { - items = []; - state = 'closed'; - return callback(err); - } - - // Return all the documents - callback(null, result); - }); - } - - var exhaustGetMore = function(callback) { - getMore(function(err, result) { - if(err) { - items = []; - state = 'closed'; - return callback(err, null); - } - - // Add the items - items = items.concat(result.documents); - - // Set the cursor id - cursorId = result.cursorId; - if(typeof cursorId == 'number') cursorId = Long.fromNumber(cursorId); - - // If the cursor is done - if(result.cursorId.equals(zeroCursor)) { - return callback(null, items); - } - - // Check the cursor id - exhaustGetMore(callback); - }); - } - - var exhaustGetMoreEach = function(callback) { - getMore(function(err, result) { - if(err) { - items = []; - state = 'closed'; - return callback(err, null); - } - - // Add the items - items = result.documents; - - // Emit all the items in the first batch - while(items.length > 0) { - callback(null, items.shift()); - } - - // Set the cursor id - cursorId = result.cursorId; - if(typeof cursorId == 'number') cursorId = Long.fromNumber(cursorId); - - // If the cursor is done - if(result.cursorId.equals(zeroCursor)) { - state = "closed"; - return callback(null, null); - } - - // Check the cursor id - exhaustGetMoreEach(callback); - }); - } - - // - // Get all the elements - // - this.get = function(options, callback) { - if(typeof options == 'function') { - callback = options; - options = {}; - } - - // Set the connection to the passed in one if it's provided - connection = options.connection ? options.connection : connection; - - // Command options - var _options = {connection:connection}; - if(typeof maxTimeMS == 'number') _options.maxTimeMS = maxTimeMS; - - // If we have a cursor Id already not equal to 0 we are just going to - // exhaust the cursor - if(cursorId.notEquals(zeroCursor)) { - // If no items set an empty array - items = items || []; - // Exhaust the cursor - return exhaustGetMore(callback); - } - - // Execute the internal command first - db.command(command, _options, function(err, result) { - if(err) { - state = 'closed'; - return callback(err, null); - } - - // Retrieve the cursor id - cursorId = result.cursor.id; - if(typeof cursorId == 'number') cursorId = Long.fromNumber(cursorId); - - // Validate cursorId - if(cursorId.equals(zeroCursor)) { - return callback(null, result.cursor.firstBatch); - }; - - // Add to the items - items = result.cursor.firstBatch; - // Execute the getMore - exhaustGetMore(callback); - }); - } - - // - // Iterate over all the items - // - this.each = function(options, callback) { - if(typeof options == 'function') { - callback = options; - options = {}; - } - - // If it's a closed cursor return error - if(this.isClosed()) return callback(new Error("cursor is closed")); - // Set the connection to the passed in one if it's provided - connection = options.connection ? options.connection : connection; - - // Command options - var _options = {connection:connection}; - if(typeof maxTimeMS == 'number') _options.maxTimeMS = maxTimeMS; - - // If we have a cursor Id already not equal to 0 we are just going to - // exhaust the cursor - if(cursorId.notEquals(zeroCursor)) { - // If no items set an empty array - items = items || []; - - // Emit all the items in the first batch - while(items.length > 0) { - callback(null, items.shift()); - } - - // Exhaust the cursor - return exhaustGetMoreEach(callback); - } - - // Execute the internal command first - db.command(command, _options, function(err, result) { - if(err) { - state = 'closed'; - return callback(err, null); - } - - // Get all the items - items = result.cursor.firstBatch; - - // Emit all the items in the first batch - while(items.length > 0) { - callback(null, items.shift()); - } - - // Retrieve the cursor id - cursorId = result.cursor.id; - if(typeof cursorId == 'number') cursorId = Long.fromNumber(cursorId); - - // If no cursor we just finish up the current batch of items - if(cursorId.equals(zeroCursor)) { - state = 'closed'; - return callback(null, null); - } - - // Emit each until no more getMore's - exhaustGetMoreEach(callback); - }); - } - - // - // Get the next object - // - this.next = function(options, callback) { - if(typeof options == 'function') { - callback = options; - options = {}; - } - - // If it's a closed cursor return error - if(this.isClosed()) return callback(new Error("cursor is closed")); - - // Set the connection to the passed in one if it's provided - connection = options.connection ? options.connection : connection; - - // Command options - var _options = {connection:connection}; - if(typeof maxTimeMS == 'number') _options.maxTimeMS = maxTimeMS; - - // If we have a cursor Id already not equal to 0 we are just going to - // going to bypass the command execution - if(cursorId.notEquals(zeroCursor)) { - items = items || []; - } - - // Execute the internal command first - if(!items) { - db.command(command, _options, function(err, result) { - if(err) { - state = 'closed'; - return callback(err, null); - } - - // Retrieve the cursor id - cursorId = result.cursor.id; - if(typeof cursorId == 'number') cursorId = Long.fromNumber(cursorId); - // Get the first batch results - items = result.cursor.firstBatch; - // We have items return the first one - if(items.length > 0) { - callback(null, items.shift()); - } else { - state = 'closed'; - callback(null, null); - } - }); - } else if(items.length > 0) { - callback(null, items.shift()); - } else if(items.length == 0 && cursorId.equals(zeroCursor)) { - state = 'closed'; - callback(null, null); - } else { - // Execute a getMore - getMore(function(err, result) { - if(err) { - state = 'closed'; - return callback(err, null); - } - - // Set the cursor id - cursorId = result.cursorId; - if(typeof cursorId == 'number') cursorId = Long.fromNumber(cursorId); - - // Add the items - items = items.concat(result.documents); - // If no more items - if(items.length == 0) { - state = 'closed'; - return callback(null, null); - } - - // Return the item - return callback(null, items.shift()); - }) - } - } - - // Validate if the cursor is closed - this.isClosed = function() { - return state == 'closed'; - } - - // Allow us to set the MaxTimeMS - this.maxTimeMS = function(_maxTimeMS) { - maxTimeMS = _maxTimeMS; - } - - // Close the cursor sending a kill cursor command if needed - this.close = function(callback) { - // Close the cursor if not needed - if(cursorId instanceof Long && cursorId.greaterThan(Long.fromInt(0))) { - try { - var command = new KillCursorCommand(this.db, [cursorId]); - // Added an empty callback to ensure we don't throw any null exceptions - db._executeQueryCommand(command, {connection:connection}); - } catch(err) {} - } - - // Null out the connection - connection = null; - // Reset cursor id - cursorId = Long.fromInt(0); - // Set to closed status - state = 'closed'; - // Clear out all the items - items = null; - - if(callback) { - callback(null, null); - } - } - - // - // Stream method - // - this._read = function(n) { - var self = this; - // Read the next command cursor doc - self.next(function(err, result) { - if(err) { - self.emit('error', err); - return self.push(null); - } - - self.push(result); - }); - } -} - -// Inherit from Readable -if(Readable != null) { - inherits(CommandCursor, Readable); -} - -exports.CommandCursor = CommandCursor; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/commands/base_command.js b/node_modules/mongodb/lib/mongodb/commands/base_command.js deleted file mode 100644 index 9558582..0000000 --- a/node_modules/mongodb/lib/mongodb/commands/base_command.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - Base object used for common functionality -**/ -var BaseCommand = exports.BaseCommand = function BaseCommand() { -}; - -var id = 1; -BaseCommand.prototype.getRequestId = function getRequestId() { - if (!this.requestId) this.requestId = id++; - return this.requestId; -}; - -BaseCommand.prototype.setMongosReadPreference = function setMongosReadPreference(readPreference, tags) {} - -BaseCommand.prototype.updateRequestId = function() { - this.requestId = id++; - return this.requestId; -}; - -// OpCodes -BaseCommand.OP_REPLY = 1; -BaseCommand.OP_MSG = 1000; -BaseCommand.OP_UPDATE = 2001; -BaseCommand.OP_INSERT = 2002; -BaseCommand.OP_GET_BY_OID = 2003; -BaseCommand.OP_QUERY = 2004; -BaseCommand.OP_GET_MORE = 2005; -BaseCommand.OP_DELETE = 2006; -BaseCommand.OP_KILL_CURSORS = 2007; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/commands/db_command.js b/node_modules/mongodb/lib/mongodb/commands/db_command.js deleted file mode 100644 index 39bdb6e..0000000 --- a/node_modules/mongodb/lib/mongodb/commands/db_command.js +++ /dev/null @@ -1,101 +0,0 @@ -var QueryCommand = require('./query_command').QueryCommand, - InsertCommand = require('./insert_command').InsertCommand, - inherits = require('util').inherits, - utils = require('../utils'), - crypto = require('crypto'); - -/** - Db Command -**/ -var DbCommand = exports.DbCommand = function(dbInstance, collectionName, queryOptions, numberToSkip, numberToReturn, query, returnFieldSelector, options) { - QueryCommand.call(this); - this.collectionName = collectionName; - this.queryOptions = queryOptions; - this.numberToSkip = numberToSkip; - this.numberToReturn = numberToReturn; - this.query = query; - this.returnFieldSelector = returnFieldSelector; - this.db = dbInstance; - - // Set the slave ok bit - if(this.db && this.db.slaveOk) { - this.queryOptions |= QueryCommand.OPTS_SLAVE; - } - - // Make sure we don't get a null exception - options = options == null ? {} : options; - - // Allow for overriding the BSON checkKeys function - this.checkKeys = typeof options['checkKeys'] == 'boolean' ? options["checkKeys"] : true; - - // Let us defined on a command basis if we want functions to be serialized or not - if(options['serializeFunctions'] != null && options['serializeFunctions']) { - this.serializeFunctions = true; - } -}; - -inherits(DbCommand, QueryCommand); - -// Constants -DbCommand.SYSTEM_NAMESPACE_COLLECTION = "system.namespaces"; -DbCommand.SYSTEM_INDEX_COLLECTION = "system.indexes"; -DbCommand.SYSTEM_PROFILE_COLLECTION = "system.profile"; -DbCommand.SYSTEM_USER_COLLECTION = "system.users"; -DbCommand.SYSTEM_COMMAND_COLLECTION = "$cmd"; -DbCommand.SYSTEM_JS_COLLECTION = "system.js"; - -// New commands -DbCommand.NcreateIsMasterCommand = function(db, databaseName) { - return new DbCommand(db, databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'ismaster':1}, null); -}; - -// Provide constructors for different db commands -DbCommand.createIsMasterCommand = function(db) { - return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'ismaster':1}, null); -}; - -DbCommand.createGetLastErrorCommand = function(options, db) { - if (typeof db === 'undefined') { - db = options; - options = {}; - } - // Final command - var command = {'getlasterror':1}; - // If we have an options Object let's merge in the fields (fsync/wtimeout/w) - if('object' === typeof options) { - for(var name in options) { - command[name] = options[name] - } - } - - // Special case for w == 1, remove the w - if(1 == command.w) { - delete command.w; - } - - // Execute command - return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, command, null); -}; - -DbCommand.createGetLastStatusCommand = DbCommand.createGetLastErrorCommand; - -DbCommand.createDbCommand = function(db, command_hash, options, auth_db) { - var db_name = (auth_db ? auth_db : db.databaseName) + "." + DbCommand.SYSTEM_COMMAND_COLLECTION; - options = options == null ? {checkKeys: false} : options; - return new DbCommand(db, db_name, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, command_hash, null, options); -}; - -DbCommand.createAdminDbCommand = function(db, command_hash) { - return new DbCommand(db, "admin." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, command_hash, null); -}; - -DbCommand.createAdminDbCommandSlaveOk = function(db, command_hash) { - return new DbCommand(db, "admin." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT | QueryCommand.OPTS_SLAVE, 0, -1, command_hash, null); -}; - -DbCommand.createDbSlaveOkCommand = function(db, command_hash, options) { - options = options == null ? {checkKeys: false} : options; - var dbName = options.dbName ? options.dbName : db.databaseName; - var flags = options.slaveOk ? QueryCommand.OPTS_NO_CURSOR_TIMEOUT | QueryCommand.OPTS_SLAVE : QueryCommand.OPTS_NO_CURSOR_TIMEOUT; - return new DbCommand(db, dbName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, flags, 0, -1, command_hash, null, options); -}; diff --git a/node_modules/mongodb/lib/mongodb/commands/delete_command.js b/node_modules/mongodb/lib/mongodb/commands/delete_command.js deleted file mode 100644 index 61a37ed..0000000 --- a/node_modules/mongodb/lib/mongodb/commands/delete_command.js +++ /dev/null @@ -1,129 +0,0 @@ -var BaseCommand = require('./base_command').BaseCommand, - inherits = require('util').inherits; - -/** - Insert Document Command -**/ -var DeleteCommand = exports.DeleteCommand = function(db, collectionName, selector, flags) { - BaseCommand.call(this); - - // Validate correctness off the selector - var object = selector; - if(Buffer.isBuffer(object)) { - var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24; - if(object_size != object.length) { - var error = new Error("delete raw message size does not match message header size [" + object.length + "] != [" + object_size + "]"); - error.name = 'MongoError'; - throw error; - } - } - - this.flags = flags; - this.collectionName = collectionName; - this.selector = selector; - this.db = db; -}; - -inherits(DeleteCommand, BaseCommand); - -DeleteCommand.OP_DELETE = 2006; - -/* -struct { - MsgHeader header; // standard message header - int32 ZERO; // 0 - reserved for future use - cstring fullCollectionName; // "dbname.collectionname" - int32 ZERO; // 0 - reserved for future use - mongo.BSON selector; // query object. See below for details. -} -*/ -DeleteCommand.prototype.toBinary = function(bsonSettings) { - // Validate that we are not passing 0x00 in the colletion name - if(!!~this.collectionName.indexOf("\x00")) { - throw new Error("namespace cannot contain a null character"); - } - - // Calculate total length of the document - var totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + 4 + this.db.bson.calculateObjectSize(this.selector, false, true) + (4 * 4); - - // Enforce maximum bson size - if(!bsonSettings.disableDriverBSONSizeCheck - && totalLengthOfCommand > bsonSettings.maxBsonSize) - throw new Error("Document exceeds maximum allowed bson size of " + bsonSettings.maxBsonSize + " bytes"); - - if(bsonSettings.disableDriverBSONSizeCheck - && totalLengthOfCommand > bsonSettings.maxMessageSizeBytes) - throw new Error("Command exceeds maximum message size of " + bsonSettings.maxMessageSizeBytes + " bytes"); - - // Let's build the single pass buffer command - var _index = 0; - var _command = new Buffer(totalLengthOfCommand); - // Write the header information to the buffer - _command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff; - _command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff; - _command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff; - _command[_index] = totalLengthOfCommand & 0xff; - // Adjust index - _index = _index + 4; - // Write the request ID - _command[_index + 3] = (this.requestId >> 24) & 0xff; - _command[_index + 2] = (this.requestId >> 16) & 0xff; - _command[_index + 1] = (this.requestId >> 8) & 0xff; - _command[_index] = this.requestId & 0xff; - // Adjust index - _index = _index + 4; - // Write zero - _command[_index++] = 0; - _command[_index++] = 0; - _command[_index++] = 0; - _command[_index++] = 0; - // Write the op_code for the command - _command[_index + 3] = (DeleteCommand.OP_DELETE >> 24) & 0xff; - _command[_index + 2] = (DeleteCommand.OP_DELETE >> 16) & 0xff; - _command[_index + 1] = (DeleteCommand.OP_DELETE >> 8) & 0xff; - _command[_index] = DeleteCommand.OP_DELETE & 0xff; - // Adjust index - _index = _index + 4; - - // Write zero - _command[_index++] = 0; - _command[_index++] = 0; - _command[_index++] = 0; - _command[_index++] = 0; - - // Write the collection name to the command - _index = _index + _command.write(this.collectionName, _index, 'utf8') + 1; - _command[_index - 1] = 0; - - // Write the flags - _command[_index + 3] = (this.flags >> 24) & 0xff; - _command[_index + 2] = (this.flags >> 16) & 0xff; - _command[_index + 1] = (this.flags >> 8) & 0xff; - _command[_index] = this.flags & 0xff; - // Adjust index - _index = _index + 4; - - // Document binary length - var documentLength = 0 - - // Serialize the selector - // If we are passing a raw buffer, do minimal validation - if(Buffer.isBuffer(this.selector)) { - documentLength = this.selector.length; - // Copy the data into the current buffer - this.selector.copy(_command, _index); - } else { - documentLength = this.db.bson.serializeWithBufferAndIndex(this.selector, false, _command, _index) - _index + 1; - } - - // Write the length to the document - _command[_index + 3] = (documentLength >> 24) & 0xff; - _command[_index + 2] = (documentLength >> 16) & 0xff; - _command[_index + 1] = (documentLength >> 8) & 0xff; - _command[_index] = documentLength & 0xff; - // Update index in buffer - _index = _index + documentLength; - // Add terminating 0 for the object - _command[_index - 1] = 0; - return _command; -}; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/commands/get_more_command.js b/node_modules/mongodb/lib/mongodb/commands/get_more_command.js deleted file mode 100644 index 1b6b172..0000000 --- a/node_modules/mongodb/lib/mongodb/commands/get_more_command.js +++ /dev/null @@ -1,88 +0,0 @@ -var BaseCommand = require('./base_command').BaseCommand, - inherits = require('util').inherits, - binaryutils = require('../utils'); - -/** - Get More Document Command -**/ -var GetMoreCommand = exports.GetMoreCommand = function(db, collectionName, numberToReturn, cursorId) { - BaseCommand.call(this); - - this.collectionName = collectionName; - this.numberToReturn = numberToReturn; - this.cursorId = cursorId; - this.db = db; -}; - -inherits(GetMoreCommand, BaseCommand); - -GetMoreCommand.OP_GET_MORE = 2005; - -GetMoreCommand.prototype.toBinary = function() { - // Validate that we are not passing 0x00 in the colletion name - if(!!~this.collectionName.indexOf("\x00")) { - throw new Error("namespace cannot contain a null character"); - } - - // Calculate total length of the document - var totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + 4 + 8 + (4 * 4); - // Let's build the single pass buffer command - var _index = 0; - var _command = new Buffer(totalLengthOfCommand); - // Write the header information to the buffer - _command[_index++] = totalLengthOfCommand & 0xff; - _command[_index++] = (totalLengthOfCommand >> 8) & 0xff; - _command[_index++] = (totalLengthOfCommand >> 16) & 0xff; - _command[_index++] = (totalLengthOfCommand >> 24) & 0xff; - - // Write the request ID - _command[_index++] = this.requestId & 0xff; - _command[_index++] = (this.requestId >> 8) & 0xff; - _command[_index++] = (this.requestId >> 16) & 0xff; - _command[_index++] = (this.requestId >> 24) & 0xff; - - // Write zero - _command[_index++] = 0; - _command[_index++] = 0; - _command[_index++] = 0; - _command[_index++] = 0; - - // Write the op_code for the command - _command[_index++] = GetMoreCommand.OP_GET_MORE & 0xff; - _command[_index++] = (GetMoreCommand.OP_GET_MORE >> 8) & 0xff; - _command[_index++] = (GetMoreCommand.OP_GET_MORE >> 16) & 0xff; - _command[_index++] = (GetMoreCommand.OP_GET_MORE >> 24) & 0xff; - - // Write zero - _command[_index++] = 0; - _command[_index++] = 0; - _command[_index++] = 0; - _command[_index++] = 0; - - // Write the collection name to the command - _index = _index + _command.write(this.collectionName, _index, 'utf8') + 1; - _command[_index - 1] = 0; - - // Number of documents to return - _command[_index++] = this.numberToReturn & 0xff; - _command[_index++] = (this.numberToReturn >> 8) & 0xff; - _command[_index++] = (this.numberToReturn >> 16) & 0xff; - _command[_index++] = (this.numberToReturn >> 24) & 0xff; - - // Encode the cursor id - var low_bits = this.cursorId.getLowBits(); - // Encode low bits - _command[_index++] = low_bits & 0xff; - _command[_index++] = (low_bits >> 8) & 0xff; - _command[_index++] = (low_bits >> 16) & 0xff; - _command[_index++] = (low_bits >> 24) & 0xff; - - var high_bits = this.cursorId.getHighBits(); - // Encode high bits - _command[_index++] = high_bits & 0xff; - _command[_index++] = (high_bits >> 8) & 0xff; - _command[_index++] = (high_bits >> 16) & 0xff; - _command[_index++] = (high_bits >> 24) & 0xff; - // Return command - return _command; -}; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/commands/insert_command.js b/node_modules/mongodb/lib/mongodb/commands/insert_command.js deleted file mode 100644 index c6e51e9..0000000 --- a/node_modules/mongodb/lib/mongodb/commands/insert_command.js +++ /dev/null @@ -1,161 +0,0 @@ -var BaseCommand = require('./base_command').BaseCommand, - inherits = require('util').inherits; - -/** - Insert Document Command -**/ -var InsertCommand = exports.InsertCommand = function(db, collectionName, checkKeys, options) { - BaseCommand.call(this); - - this.collectionName = collectionName; - this.documents = []; - this.checkKeys = checkKeys == null ? true : checkKeys; - this.db = db; - this.flags = 0; - this.serializeFunctions = false; - - // Ensure valid options hash - options = options == null ? {} : options; - - // Check if we have keepGoing set -> set flag if it's the case - if(options['keepGoing'] != null && options['keepGoing']) { - // This will finish inserting all non-index violating documents even if it returns an error - this.flags = 1; - } - - // Check if we have keepGoing set -> set flag if it's the case - if(options['continueOnError'] != null && options['continueOnError']) { - // This will finish inserting all non-index violating documents even if it returns an error - this.flags = 1; - } - - // Let us defined on a command basis if we want functions to be serialized or not - if(options['serializeFunctions'] != null && options['serializeFunctions']) { - this.serializeFunctions = true; - } -}; - -inherits(InsertCommand, BaseCommand); - -// OpCodes -InsertCommand.OP_INSERT = 2002; - -InsertCommand.prototype.add = function(document) { - if(Buffer.isBuffer(document)) { - var object_size = document[0] | document[1] << 8 | document[2] << 16 | document[3] << 24; - if(object_size != document.length) { - var error = new Error("insert raw message size does not match message header size [" + document.length + "] != [" + object_size + "]"); - error.name = 'MongoError'; - throw error; - } - } - - this.documents.push(document); - return this; -}; - -/* -struct { - MsgHeader header; // standard message header - int32 ZERO; // 0 - reserved for future use - cstring fullCollectionName; // "dbname.collectionname" - BSON[] documents; // one or more documents to insert into the collection -} -*/ -InsertCommand.prototype.toBinary = function(bsonSettings) { - // Validate that we are not passing 0x00 in the colletion name - if(!!~this.collectionName.indexOf("\x00")) { - throw new Error("namespace cannot contain a null character"); - } - - // Calculate total length of the document - var totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + (4 * 4); - // var docLength = 0 - for(var i = 0; i < this.documents.length; i++) { - if(Buffer.isBuffer(this.documents[i])) { - totalLengthOfCommand += this.documents[i].length; - } else { - // Calculate size of document - totalLengthOfCommand += this.db.bson.calculateObjectSize(this.documents[i], this.serializeFunctions, true); - } - } - - // Enforce maximum bson size - if(!bsonSettings.disableDriverBSONSizeCheck - && totalLengthOfCommand > bsonSettings.maxBsonSize) - throw new Error("Document exceeds maximum allowed bson size of " + bsonSettings.maxBsonSize + " bytes"); - - if(bsonSettings.disableDriverBSONSizeCheck - && totalLengthOfCommand > bsonSettings.maxMessageSizeBytes) - throw new Error("Command exceeds maximum message size of " + bsonSettings.maxMessageSizeBytes + " bytes"); - - // Let's build the single pass buffer command - var _index = 0; - var _command = new Buffer(totalLengthOfCommand); - // Write the header information to the buffer - _command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff; - _command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff; - _command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff; - _command[_index] = totalLengthOfCommand & 0xff; - // Adjust index - _index = _index + 4; - // Write the request ID - _command[_index + 3] = (this.requestId >> 24) & 0xff; - _command[_index + 2] = (this.requestId >> 16) & 0xff; - _command[_index + 1] = (this.requestId >> 8) & 0xff; - _command[_index] = this.requestId & 0xff; - // Adjust index - _index = _index + 4; - // Write zero - _command[_index++] = 0; - _command[_index++] = 0; - _command[_index++] = 0; - _command[_index++] = 0; - // Write the op_code for the command - _command[_index + 3] = (InsertCommand.OP_INSERT >> 24) & 0xff; - _command[_index + 2] = (InsertCommand.OP_INSERT >> 16) & 0xff; - _command[_index + 1] = (InsertCommand.OP_INSERT >> 8) & 0xff; - _command[_index] = InsertCommand.OP_INSERT & 0xff; - // Adjust index - _index = _index + 4; - // Write flags if any - _command[_index + 3] = (this.flags >> 24) & 0xff; - _command[_index + 2] = (this.flags >> 16) & 0xff; - _command[_index + 1] = (this.flags >> 8) & 0xff; - _command[_index] = this.flags & 0xff; - // Adjust index - _index = _index + 4; - // Write the collection name to the command - _index = _index + _command.write(this.collectionName, _index, 'utf8') + 1; - _command[_index - 1] = 0; - - // Write all the bson documents to the buffer at the index offset - for(var i = 0; i < this.documents.length; i++) { - // Document binary length - var documentLength = 0 - var object = this.documents[i]; - - // Serialize the selector - // If we are passing a raw buffer, do minimal validation - if(Buffer.isBuffer(object)) { - documentLength = object.length; - // Copy the data into the current buffer - object.copy(_command, _index); - } else { - // Serialize the document straight to the buffer - documentLength = this.db.bson.serializeWithBufferAndIndex(object, this.checkKeys, _command, _index, this.serializeFunctions) - _index + 1; - } - - // Write the length to the document - _command[_index + 3] = (documentLength >> 24) & 0xff; - _command[_index + 2] = (documentLength >> 16) & 0xff; - _command[_index + 1] = (documentLength >> 8) & 0xff; - _command[_index] = documentLength & 0xff; - // Update index in buffer - _index = _index + documentLength; - // Add terminating 0 for the object - _command[_index - 1] = 0; - } - - return _command; -}; diff --git a/node_modules/mongodb/lib/mongodb/commands/kill_cursor_command.js b/node_modules/mongodb/lib/mongodb/commands/kill_cursor_command.js deleted file mode 100644 index d8ccb0c..0000000 --- a/node_modules/mongodb/lib/mongodb/commands/kill_cursor_command.js +++ /dev/null @@ -1,98 +0,0 @@ -var BaseCommand = require('./base_command').BaseCommand, - inherits = require('util').inherits, - binaryutils = require('../utils'); - -/** - Insert Document Command -**/ -var KillCursorCommand = exports.KillCursorCommand = function(db, cursorIds) { - BaseCommand.call(this); - - this.cursorIds = cursorIds; - this.db = db; -}; - -inherits(KillCursorCommand, BaseCommand); - -KillCursorCommand.OP_KILL_CURSORS = 2007; - -/* -struct { - MsgHeader header; // standard message header - int32 ZERO; // 0 - reserved for future use - int32 numberOfCursorIDs; // number of cursorIDs in message - int64[] cursorIDs; // array of cursorIDs to close -} -*/ -KillCursorCommand.prototype.toBinary = function() { - // Calculate total length of the document - var totalLengthOfCommand = 4 + 4 + (4 * 4) + (this.cursorIds.length * 8); - // Let's build the single pass buffer command - var _index = 0; - var _command = new Buffer(totalLengthOfCommand); - // Write the header information to the buffer - _command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff; - _command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff; - _command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff; - _command[_index] = totalLengthOfCommand & 0xff; - // Adjust index - _index = _index + 4; - // Write the request ID - _command[_index + 3] = (this.requestId >> 24) & 0xff; - _command[_index + 2] = (this.requestId >> 16) & 0xff; - _command[_index + 1] = (this.requestId >> 8) & 0xff; - _command[_index] = this.requestId & 0xff; - // Adjust index - _index = _index + 4; - // Write zero - _command[_index++] = 0; - _command[_index++] = 0; - _command[_index++] = 0; - _command[_index++] = 0; - // Write the op_code for the command - _command[_index + 3] = (KillCursorCommand.OP_KILL_CURSORS >> 24) & 0xff; - _command[_index + 2] = (KillCursorCommand.OP_KILL_CURSORS >> 16) & 0xff; - _command[_index + 1] = (KillCursorCommand.OP_KILL_CURSORS >> 8) & 0xff; - _command[_index] = KillCursorCommand.OP_KILL_CURSORS & 0xff; - // Adjust index - _index = _index + 4; - - // Write zero - _command[_index++] = 0; - _command[_index++] = 0; - _command[_index++] = 0; - _command[_index++] = 0; - - // Number of cursors to kill - var numberOfCursors = this.cursorIds.length; - _command[_index + 3] = (numberOfCursors >> 24) & 0xff; - _command[_index + 2] = (numberOfCursors >> 16) & 0xff; - _command[_index + 1] = (numberOfCursors >> 8) & 0xff; - _command[_index] = numberOfCursors & 0xff; - // Adjust index - _index = _index + 4; - - // Encode all the cursors - for(var i = 0; i < this.cursorIds.length; i++) { - // Encode the cursor id - var low_bits = this.cursorIds[i].getLowBits(); - // Encode low bits - _command[_index + 3] = (low_bits >> 24) & 0xff; - _command[_index + 2] = (low_bits >> 16) & 0xff; - _command[_index + 1] = (low_bits >> 8) & 0xff; - _command[_index] = low_bits & 0xff; - // Adjust index - _index = _index + 4; - - var high_bits = this.cursorIds[i].getHighBits(); - // Encode high bits - _command[_index + 3] = (high_bits >> 24) & 0xff; - _command[_index + 2] = (high_bits >> 16) & 0xff; - _command[_index + 1] = (high_bits >> 8) & 0xff; - _command[_index] = high_bits & 0xff; - // Adjust index - _index = _index + 4; - } - - return _command; -}; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/commands/query_command.js b/node_modules/mongodb/lib/mongodb/commands/query_command.js deleted file mode 100644 index 196c9f1..0000000 --- a/node_modules/mongodb/lib/mongodb/commands/query_command.js +++ /dev/null @@ -1,296 +0,0 @@ -var BaseCommand = require('./base_command').BaseCommand, - inherits = require('util').inherits; - -/** - Insert Document Command -**/ -var QueryCommand = exports.QueryCommand = function(db, collectionName, queryOptions, numberToSkip, numberToReturn, query, returnFieldSelector, options) { - BaseCommand.call(this); - - // Validate correctness off the selector - var object = query, - object_size; - if(Buffer.isBuffer(object)) { - object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24; - if(object_size != object.length) { - var error = new Error("query selector raw message size does not match message header size [" + object.length + "] != [" + object_size + "]"); - error.name = 'MongoError'; - throw error; - } - } - - object = returnFieldSelector; - if(Buffer.isBuffer(object)) { - object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24; - if(object_size != object.length) { - var error = new Error("query fields raw message size does not match message header size [" + object.length + "] != [" + object_size + "]"); - error.name = 'MongoError'; - throw error; - } - } - - // Make sure we don't get a null exception - options = options == null ? {} : options; - // Set up options - this.collectionName = collectionName; - this.queryOptions = queryOptions; - this.numberToSkip = numberToSkip; - this.numberToReturn = numberToReturn; - - // Ensure we have no null query - query = query == null ? {} : query; - // Wrap query in the $query parameter so we can add read preferences for mongos - this.query = query; - this.returnFieldSelector = returnFieldSelector; - this.db = db; - - // Force the slave ok flag to be set if we are not using primary read preference - if(this.db && this.db.slaveOk) { - this.queryOptions |= QueryCommand.OPTS_SLAVE; - } - - // If checkKeys set - this.checkKeys = typeof options.checkKeys == 'boolean' ? options.checkKeys : false; - - // Let us defined on a command basis if we want functions to be serialized or not - if(options['serializeFunctions'] != null && options['serializeFunctions']) { - this.serializeFunctions = true; - } -}; - -inherits(QueryCommand, BaseCommand); - -QueryCommand.OP_QUERY = 2004; - -/* - * Adds the read prefrence to the current command - */ -QueryCommand.prototype.setMongosReadPreference = function(readPreference, tags) { - // No read preference specified - if(readPreference == false) return; - // If we have readPreference set to true set to secondary prefered - if(readPreference == true) { - readPreference = 'secondaryPreferred'; - } else if(readPreference == 'false') { - readPreference = 'primary'; - } - - // If we have primary read preference ignore it - if(readPreference == 'primary' - || readPreference.mode == 'primary') return; - - // Force the slave ok flag to be set if we are not using primary read preference - if(readPreference != false && readPreference != 'primary') { - this.queryOptions |= QueryCommand.OPTS_SLAVE; - } - - // Backward compatibility, ensure $query only set on read preference so 1.8.X works - if((readPreference != null || tags != null) && this.query['$query'] == null) { - this.query = {'$query': this.query}; - } - - // If we have no readPreference set and no tags, check if the slaveOk bit is set - if(readPreference == null && tags == null) { - // If we have a slaveOk bit set the read preference for MongoS - if(this.queryOptions & QueryCommand.OPTS_SLAVE) { - this.query['$readPreference'] = {mode: 'secondary'} - } else { - this.query['$readPreference'] = {mode: 'primary'} - } - } - - // Build read preference object - if(typeof readPreference == 'object' && readPreference['_type'] == 'ReadPreference') { - this.query['$readPreference'] = readPreference.toObject(); - } else if(readPreference != null) { - // Add the read preference - this.query['$readPreference'] = {mode: readPreference}; - - // If we have tags let's add them - if(tags != null) { - this.query['$readPreference']['tags'] = tags; - } - } -} - -/* -struct { - MsgHeader header; // standard message header - int32 opts; // query options. See below for details. - cstring fullCollectionName; // "dbname.collectionname" - int32 numberToSkip; // number of documents to skip when returning results - int32 numberToReturn; // number of documents to return in the first OP_REPLY - BSON query ; // query object. See below for details. - [ BSON returnFieldSelector; ] // OPTIONAL : selector indicating the fields to return. See below for details. -} -*/ -QueryCommand.prototype.toBinary = function(bsonSettings) { - // Validate that we are not passing 0x00 in the colletion name - if(!!~this.collectionName.indexOf("\x00")) { - throw new Error("namespace cannot contain a null character"); - } - - // Total length of the command - var totalLengthOfCommand = 0; - // Calculate total length of the document - if(Buffer.isBuffer(this.query)) { - totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + 4 + 4 + this.query.length + (4 * 4); - } else { - totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + 4 + 4 + this.db.bson.calculateObjectSize(this.query, this.serializeFunctions, true) + (4 * 4); - } - - // Calculate extra fields size - if(this.returnFieldSelector != null && !(Buffer.isBuffer(this.returnFieldSelector))) { - if(Object.keys(this.returnFieldSelector).length > 0) { - totalLengthOfCommand += this.db.bson.calculateObjectSize(this.returnFieldSelector, this.serializeFunctions, true); - } - } else if(Buffer.isBuffer(this.returnFieldSelector)) { - totalLengthOfCommand += this.returnFieldSelector.length; - } - - // Enforce maximum bson size - if(!bsonSettings.disableDriverBSONSizeCheck - && totalLengthOfCommand > bsonSettings.maxBsonSize) - throw new Error("Document exceeds maximum allowed bson size of " + bsonSettings.maxBsonSize + " bytes"); - - if(bsonSettings.disableDriverBSONSizeCheck - && totalLengthOfCommand > bsonSettings.maxMessageSizeBytes) - throw new Error("Command exceeds maximum message size of " + bsonSettings.maxMessageSizeBytes + " bytes"); - - // Let's build the single pass buffer command - var _index = 0; - var _command = new Buffer(totalLengthOfCommand); - // Write the header information to the buffer - _command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff; - _command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff; - _command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff; - _command[_index] = totalLengthOfCommand & 0xff; - // Adjust index - _index = _index + 4; - // Write the request ID - _command[_index + 3] = (this.requestId >> 24) & 0xff; - _command[_index + 2] = (this.requestId >> 16) & 0xff; - _command[_index + 1] = (this.requestId >> 8) & 0xff; - _command[_index] = this.requestId & 0xff; - // Adjust index - _index = _index + 4; - // Write zero - _command[_index++] = 0; - _command[_index++] = 0; - _command[_index++] = 0; - _command[_index++] = 0; - // Write the op_code for the command - _command[_index + 3] = (QueryCommand.OP_QUERY >> 24) & 0xff; - _command[_index + 2] = (QueryCommand.OP_QUERY >> 16) & 0xff; - _command[_index + 1] = (QueryCommand.OP_QUERY >> 8) & 0xff; - _command[_index] = QueryCommand.OP_QUERY & 0xff; - // Adjust index - _index = _index + 4; - - // Write the query options - _command[_index + 3] = (this.queryOptions >> 24) & 0xff; - _command[_index + 2] = (this.queryOptions >> 16) & 0xff; - _command[_index + 1] = (this.queryOptions >> 8) & 0xff; - _command[_index] = this.queryOptions & 0xff; - // Adjust index - _index = _index + 4; - - // Write the collection name to the command - _index = _index + _command.write(this.collectionName, _index, 'utf8') + 1; - _command[_index - 1] = 0; - - // Write the number of documents to skip - _command[_index + 3] = (this.numberToSkip >> 24) & 0xff; - _command[_index + 2] = (this.numberToSkip >> 16) & 0xff; - _command[_index + 1] = (this.numberToSkip >> 8) & 0xff; - _command[_index] = this.numberToSkip & 0xff; - // Adjust index - _index = _index + 4; - - // Write the number of documents to return - _command[_index + 3] = (this.numberToReturn >> 24) & 0xff; - _command[_index + 2] = (this.numberToReturn >> 16) & 0xff; - _command[_index + 1] = (this.numberToReturn >> 8) & 0xff; - _command[_index] = this.numberToReturn & 0xff; - // Adjust index - _index = _index + 4; - - // Document binary length - var documentLength = 0 - var object = this.query; - - // Serialize the selector - if(Buffer.isBuffer(object)) { - documentLength = object.length; - // Copy the data into the current buffer - object.copy(_command, _index); - } else { - // If $query we need to check for a valid document - if(this.query['$query']) { - this.db.bson.serializeWithBufferAndIndex(object['$query'], this.checkKeys, _command, _index, this.serializeFunctions) - _index + 1; - // Cannot check keys due to $query - this.checkKeys = false; - } - - // Serialize the document straight to the buffer - documentLength = this.db.bson.serializeWithBufferAndIndex(object, this.checkKeys, _command, _index, this.serializeFunctions) - _index + 1; - } - - // Write the length to the document - _command[_index + 3] = (documentLength >> 24) & 0xff; - _command[_index + 2] = (documentLength >> 16) & 0xff; - _command[_index + 1] = (documentLength >> 8) & 0xff; - _command[_index] = documentLength & 0xff; - // Update index in buffer - _index = _index + documentLength; - // // Add terminating 0 for the object - _command[_index - 1] = 0; - - // Push field selector if available - if(this.returnFieldSelector != null && !(Buffer.isBuffer(this.returnFieldSelector))) { - if(Object.keys(this.returnFieldSelector).length > 0) { - var documentLength = this.db.bson.serializeWithBufferAndIndex(this.returnFieldSelector, this.checkKeys, _command, _index, this.serializeFunctions) - _index + 1; - // Write the length to the document - _command[_index + 3] = (documentLength >> 24) & 0xff; - _command[_index + 2] = (documentLength >> 16) & 0xff; - _command[_index + 1] = (documentLength >> 8) & 0xff; - _command[_index] = documentLength & 0xff; - // Update index in buffer - _index = _index + documentLength; - // Add terminating 0 for the object - _command[_index - 1] = 0; - } - } if(this.returnFieldSelector != null && Buffer.isBuffer(this.returnFieldSelector)) { - // Document binary length - var documentLength = 0 - var object = this.returnFieldSelector; - - // Serialize the selector - documentLength = object.length; - // Copy the data into the current buffer - object.copy(_command, _index); - - // Write the length to the document - _command[_index + 3] = (documentLength >> 24) & 0xff; - _command[_index + 2] = (documentLength >> 16) & 0xff; - _command[_index + 1] = (documentLength >> 8) & 0xff; - _command[_index] = documentLength & 0xff; - // Update index in buffer - _index = _index + documentLength; - // Add terminating 0 for the object - _command[_index - 1] = 0; - } - - // Return finished command - return _command; -}; - -// Constants -QueryCommand.OPTS_NONE = 0; -QueryCommand.OPTS_TAILABLE_CURSOR = 2; -QueryCommand.OPTS_SLAVE = 4; -QueryCommand.OPTS_OPLOG_REPLAY = 8; -QueryCommand.OPTS_NO_CURSOR_TIMEOUT = 16; -QueryCommand.OPTS_AWAIT_DATA = 32; -QueryCommand.OPTS_EXHAUST = 64; -QueryCommand.OPTS_PARTIAL = 128; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/commands/update_command.js b/node_modules/mongodb/lib/mongodb/commands/update_command.js deleted file mode 100644 index daa3cba..0000000 --- a/node_modules/mongodb/lib/mongodb/commands/update_command.js +++ /dev/null @@ -1,189 +0,0 @@ -var BaseCommand = require('./base_command').BaseCommand, - inherits = require('util').inherits; - -/** - Update Document Command -**/ -var UpdateCommand = exports.UpdateCommand = function(db, collectionName, spec, document, options) { - BaseCommand.call(this); - - var object = spec; - if(Buffer.isBuffer(object)) { - var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24; - if(object_size != object.length) { - var error = new Error("update spec raw message size does not match message header size [" + object.length + "] != [" + object_size + "]"); - error.name = 'MongoError'; - throw error; - } - } - - var object = document; - if(Buffer.isBuffer(object)) { - var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24; - if(object_size != object.length) { - var error = new Error("update document raw message size does not match message header size [" + object.length + "] != [" + object_size + "]"); - error.name = 'MongoError'; - throw error; - } - } - - this.collectionName = collectionName; - this.spec = spec; - this.document = document; - this.db = db; - this.serializeFunctions = false; - this.checkKeys = typeof options.checkKeys != 'boolean' ? false : options.checkKeys; - - // Generate correct flags - var db_upsert = 0; - var db_multi_update = 0; - db_upsert = options != null && options['upsert'] != null ? (options['upsert'] == true ? 1 : 0) : db_upsert; - db_multi_update = options != null && options['multi'] != null ? (options['multi'] == true ? 1 : 0) : db_multi_update; - - // Flags - this.flags = parseInt(db_multi_update.toString() + db_upsert.toString(), 2); - // Let us defined on a command basis if we want functions to be serialized or not - if(options['serializeFunctions'] != null && options['serializeFunctions']) { - this.serializeFunctions = true; - } -}; - -inherits(UpdateCommand, BaseCommand); - -UpdateCommand.OP_UPDATE = 2001; - -/* -struct { - MsgHeader header; // standard message header - int32 ZERO; // 0 - reserved for future use - cstring fullCollectionName; // "dbname.collectionname" - int32 flags; // bit vector. see below - BSON spec; // the query to select the document - BSON document; // the document data to update with or insert -} -*/ -UpdateCommand.prototype.toBinary = function(bsonSettings) { - // Validate that we are not passing 0x00 in the colletion name - if(!!~this.collectionName.indexOf("\x00")) { - throw new Error("namespace cannot contain a null character"); - } - - // Calculate total length of the document - var totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + 4 + this.db.bson.calculateObjectSize(this.spec, false, true) + - this.db.bson.calculateObjectSize(this.document, this.serializeFunctions, true) + (4 * 4); - - // Enforce maximum bson size - if(!bsonSettings.disableDriverBSONSizeCheck - && totalLengthOfCommand > bsonSettings.maxBsonSize) - throw new Error("Document exceeds maximum allowed bson size of " + bsonSettings.maxBsonSize + " bytes"); - - if(bsonSettings.disableDriverBSONSizeCheck - && totalLengthOfCommand > bsonSettings.maxMessageSizeBytes) - throw new Error("Command exceeds maximum message size of " + bsonSettings.maxMessageSizeBytes + " bytes"); - - // Let's build the single pass buffer command - var _index = 0; - var _command = new Buffer(totalLengthOfCommand); - // Write the header information to the buffer - _command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff; - _command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff; - _command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff; - _command[_index] = totalLengthOfCommand & 0xff; - // Adjust index - _index = _index + 4; - // Write the request ID - _command[_index + 3] = (this.requestId >> 24) & 0xff; - _command[_index + 2] = (this.requestId >> 16) & 0xff; - _command[_index + 1] = (this.requestId >> 8) & 0xff; - _command[_index] = this.requestId & 0xff; - // Adjust index - _index = _index + 4; - // Write zero - _command[_index++] = 0; - _command[_index++] = 0; - _command[_index++] = 0; - _command[_index++] = 0; - // Write the op_code for the command - _command[_index + 3] = (UpdateCommand.OP_UPDATE >> 24) & 0xff; - _command[_index + 2] = (UpdateCommand.OP_UPDATE >> 16) & 0xff; - _command[_index + 1] = (UpdateCommand.OP_UPDATE >> 8) & 0xff; - _command[_index] = UpdateCommand.OP_UPDATE & 0xff; - // Adjust index - _index = _index + 4; - - // Write zero - _command[_index++] = 0; - _command[_index++] = 0; - _command[_index++] = 0; - _command[_index++] = 0; - - // Write the collection name to the command - _index = _index + _command.write(this.collectionName, _index, 'utf8') + 1; - _command[_index - 1] = 0; - - // Write the update flags - _command[_index + 3] = (this.flags >> 24) & 0xff; - _command[_index + 2] = (this.flags >> 16) & 0xff; - _command[_index + 1] = (this.flags >> 8) & 0xff; - _command[_index] = this.flags & 0xff; - // Adjust index - _index = _index + 4; - - // Document binary length - var documentLength = 0 - var object = this.spec; - - // Serialize the selector - // If we are passing a raw buffer, do minimal validation - if(Buffer.isBuffer(object)) { - var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24; - if(object_size != object.length) throw new Error("raw message size does not match message header size [" + object.length + "] != [" + object_size + "]"); - documentLength = object.length; - // Copy the data into the current buffer - object.copy(_command, _index); - } else { - documentLength = this.db.bson.serializeWithBufferAndIndex(object, this.checkKeys, _command, _index, false) - _index + 1; - } - - // Write the length to the document - _command[_index + 3] = (documentLength >> 24) & 0xff; - _command[_index + 2] = (documentLength >> 16) & 0xff; - _command[_index + 1] = (documentLength >> 8) & 0xff; - _command[_index] = documentLength & 0xff; - // Update index in buffer - _index = _index + documentLength; - // Add terminating 0 for the object - _command[_index - 1] = 0; - - // Document binary length - var documentLength = 0 - var object = this.document; - - // Serialize the document - // If we are passing a raw buffer, do minimal validation - if(Buffer.isBuffer(object)) { - var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24; - if(object_size != object.length) throw new Error("raw message size does not match message header size [" + object.length + "] != [" + object_size + "]"); - documentLength = object.length; - // Copy the data into the current buffer - object.copy(_command, _index); - } else { - documentLength = this.db.bson.serializeWithBufferAndIndex(object, false, _command, _index, this.serializeFunctions) - _index + 1; - } - - // Write the length to the document - _command[_index + 3] = (documentLength >> 24) & 0xff; - _command[_index + 2] = (documentLength >> 16) & 0xff; - _command[_index + 1] = (documentLength >> 8) & 0xff; - _command[_index] = documentLength & 0xff; - // Update index in buffer - _index = _index + documentLength; - // Add terminating 0 for the object - _command[_index - 1] = 0; - - return _command; -}; - -// Constants -UpdateCommand.DB_UPSERT = 0; -UpdateCommand.DB_MULTI_UPDATE = 1; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/connection/base.js b/node_modules/mongodb/lib/mongodb/connection/base.js deleted file mode 100644 index b8c1343..0000000 --- a/node_modules/mongodb/lib/mongodb/connection/base.js +++ /dev/null @@ -1,515 +0,0 @@ -var EventEmitter = require('events').EventEmitter - , inherits = require('util').inherits - , utils = require('../utils') - , mongodb_cr_authenticate = require('../auth/mongodb_cr.js').authenticate - , mongodb_gssapi_authenticate = require('../auth/mongodb_gssapi.js').authenticate - , mongodb_sspi_authenticate = require('../auth/mongodb_sspi.js').authenticate - , mongodb_plain_authenticate = require('../auth/mongodb_plain.js').authenticate - , mongodb_x509_authenticate = require('../auth/mongodb_x509.js').authenticate - , mongodb_scram_authenticate = require('../auth/mongodb_scram.js').authenticate; - -var id = 0; - -/** - * Internal class for callback storage - * @ignore - */ -var CallbackStore = function() { - // Make class an event emitter - EventEmitter.call(this); - // Add a info about call variable - this._notReplied = {}; - this.id = id++; -} - -/** - * @ignore - */ -inherits(CallbackStore, EventEmitter); - -CallbackStore.prototype.notRepliedToIds = function() { - return Object.keys(this._notReplied); -} - -CallbackStore.prototype.callbackInfo = function(id) { - return this._notReplied[id]; -} - -/** - * Internal class for holding non-executed commands - * @ignore - */ -var NonExecutedOperationStore = function(config) { - var commands = { - read: [] - , write_reads: [] - , write: [] - }; - - // Execute all callbacks - var fireCallbacksWithError = function(error, commands) { - while(commands.length > 0) { - var command = commands.shift(); - if(typeof command.callback == 'function') { - command.callback(error); - } - } - } - - this.count = function() { - return commands.read.length - + commands.write_reads.length - + commands.write.length; - } - - this.write = function(op) { - commands.write.push(op); - } - - this.read_from_writer = function(op) { - commands.write_reads.push(op); - } - - this.read = function(op) { - commands.read.push(op); - } - - this.validateBufferLimit = function(numberToFailOn) { - if(numberToFailOn == -1 || numberToFailOn == null) - return true; - - // Error passed back - var error = utils.toError("No connection operations buffering limit of " + numberToFailOn + " reached"); - - // If we have passed the number of items to buffer we need to fail - if(numberToFailOn < this.count()) { - // Fail all of the callbacks - fireCallbacksWithError(error, commands.read); - fireCallbacksWithError(error, commands.write_reads); - fireCallbacksWithError(error, commands.write); - - // Report back that the buffer has been filled - return false; - } - - // There is still some room to go - return true; - } - - this.execute_queries = function(executeInsertCommand) { - var connection = config.checkoutReader(); - if(connection == null || connection instanceof Error) return; - - // Write out all the queries - while(commands.read.length > 0) { - // Get the next command - var command = commands.read.shift(); - command.options.connection = connection; - // Execute the next command - command.executeQueryCommand(command.db, command.db_command, command.options, command.callback); - } - } - - this.execute_writes = function() { - var connection = config.checkoutWriter(); - if(connection == null || connection instanceof Error) return; - - // Write out all the queries to the primary - while(commands.write_reads.length > 0) { - // Get the next command - var command = commands.write_reads.shift(); - command.options.connection = connection; - // Execute the next command - command.executeQueryCommand(command.db, command.db_command, command.options, command.callback); - } - - // Execute all write operations - while(commands.write.length > 0) { - // Get the next command - var command = commands.write.shift(); - // Set the connection - command.options.connection = connection; - // Execute the next command - command.executeInsertCommand(command.db, command.db_command, command.options, command.callback); - } - } -} - -/** - * Internal class for authentication storage - * @ignore - */ -var AuthStore = function() { - var _auths = []; - - this.add = function(authMechanism, dbName, username, password, authdbName, gssapiServiceName) { - // Check for duplicates - if(!this.contains(dbName)) { - // Base config - var config = { - 'username':username - , 'password':password - , 'db': dbName - , 'authMechanism': authMechanism - , 'gssapiServiceName': gssapiServiceName - }; - - // Add auth source if passed in - if(typeof authdbName == 'string') { - config['authdb'] = authdbName; - } - - // Push the config - _auths.push(config); - } - } - - this.contains = function(dbName) { - for(var i = 0; i < _auths.length; i++) { - if(_auths[i].db == dbName) return true; - } - - return false; - } - - this.remove = function(dbName) { - var newAuths = []; - - // Filter out all the login details - for(var i = 0; i < _auths.length; i++) { - if(_auths[i].db != dbName) newAuths.push(_auths[i]); - } - - // Set the filtered list - _auths = newAuths; - } - - this.get = function(index) { - return _auths[index]; - } - - this.length = function() { - return _auths.length; - } - - this.toArray = function() { - return _auths.slice(0); - } -} - -/** - * Internal class for storing db references - * @ignore - */ -var DbStore = function() { - var _dbs = []; - - this.add = function(db) { - var found = false; - - // Only add if it does not exist already - for(var i = 0; i < _dbs.length; i++) { - if(db.databaseName == _dbs[i].databaseName) found = true; - } - - // Only add if it does not already exist - if(!found) { - _dbs.push(db); - } - } - - this.reset = function() { - _dbs = []; - } - - this.db = function() { - return _dbs; - } - - this.fetch = function(databaseName) { - // Only add if it does not exist already - for(var i = 0; i < _dbs.length; i++) { - if(databaseName == _dbs[i].databaseName) - return _dbs[i]; - } - - return null; - } - - this.emit = function(event, message, object, reset, filterDb, rethrow_if_no_listeners) { - var emitted = false; - - // Not emitted and we have enabled rethrow, let process.uncaughtException - // deal with the issue - if(!emitted && rethrow_if_no_listeners) { - return process.nextTick(function() { - throw message; - }) - } - - // Emit the events - for(var i = 0; i < _dbs.length; i++) { - if(_dbs[i].listeners(event).length > 0) { - if(filterDb == null || filterDb.databaseName !== _dbs[i].databaseName - || filterDb.tag !== _dbs[i].tag) { - _dbs[i].emit(event, message, object == null ? _dbs[i] : object); - emitted = true; - } - } - } - - // Emit error message - if(message - && event == 'error' - && !emitted - && rethrow_if_no_listeners - && object && object.db) { - process.nextTick(function() { - object.db.emit(event, message, null); - }) - } - } -} - -var Base = function Base() { - EventEmitter.call(this); - - // Callback store is part of connection specification - if(Base._callBackStore == null) { - Base._callBackStore = new CallbackStore(); - } - - // Create a new auth store - var auth = new AuthStore(); - - Object.defineProperty(this, "auth", {enumerable: true - , get: function() { return auth; } - }); - - // Create a new callback store - this._callBackStore = new CallbackStore(); - // All commands not being executed - this._commandsStore = new NonExecutedOperationStore(this); - // Contains all the dbs attached to this server config - this._dbStore = new DbStore(); -} - -/** - * @ignore - */ -inherits(Base, EventEmitter); - -/** - * @ignore - */ -Base.prototype._apply_auths = function(db, callback) { - _apply_auths_serially(this, db, this.auth.toArray(), callback); -} - -var _apply_auths_serially = function(self, db, auths, callback) { - if(auths.length == 0) return callback(null, null); - // Get the first auth - var auth = auths.shift(); - var connections = self.allRawConnections(); - var connectionsLeft = connections.length; - var options = {}; - - if(auth.authMechanism == 'GSSAPI') { - // We have the kerberos library, execute auth process - if(process.platform == 'win32') { - mongodb_sspi_authenticate(db, auth.username, auth.password, auth.authdb, options, callback); - } else { - mongodb_gssapi_authenticate(db, auth.username, auth.password, auth.authdb, options, callback); - } - } else if(auth.authMechanism == 'MONGODB-CR') { - mongodb_cr_authenticate(db, auth.username, auth.password, auth.authdb, options, callback); - } else if(auth.authMechanism == 'SCRAM-SHA-1') { - mongodb_scram_authenticate(db, auth.username, auth.password, auth.authdb, options, callback); - } else if(auth.authMechanism == 'PLAIN') { - mongodb_plain_authenticate(db, auth.username, auth.password, options, callback); - } else if(auth.authMechanism == 'MONGODB-X509') { - mongodb_x509_authenticate(db, auth.username, auth.password, options, callback); - } -} - -/** - * Fire all the errors - * @ignore - */ -Base.prototype.__executeAllCallbacksWithError = function(err) { - // Check all callbacks - var keys = Object.keys(this._callBackStore._notReplied); - // For each key check if it's a callback that needs to be returned - for(var j = 0; j < keys.length; j++) { - var info = this._callBackStore._notReplied[keys[j]]; - // Execute callback with error - this._callBackStore.emit(keys[j], err, null); - // Remove the key - delete this._callBackStore._notReplied[keys[j]]; - // Force cleanup _events, node.js seems to set it as a null value - if(this._callBackStore._events) { - delete this._callBackStore._events[keys[j]]; - } - } -} - -/** - * Fire all the errors - * @ignore - */ -Base.prototype.__executeAllServerSpecificErrorCallbacks = function(host, port, err) { - // Check all callbacks - var keys = Object.keys(this._callBackStore._notReplied); - // For each key check if it's a callback that needs to be returned - for(var j = 0; j < keys.length; j++) { - var info = this._callBackStore._notReplied[keys[j]]; - - if(info && info.connection) { - // Unpack the connection settings - var _host = info.connection.socketOptions.host; - var _port = info.connection.socketOptions.port; - // If the server matches execute the callback with the error - if(_port == port && _host == host) { - this._callBackStore.emit(keys[j], err, null); - // Remove the key - delete this._callBackStore._notReplied[keys[j]]; - // Force cleanup _events, node.js seems to set it as a null value - if(this._callBackStore._events) { - delete this._callBackStore._events[keys[j]]; - } - } - } - } -} - -/** - * Register a handler - * @ignore - * @api private - */ -Base.prototype._registerHandler = function(db_command, raw, connection, exhaust, callback) { - // Check if we have exhausted - if(typeof exhaust == 'function') { - callback = exhaust; - exhaust = false; - } - - // Add the callback to the list of handlers - this._callBackStore.once(db_command.getRequestId(), callback); - // Add the information about the reply - this._callBackStore._notReplied[db_command.getRequestId().toString()] = {start: new Date().getTime(), 'raw': raw, connection:connection, exhaust:exhaust}; -} - -/** - * Re-Register a handler, on the cursor id f.ex - * @ignore - * @api private - */ -Base.prototype._reRegisterHandler = function(newId, object, callback) { - // Add the callback to the list of handlers - this._callBackStore.once(newId, object.callback.listener); - // Add the information about the reply - this._callBackStore._notReplied[newId] = object.info; -} - -/** - * - * @ignore - * @api private - */ -Base.prototype._flushAllCallHandlers = function(err) { - var keys = Object.keys(this._callBackStore._notReplied); - - for(var i = 0; i < keys.length; i++) { - this._callHandler(keys[i], null, err); - } -} - -/** - * - * @ignore - * @api private - */ -Base.prototype._callHandler = function(id, document, err) { - var self = this; - - // If there is a callback peform it - if(this._callBackStore.listeners(id).length >= 1) { - // Get info object - var info = this._callBackStore._notReplied[id]; - // Delete the current object - delete this._callBackStore._notReplied[id]; - // Call the handle directly don't emit - var callback = this._callBackStore.listeners(id)[0].listener; - // Remove the listeners - this._callBackStore.removeAllListeners(id); - // Force key deletion because it nulling it not deleting in 0.10.X - if(this._callBackStore._events) { - delete this._callBackStore._events[id]; - } - - try { - // Execute the callback if one was provided - if(typeof callback == 'function') callback(err, document, info.connection); - } catch(err) { - self._emitAcrossAllDbInstances(self, null, "error", utils.toError(err), self, true, true); - } - } -} - -/** - * - * @ignore - * @api private - */ -Base.prototype._hasHandler = function(id) { - return this._callBackStore.listeners(id).length >= 1; -} - -/** - * - * @ignore - * @api private - */ -Base.prototype._removeHandler = function(id) { - // Remove the information - if(this._callBackStore._notReplied[id] != null) delete this._callBackStore._notReplied[id]; - // Remove the callback if it's registered - this._callBackStore.removeAllListeners(id); - // Force cleanup _events, node.js seems to set it as a null value - if(this._callBackStore._events) { - delete this._callBackStore._events[id]; - } -} - -/** - * - * @ignore - * @api private - */ -Base.prototype._findHandler = function(id) { - var info = this._callBackStore._notReplied[id]; - // Return the callback - return {info:info, callback:(this._callBackStore.listeners(id).length >= 1) ? this._callBackStore.listeners(id)[0] : null} -} - -/** - * - * @ignore - * @api private - */ -Base.prototype._emitAcrossAllDbInstances = function(server, filterDb, event, message, object, resetConnection, rethrow_if_no_listeners) { - if(resetConnection) { - var dbs = this._dbStore.db(); - - for(var i = 0; i < dbs.length; i++) { - if(typeof dbs[i].openCalled != 'undefined') - dbs[i].openCalled = false; - } - } - - // Fire event - this._dbStore.emit(event, message, object, resetConnection, filterDb, rethrow_if_no_listeners); -} - -exports.Base = Base; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/connection/connection.js b/node_modules/mongodb/lib/mongodb/connection/connection.js deleted file mode 100644 index d1e4835..0000000 --- a/node_modules/mongodb/lib/mongodb/connection/connection.js +++ /dev/null @@ -1,563 +0,0 @@ -var utils = require('./connection_utils'), - inherits = require('util').inherits, - net = require('net'), - EventEmitter = require('events').EventEmitter, - inherits = require('util').inherits, - binaryutils = require('../utils'), - tls = require('tls'); - -var Connection = exports.Connection = function(id, socketOptions) { - var self = this; - // Set up event emitter - EventEmitter.call(this); - // Store all socket options - this.socketOptions = socketOptions ? socketOptions : {host:'localhost', port:27017, domainSocket:false}; - // Set keep alive default if not overriden - if(this.socketOptions.keepAlive == null && (process.platform !== "sunos" || process.platform !== "win32")) this.socketOptions.keepAlive = 100; - // Id for the connection - this.id = id; - // State of the connection - this.connected = false; - // Set if this is a domain socket - this.domainSocket = this.socketOptions.domainSocket; - - // Supported min and max wire protocol - this.minWireVersion = 0; - this.maxWireVersion = 3; - - // - // Connection parsing state - // - this.maxBsonSize = socketOptions.maxBsonSize ? socketOptions.maxBsonSize : Connection.DEFAULT_MAX_BSON_SIZE; - this.maxMessageSizeBytes = socketOptions.maxMessageSizeBytes ? socketOptions.maxMessageSizeBytes : Connection.DEFAULT_MAX_MESSAGE_SIZE; - this.maxNumberOfDocsInBatch = socketOptions.maxWriteBatchSize ? socketOptions.maxWriteBatchSize : Connection.DEFAULT_MAX_WRITE_BATCH_SIZE; - // Contains the current message bytes - this.buffer = null; - // Contains the current message size - this.sizeOfMessage = 0; - // Contains the readIndex for the messaage - this.bytesRead = 0; - // Contains spill over bytes from additional messages - this.stubBuffer = 0; - - // Just keeps list of events we allow - this.eventHandlers = {error:[], parseError:[], poolReady:[], message:[], close:[], timeout:[], end:[]}; - - // Just keeps list of events we allow - resetHandlers(this, false); - - // Bson object - this.maxBsonSettings = { - disableDriverBSONSizeCheck: this.socketOptions['disableDriverBSONSizeCheck'] || false - , maxBsonSize: this.maxBsonSize - , maxMessageSizeBytes: this.maxMessageSizeBytes - } - - // Allow setting the socketTimeoutMS on all connections - // to work around issues such as secondaries blocking due to compaction - Object.defineProperty(this, "socketTimeoutMS", { - enumerable: true - , get: function () { return self.socketOptions.socketTimeoutMS; } - , set: function (value) { - // Set the socket timeoutMS value - self.socketOptions.socketTimeoutMS = value; - // Set the physical connection timeout - self.connection.setTimeout(self.socketOptions.socketTimeoutMS); - } - }); -} - -// Set max bson size -Connection.DEFAULT_MAX_BSON_SIZE = 1024 * 1024 * 4; -// Set default to max bson to avoid overflow or bad guesses -Connection.DEFAULT_MAX_MESSAGE_SIZE = Connection.DEFAULT_MAX_BSON_SIZE; -// Max default write bulk ops -Connection.DEFAULT_MAX_WRITE_BATCH_SIZE = 2000; - -// Inherit event emitter so we can emit stuff wohoo -inherits(Connection, EventEmitter); - -Connection.prototype.start = function() { - var self = this; - - // If we have a normal connection - if(this.socketOptions.ssl) { - // Create new connection instance - if(this.domainSocket) { - this.connection = net.createConnection(this.socketOptions.host); - } else { - this.connection = net.createConnection(this.socketOptions.port, this.socketOptions.host); - } - if(this.logger != null && this.logger.doDebug){ - this.logger.debug("opened connection", this.socketOptions); - } - - // Set options on the socket - this.connection.setTimeout(this.socketOptions.connectTimeoutMS != null ? this.socketOptions.connectTimeoutMS : this.socketOptions.timeout); - // Work around for 0.4.X - if(process.version.indexOf("v0.4") == -1) this.connection.setNoDelay(this.socketOptions.noDelay); - // Set keep alive if defined - if(process.version.indexOf("v0.4") == -1) { - if(this.socketOptions.keepAlive > 0) { - this.connection.setKeepAlive(true, this.socketOptions.keepAlive); - } else { - this.connection.setKeepAlive(false); - } - } - - // Check if the driver should validate the certificate - var validate_certificates = this.socketOptions.sslValidate == true ? true : false; - - // Create options for the tls connection - var tls_options = { - socket: this.connection - , rejectUnauthorized: false - } - - // If we wish to validate the certificate we have provided a ca store - if(validate_certificates) { - tls_options.ca = this.socketOptions.sslCA; - } - - // If we have a certificate to present - if(this.socketOptions.sslCert) { - tls_options.cert = this.socketOptions.sslCert; - tls_options.key = this.socketOptions.sslKey; - } - - // If the driver has been provided a private key password - if(this.socketOptions.sslPass) { - tls_options.passphrase = this.socketOptions.sslPass; - } - - // Contains the cleartext stream - var cleartext = null; - // Attempt to establish a TLS connection to the server - try { - cleartext = tls.connect(this.socketOptions.port, this.socketOptions.host, tls_options, function() { - // If we have a ssl certificate validation error return an error - if(cleartext.authorizationError && validate_certificates) { - // Emit an error - return self.emit("error", cleartext.authorizationError, self, {ssl:true}); - } - - // Connect to the server - connectHandler(self)(); - }) - } catch(err) { - return self.emit("error", "SSL connection failed", self, {ssl:true}); - } - - // Save the output stream - this.writeSteam = cleartext; - - // Set up data handler for the clear stream - cleartext.on("data", createDataHandler(this)); - // Do any handling of end event of the stream - cleartext.on("end", endHandler(this)); - cleartext.on("error", errorHandler(this)); - - // Handle any errors - this.connection.on("error", errorHandler(this)); - // Handle timeout - this.connection.on("timeout", timeoutHandler(this)); - // Handle drain event - this.connection.on("drain", drainHandler(this)); - // Handle the close event - this.connection.on("close", closeHandler(this)); - } else { - // Create new connection instance - if(this.domainSocket) { - this.connection = net.createConnection(this.socketOptions.host); - } else { - this.connection = net.createConnection(this.socketOptions.port, this.socketOptions.host); - } - if(this.logger != null && this.logger.doDebug){ - this.logger.debug("opened connection", this.socketOptions); - } - - // Set options on the socket - this.connection.setTimeout(this.socketOptions.connectTimeoutMS != null ? this.socketOptions.connectTimeoutMS : this.socketOptions.timeout); - // Work around for 0.4.X - if(process.version.indexOf("v0.4") == -1) this.connection.setNoDelay(this.socketOptions.noDelay); - // Set keep alive if defined - if(process.version.indexOf("v0.4") == -1) { - if(this.socketOptions.keepAlive > 0) { - this.connection.setKeepAlive(true, this.socketOptions.keepAlive); - } else { - this.connection.setKeepAlive(false); - } - } - - // Set up write stream - this.writeSteam = this.connection; - // Add handlers - this.connection.on("error", errorHandler(this)); - // Add all handlers to the socket to manage it - this.connection.on("connect", connectHandler(this)); - // this.connection.on("end", endHandler(this)); - this.connection.on("data", createDataHandler(this)); - this.connection.on("timeout", timeoutHandler(this)); - this.connection.on("drain", drainHandler(this)); - this.connection.on("close", closeHandler(this)); - } -} - -/** - * @ignore - */ -Connection.prototype.setSocketOptions = function(options) { - options = options || {}; - - if(typeof options.connectTimeoutMS == 'number') { - this.socketOptions.connectTimeoutMS = options.connectTimeoutMS; - } - - if(typeof options.socketTimeoutMS == 'number') { - this.socketOptions.socketTimeoutMS = options.socketTimeoutMS; - // Set the current socket timeout - this.connection.setTimeout(options.socketTimeoutMS); - } -} - -// Check if the sockets are live -Connection.prototype.isConnected = function() { - return this.connected && !this.connection.destroyed && this.connection.writable; -} - -// Validate if the driver supports this server -Connection.prototype.isCompatible = function() { - if(this.serverCapabilities == null) return true; - - // Is compatible with backward server - if(this.serverCapabilities.minWireVersion == 0 - && this.serverCapabilities.maxWireVersion ==0) return true; - - // Check if we overlap - if(this.serverCapabilities.minWireVersion >= this.minWireVersion - && this.serverCapabilities.maxWireVersion <= this.maxWireVersion) return true; - - // Not compatible - return false; -} - -// Write the data out to the socket -Connection.prototype.write = function(command, callback) { - try { - // If we have a list off commands to be executed on the same socket - if(Array.isArray(command)) { - for(var i = 0; i < command.length; i++) { - try { - // Pass in the bson validation settings (validate early) - var binaryCommand = command[i].toBinary(this.maxBsonSettings); - - if(this.logger != null && this.logger.doDebug) - this.logger.debug("writing command to mongodb", {binary: binaryCommand, json: command[i]}); - - this.writeSteam.write(binaryCommand); - } catch(err) { - return callback(err, null); - } - } - } else { - try { - // Pass in the bson validation settings (validate early) - var binaryCommand = command.toBinary(this.maxBsonSettings); - // Do we have a logger active log the event - if(this.logger != null && this.logger.doDebug) - this.logger.debug("writing command to mongodb", {binary: binaryCommand, json: command}); - // Write the binary command out to socket - this.writeSteam.write(binaryCommand); - } catch(err) { - return callback(err, null); - } - } - } catch (err) { - if(typeof callback === 'function') callback(err); - } -} - -// Force the closure of the connection -Connection.prototype.close = function() { - // clear out all the listeners - resetHandlers(this, true); - // Add a dummy error listener to catch any weird last moment errors (and ignore them) - this.connection.on("error", function() {}) - // destroy connection - this.connection.destroy(); - if(this.logger != null && this.logger.doDebug){ - this.logger.debug("closed connection", this.connection); - } -} - -// Reset all handlers -var resetHandlers = function(self, clearListeners) { - self.eventHandlers = {error:[], connect:[], close:[], end:[], timeout:[], parseError:[], message:[]}; - - // If we want to clear all the listeners - if(clearListeners && self.connection != null) { - var keys = Object.keys(self.eventHandlers); - // Remove all listeners - for(var i = 0; i < keys.length; i++) { - self.connection.removeAllListeners(keys[i]); - } - } -} - -// -// Handlers -// - -// Connect handler -var connectHandler = function(self) { - return function(data) { - // Set connected - self.connected = true; - // Now that we are connected set the socket timeout - self.connection.setTimeout(self.socketOptions.socketTimeoutMS != null ? self.socketOptions.socketTimeoutMS : self.socketOptions.timeout); - // Emit the connect event with no error - self.emit("connect", null, self); - } -} - -var createDataHandler = exports.Connection.createDataHandler = function(self) { - // We need to handle the parsing of the data - // and emit the messages when there is a complete one - return function(data) { - // Parse until we are done with the data - while(data.length > 0) { - // If we still have bytes to read on the current message - if(self.bytesRead > 0 && self.sizeOfMessage > 0) { - // Calculate the amount of remaining bytes - var remainingBytesToRead = self.sizeOfMessage - self.bytesRead; - // Check if the current chunk contains the rest of the message - if(remainingBytesToRead > data.length) { - // Copy the new data into the exiting buffer (should have been allocated when we know the message size) - data.copy(self.buffer, self.bytesRead); - // Adjust the number of bytes read so it point to the correct index in the buffer - self.bytesRead = self.bytesRead + data.length; - - // Reset state of buffer - data = new Buffer(0); - } else { - // Copy the missing part of the data into our current buffer - data.copy(self.buffer, self.bytesRead, 0, remainingBytesToRead); - // Slice the overflow into a new buffer that we will then re-parse - data = data.slice(remainingBytesToRead); - - // Emit current complete message - try { - var emitBuffer = self.buffer; - // Reset state of buffer - self.buffer = null; - self.sizeOfMessage = 0; - self.bytesRead = 0; - self.stubBuffer = null; - // Emit the buffer - self.emit("message", emitBuffer, self); - } catch(err) { - var errorObject = {err:"socketHandler", trace:err, bin:self.buffer, parseState:{ - sizeOfMessage:self.sizeOfMessage, - bytesRead:self.bytesRead, - stubBuffer:self.stubBuffer}}; - if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject); - // We got a parse Error fire it off then keep going - self.emit("parseError", errorObject, self); - } - } - } else { - // Stub buffer is kept in case we don't get enough bytes to determine the - // size of the message (< 4 bytes) - if(self.stubBuffer != null && self.stubBuffer.length > 0) { - - // If we have enough bytes to determine the message size let's do it - if(self.stubBuffer.length + data.length > 4) { - // Prepad the data - var newData = new Buffer(self.stubBuffer.length + data.length); - self.stubBuffer.copy(newData, 0); - data.copy(newData, self.stubBuffer.length); - // Reassign for parsing - data = newData; - - // Reset state of buffer - self.buffer = null; - self.sizeOfMessage = 0; - self.bytesRead = 0; - self.stubBuffer = null; - - } else { - - // Add the the bytes to the stub buffer - var newStubBuffer = new Buffer(self.stubBuffer.length + data.length); - // Copy existing stub buffer - self.stubBuffer.copy(newStubBuffer, 0); - // Copy missing part of the data - data.copy(newStubBuffer, self.stubBuffer.length); - // Exit parsing loop - data = new Buffer(0); - } - } else { - if(data.length > 4) { - // Retrieve the message size - var sizeOfMessage = binaryutils.decodeUInt32(data, 0); - // If we have a negative sizeOfMessage emit error and return - if(sizeOfMessage < 0 || sizeOfMessage > self.maxMessageSizeBytes) { - var errorObject = {err:"socketHandler", trace:'', bin:self.buffer, parseState:{ - sizeOfMessage: sizeOfMessage, - bytesRead: self.bytesRead, - stubBuffer: self.stubBuffer}}; - if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject); - // We got a parse Error fire it off then keep going - self.emit("parseError", errorObject, self); - return; - } - - // Ensure that the size of message is larger than 0 and less than the max allowed - if(sizeOfMessage > 4 && sizeOfMessage < self.maxMessageSizeBytes && sizeOfMessage > data.length) { - self.buffer = new Buffer(sizeOfMessage); - // Copy all the data into the buffer - data.copy(self.buffer, 0); - // Update bytes read - self.bytesRead = data.length; - // Update sizeOfMessage - self.sizeOfMessage = sizeOfMessage; - // Ensure stub buffer is null - self.stubBuffer = null; - // Exit parsing loop - data = new Buffer(0); - - } else if(sizeOfMessage > 4 && sizeOfMessage < self.maxMessageSizeBytes && sizeOfMessage == data.length) { - try { - var emitBuffer = data; - // Reset state of buffer - self.buffer = null; - self.sizeOfMessage = 0; - self.bytesRead = 0; - self.stubBuffer = null; - // Exit parsing loop - data = new Buffer(0); - // Emit the message - self.emit("message", emitBuffer, self); - } catch (err) { - var errorObject = {err:"socketHandler", trace:err, bin:self.buffer, parseState:{ - sizeOfMessage:self.sizeOfMessage, - bytesRead:self.bytesRead, - stubBuffer:self.stubBuffer}}; - if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject); - // We got a parse Error fire it off then keep going - self.emit("parseError", errorObject, self); - } - } else if(sizeOfMessage <= 4 || sizeOfMessage > self.maxMessageSizeBytes) { - var errorObject = {err:"socketHandler", trace:null, bin:data, parseState:{ - sizeOfMessage:sizeOfMessage, - bytesRead:0, - buffer:null, - stubBuffer:null}}; - if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject); - // We got a parse Error fire it off then keep going - self.emit("parseError", errorObject, self); - - // Clear out the state of the parser - self.buffer = null; - self.sizeOfMessage = 0; - self.bytesRead = 0; - self.stubBuffer = null; - // Exit parsing loop - data = new Buffer(0); - - } else { - try { - var emitBuffer = data.slice(0, sizeOfMessage); - // Reset state of buffer - self.buffer = null; - self.sizeOfMessage = 0; - self.bytesRead = 0; - self.stubBuffer = null; - // Copy rest of message - data = data.slice(sizeOfMessage); - // Emit the message - self.emit("message", emitBuffer, self); - } catch (err) { - var errorObject = {err:"socketHandler", trace:err, bin:self.buffer, parseState:{ - sizeOfMessage:sizeOfMessage, - bytesRead:self.bytesRead, - stubBuffer:self.stubBuffer}}; - if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject); - // We got a parse Error fire it off then keep going - self.emit("parseError", errorObject, self); - } - - } - } else { - // Create a buffer that contains the space for the non-complete message - self.stubBuffer = new Buffer(data.length) - // Copy the data to the stub buffer - data.copy(self.stubBuffer, 0); - // Exit parsing loop - data = new Buffer(0); - } - } - } - } - } -} - -var endHandler = function(self) { - return function() { - // Set connected to false - self.connected = false; - // Emit end event - self.emit("end", {err: 'connection received Fin packet from [' + self.socketOptions.host + ':' + self.socketOptions.port + ']'}, self); - } -} - -var timeoutHandler = function(self) { - return function() { - // Set connected to false - self.connected = false; - // Emit timeout event - self.emit("timeout", {err: 'connection to [' + self.socketOptions.host + ':' + self.socketOptions.port + '] timed out'}, self); - } -} - -var drainHandler = function(self) { - return function() { - } -} - -var errorHandler = function(self) { - return function(err) { - self.connection.destroy(); - // Set connected to false - self.connected = false; - // Emit error - self.emit("error", {err: 'failed to connect to [' + self.socketOptions.host + ':' + self.socketOptions.port + ']'}, self); - } -} - -var closeHandler = function(self) { - return function(hadError) { - // If we have an error during the connection phase - if(hadError && !self.connected) { - // Set disconnected - self.connected = false; - // Emit error - self.emit("error", {err: 'failed to connect to [' + self.socketOptions.host + ':' + self.socketOptions.port + ']'}, self); - } else { - // Set disconnected - self.connected = false; - // Emit close - self.emit("close", {err: 'connection closed to [' + self.socketOptions.host + ':' + self.socketOptions.port + ']'}, self); - } - } -} - -// Some basic defaults -Connection.DEFAULT_PORT = 27017; - - - - - - - diff --git a/node_modules/mongodb/lib/mongodb/connection/connection_pool.js b/node_modules/mongodb/lib/mongodb/connection/connection_pool.js deleted file mode 100644 index e669354..0000000 --- a/node_modules/mongodb/lib/mongodb/connection/connection_pool.js +++ /dev/null @@ -1,305 +0,0 @@ -var utils = require('./connection_utils'), - inherits = require('util').inherits, - net = require('net'), - timers = require('timers'), - EventEmitter = require('events').EventEmitter, - inherits = require('util').inherits, - MongoReply = require("../responses/mongo_reply").MongoReply, - Connection = require("./connection").Connection; - -// Set processor, setImmediate if 0.10 otherwise nextTick -var processor = require('../utils').processor(); - -var ConnectionPool = exports.ConnectionPool = function(host, port, poolSize, bson, socketOptions) { - if(typeof host !== 'string') { - throw new Error("host must be specified [" + host + "]"); - } - - // Set up event emitter - EventEmitter.call(this); - - // Keep all options for the socket in a specific collection allowing the user to specify the - // Wished upon socket connection parameters - this.socketOptions = typeof socketOptions === 'object' ? socketOptions : {}; - this.socketOptions.host = host; - this.socketOptions.port = port; - this.socketOptions.domainSocket = false; - this.bson = bson; - // PoolSize is always + 1 for special reserved "measurment" socket (like ping, stats etc) - this.poolSize = poolSize; - this.minPoolSize = Math.floor(this.poolSize / 2) + 1; - - // Check if the host is a socket - if(host.match(/^\//)) { - this.socketOptions.domainSocket = true; - } else if(typeof port === 'string') { - try { - port = parseInt(port, 10); - } catch(err) { - new Error("port must be specified or valid integer[" + port + "]"); - } - } else if(typeof port !== 'number') { - throw new Error("port must be specified [" + port + "]"); - } - - // Set default settings for the socket options - utils.setIntegerParameter(this.socketOptions, 'timeout', 0); - // Delay before writing out the data to the server - utils.setBooleanParameter(this.socketOptions, 'noDelay', true); - // Delay before writing out the data to the server - utils.setIntegerParameter(this.socketOptions, 'keepAlive', 0); - // Set the encoding of the data read, default is binary == null - utils.setStringParameter(this.socketOptions, 'encoding', null); - // Allows you to set a throttling bufferSize if you need to stop overflows - utils.setIntegerParameter(this.socketOptions, 'bufferSize', 0); - - // Internal structures - this.openConnections = []; - // Assign connection id's - this.connectionId = 0; - - // Current index for selection of pool connection - this.currentConnectionIndex = 0; - // The pool state - this._poolState = 'disconnected'; - // timeout control - this._timeout = false; - // Time to wait between connections for the pool - this._timeToWait = 10; -} - -inherits(ConnectionPool, EventEmitter); - -ConnectionPool.prototype.setMaxBsonSize = function(maxBsonSize) { - if(maxBsonSize == null){ - maxBsonSize = Connection.DEFAULT_MAX_BSON_SIZE; - } - - for(var i = 0; i < this.openConnections.length; i++) { - this.openConnections[i].maxBsonSize = maxBsonSize; - this.openConnections[i].maxBsonSettings.maxBsonSize = maxBsonSize; - } -} - -ConnectionPool.prototype.setMaxMessageSizeBytes = function(maxMessageSizeBytes) { - if(maxMessageSizeBytes == null){ - maxMessageSizeBytes = Connection.DEFAULT_MAX_MESSAGE_SIZE; - } - - for(var i = 0; i < this.openConnections.length; i++) { - this.openConnections[i].maxMessageSizeBytes = maxMessageSizeBytes; - this.openConnections[i].maxBsonSettings.maxMessageSizeBytes = maxMessageSizeBytes; - } -} - -ConnectionPool.prototype.setMaxWriteBatchSize = function(maxWriteBatchSize) { - if(maxWriteBatchSize == null){ - maxWriteBatchSize = Connection.DEFAULT_MAX_WRITE_BATCH_SIZE; - } - - for(var i = 0; i < this.openConnections.length; i++) { - this.openConnections[i].maxWriteBatchSize = maxWriteBatchSize; - } -} - -// Start a function -var _connect = function(_self) { - // return new function() { - // Create a new connection instance - var connection = new Connection(_self.connectionId++, _self.socketOptions); - // Set logger on pool - connection.logger = _self.logger; - // Connect handler - connection.on("connect", function(err, connection) { - // Add connection to list of open connections - _self.openConnections.push(connection); - // If the number of open connections is equal to the poolSize signal ready pool - if(_self.openConnections.length === _self.poolSize && _self._poolState !== 'disconnected') { - // Set connected - _self._poolState = 'connected'; - // Emit pool ready - _self.emit("poolReady"); - } else if(_self.openConnections.length < _self.poolSize) { - // Wait a little bit of time to let the close event happen if the server closes the connection - // so we don't leave hanging connections around - if(typeof _self._timeToWait == 'number') { - setTimeout(function() { - // If we are still connecting (no close events fired in between start another connection) - if(_self._poolState == 'connecting') { - _connect(_self); - } - }, _self._timeToWait); - } else { - processor(function() { - // If we are still connecting (no close events fired in between start another connection) - if(_self._poolState == 'connecting') { - _connect(_self); - } - }); - } - } - }); - - var numberOfErrors = 0 - - // Error handler - connection.on("error", function(err, connection, error_options) { - numberOfErrors++; - // If we are already disconnected ignore the event - if(_self._poolState != 'disconnected' && _self.listeners("error").length > 0) { - _self.emit("error", err, connection, error_options); - } - - // Close the connection - connection.close(); - // Set pool as disconnected - _self._poolState = 'disconnected'; - // Stop the pool - _self.stop(); - }); - - // Close handler - connection.on("close", function() { - // If we are already disconnected ignore the event - if(_self._poolState !== 'disconnected' && _self.listeners("close").length > 0) { - _self.emit("close"); - } - - // Set disconnected - _self._poolState = 'disconnected'; - // Stop - _self.stop(); - }); - - // Timeout handler - connection.on("timeout", function(err, connection) { - // If we are already disconnected ignore the event - if(_self._poolState !== 'disconnected' && _self.listeners("timeout").length > 0) { - _self.emit("timeout", err); - } - - // Close the connection - connection.close(); - // Set disconnected - _self._poolState = 'disconnected'; - _self.stop(); - }); - - // Parse error, needs a complete shutdown of the pool - connection.on("parseError", function() { - // If we are already disconnected ignore the event - if(_self._poolState !== 'disconnected' && _self.listeners("parseError").length > 0) { - _self.emit("parseError", new Error("parseError occured")); - } - - // Set disconnected - _self._poolState = 'disconnected'; - _self.stop(); - }); - - connection.on("message", function(message) { - _self.emit("message", message); - }); - - // Start connection in the next tick - connection.start(); - // }(); -} - - -// Start method, will throw error if no listeners are available -// Pass in an instance of the listener that contains the api for -// finding callbacks for a given message etc. -ConnectionPool.prototype.start = function() { - var markerDate = new Date().getTime(); - var self = this; - - if(this.listeners("poolReady").length == 0) { - throw "pool must have at least one listener ready that responds to the [poolReady] event"; - } - - // Set pool state to connecting - this._poolState = 'connecting'; - this._timeout = false; - - _connect(self); -} - -// Restart a connection pool (on a close the pool might be in a wrong state) -ConnectionPool.prototype.restart = function() { - // Close all connections - this.stop(false); - // Now restart the pool - this.start(); -} - -// Stop the connections in the pool -ConnectionPool.prototype.stop = function(removeListeners) { - removeListeners = removeListeners == null ? true : removeListeners; - // Set disconnected - this._poolState = 'disconnected'; - - // Clear all listeners if specified - if(removeListeners) { - this.removeAllEventListeners(); - } - - // Close all connections - for(var i = 0; i < this.openConnections.length; i++) { - this.openConnections[i].close(); - } - - // Clean up - this.openConnections = []; -} - -// Check the status of the connection -ConnectionPool.prototype.isConnected = function() { - // return this._poolState === 'connected'; - return this.openConnections.length > 0 && this.openConnections[0].isConnected(); -} - -// Checkout a connection from the pool for usage, or grab a specific pool instance -ConnectionPool.prototype.checkoutConnection = function(id) { - var index = (this.currentConnectionIndex++ % (this.openConnections.length)); - var connection = this.openConnections[index]; - return connection; -} - -ConnectionPool.prototype.getAllConnections = function() { - return this.openConnections; -} - -// Remove all non-needed event listeners -ConnectionPool.prototype.removeAllEventListeners = function() { - this.removeAllListeners("close"); - this.removeAllListeners("error"); - this.removeAllListeners("timeout"); - this.removeAllListeners("connect"); - this.removeAllListeners("end"); - this.removeAllListeners("parseError"); - this.removeAllListeners("message"); - this.removeAllListeners("poolReady"); -} - - - - - - - - - - - - - - - - - - - - - - diff --git a/node_modules/mongodb/lib/mongodb/connection/connection_utils.js b/node_modules/mongodb/lib/mongodb/connection/connection_utils.js deleted file mode 100644 index 5910924..0000000 --- a/node_modules/mongodb/lib/mongodb/connection/connection_utils.js +++ /dev/null @@ -1,23 +0,0 @@ -exports.setIntegerParameter = function(object, field, defaultValue) { - if(object[field] == null) { - object[field] = defaultValue; - } else if(typeof object[field] !== "number" && object[field] !== parseInt(object[field], 10)) { - throw "object field [" + field + "] must be a numeric integer value, attempted to set to [" + object[field] + "] type of [" + typeof object[field] + "]"; - } -} - -exports.setBooleanParameter = function(object, field, defaultValue) { - if(object[field] == null) { - object[field] = defaultValue; - } else if(typeof object[field] !== "boolean") { - throw "object field [" + field + "] must be a boolean value, attempted to set to [" + object[field] + "] type of [" + typeof object[field] + "]"; - } -} - -exports.setStringParameter = function(object, field, defaultValue) { - if(object[field] == null) { - object[field] = defaultValue; - } else if(typeof object[field] !== "string") { - throw "object field [" + field + "] must be a string value, attempted to set to [" + object[field] + "] type of [" + typeof object[field] + "]"; - } -} \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/connection/mongos.js b/node_modules/mongodb/lib/mongodb/connection/mongos.js deleted file mode 100644 index 47c3361..0000000 --- a/node_modules/mongodb/lib/mongodb/connection/mongos.js +++ /dev/null @@ -1,578 +0,0 @@ -var ReadPreference = require('./read_preference').ReadPreference - , Base = require('./base').Base - , Server = require('./server').Server - , format = require('util').format - , timers = require('timers') - , utils = require('../utils') - , inherits = require('util').inherits; - -// Set processor, setImmediate if 0.10 otherwise nextTick -var processor = require('../utils').processor(); - -/** - * Mongos constructor provides a connection to a mongos proxy including failover to additional servers - * - * Options - * - **socketOptions** {Object, default:null}, an object containing socket options to use (noDelay:(boolean), keepAlive:(number), connectTimeoutMS:(number), socketTimeoutMS:(number)) - * - **ha** {Boolean, default:true}, turn on high availability, attempts to reconnect to down proxies - * - **haInterval** {Number, default:2000}, time between each replicaset status check. - * - * @class Represents a Mongos connection with failover to backup proxies - * @param {Array} list of mongos server objects - * @param {Object} [options] additional options for the mongos connection - */ -var Mongos = function Mongos(servers, options) { - // Set up basic - if(!(this instanceof Mongos)) - return new Mongos(servers, options); - - // Set up event emitter - Base.call(this); - - // Throw error on wrong setup - if(servers == null || !Array.isArray(servers) || servers.length == 0) - throw new Error("At least one mongos proxy must be in the array"); - - // Ensure we have at least an empty options object - this.options = options == null ? {} : options; - // Set default connection pool options - this.socketOptions = this.options.socketOptions != null ? this.options.socketOptions : {}; - // Enabled ha - this.haEnabled = this.options['ha'] == null ? true : this.options['ha']; - this._haInProgress = false; - // How often are we checking for new servers in the replicaset - this.mongosStatusCheckInterval = this.options['haInterval'] == null ? 1000 : this.options['haInterval']; - // Save all the server connections - this.servers = servers; - // Servers we need to attempt reconnect with - this.downServers = {}; - // Servers that are up - this.upServers = {}; - // Up servers by ping time - this.upServersByUpTime = {}; - // Set poolsize or default - this.poolSize = this.options.poolSize || 5; - // Emit open setup - this.emitOpen = this.options.emitOpen || true; - // Just contains the current lowest ping time and server - this.lowestPingTimeServer = null; - this.lowestPingTime = 0; - // Connection timeout - this._connectTimeoutMS = this.socketOptions.connectTimeoutMS - ? this.socketOptions.connectTimeoutMS - : 1000; - - // Add options to servers - for(var i = 0; i < this.servers.length; i++) { - var server = this.servers[i]; - server._callBackStore = this._callBackStore; - server.auto_reconnect = false; - - // Override pool size - if(typeof this.poolSize == 'number') { - server.poolSize = this.poolSize - } - - // Default empty socket options object - var socketOptions = {host: server.host, port: server.port}; - // If a socket option object exists clone it - if(this.socketOptions != null) { - var keys = Object.keys(this.socketOptions); - for(var k = 0; k < keys.length;k++) socketOptions[keys[i]] = this.socketOptions[keys[i]]; - } - - // Set socket options - server.socketOptions = socketOptions; - } - - // Allow setting the socketTimeoutMS on all connections - // to work around issues such as secondaries blocking due to compaction - utils.setSocketTimeoutProperty(this, this.socketOptions); -} - -/** - * @ignore - */ -inherits(Mongos, Base); - -/** - * @ignore - */ -Mongos.prototype.isMongos = function() { - return true; -} - -/** - * @ignore - */ -Mongos.prototype.connect = function(db, options, callback) { - if('function' === typeof options) callback = options, options = {}; - if(options == null) options = {}; - if(!('function' === typeof callback)) callback = null; - var self = this; - - // Keep reference to parent - this.db = db; - // Set server state to connecting - this._serverState = 'connecting'; - // Number of total servers that need to initialized (known servers) - this._numberOfServersLeftToInitialize = this.servers.length; - // Connect handler - var connectHandler = function(_server) { - return function(err, result) { - self._numberOfServersLeftToInitialize = self._numberOfServersLeftToInitialize - 1; - - // Add the server to the list of servers that are up - if(!err) { - self.upServers[format("%s:%s", _server.host, _server.port)] = _server; - } - - // We are done connecting - if(self._numberOfServersLeftToInitialize == 0) { - // If we have no valid mongos server instances error out - if(Object.keys(self.upServers).length == 0) { - // return self.emit("connectionError", new Error("No valid mongos instances found")); - return callback(new Error("No valid mongos instances found"), null); - } - - // Start ha function if it exists - if(self.haEnabled) { - // Setup the ha process - if(self._replicasetTimeoutId != null) clearInterval(self._replicasetTimeoutId); - self._replicasetTimeoutId = setInterval(self.mongosCheckFunction, self.mongosStatusCheckInterval); - } - - // Set the mongos to connected - self._serverState = "connected"; - - // Emit the open event - if(self.emitOpen) - self._emitAcrossAllDbInstances(self, null, "open", null, null, null); - - self._emitAcrossAllDbInstances(self, null, "fullsetup", null, null, null); - // Callback - callback(null, self.db); - } - } - }; - - // Error handler - var errorOrCloseHandler = function(_server) { - return function(err, result) { - // Emit left event, signaling mongos left the ha - self.emit('left', 'mongos', _server); - // Execute all the callbacks with errors - self.__executeAllCallbacksWithError(err); - // Check if we have the server - var found = false; - - // Get the server name - var server_name = format("%s:%s", _server.host, _server.port); - // Add the downed server - self.downServers[server_name] = _server; - // Remove the current server from the list - delete self.upServers[server_name]; - - // Emit close across all the attached db instances - if(Object.keys(self.upServers).length == 0) { - self._emitAcrossAllDbInstances(self, null, "close", new Error("mongos disconnected, no valid proxies contactable over tcp"), null, null); - } - } - } - - // Mongo function - this.mongosCheckFunction = function() { - // Set as not waiting for check event - self._haInProgress = true; - - // Servers down - var numberOfServersLeft = Object.keys(self.downServers).length; - - // Check downed servers - if(numberOfServersLeft > 0) { - for(var name in self.downServers) { - // Pop a downed server - var downServer = self.downServers[name]; - // Set up the connection options for a Mongos - var options = { - auto_reconnect: false, - returnIsMasterResults: true, - slaveOk: true, - poolSize: self.poolSize, - socketOptions: { - connectTimeoutMS: self._connectTimeoutMS, - socketTimeoutMS: self._socketTimeoutMS - } - } - - // Create a new server object - var newServer = new Server(downServer.host, downServer.port, options); - // Setup the connection function - var connectFunction = function(_db, _server, _options, _callback) { - return function() { - // Attempt to connect - _server.connect(_db, _options, function(err, result) { - numberOfServersLeft = numberOfServersLeft - 1; - - if(err) { - return _callback(err, _server); - } else { - // Set the new server settings - _server._callBackStore = self._callBackStore; - - // Add server event handlers - _server.on("close", errorOrCloseHandler(_server)); - _server.on("timeout", errorOrCloseHandler(_server)); - _server.on("error", errorOrCloseHandler(_server)); - - // Get a read connection - var _connection = _server.checkoutReader(); - // Get the start time - var startTime = new Date().getTime(); - - // Execute ping command to mark each server with the expected times - self.db.command({ping:1} - , {failFast:true, connection:_connection}, function(err, result) { - // Get the start time - var endTime = new Date().getTime(); - // Mark the server with the ping time - _server.runtimeStats['pingMs'] = endTime - startTime; - - // If we have any buffered commands let's signal reconnect event - if(self._commandsStore.count() > 0) { - self.emit('reconnect'); - } - - // Execute any waiting reads - self._commandsStore.execute_writes(); - self._commandsStore.execute_queries(); - // Callback - return _callback(null, _server); - }); - } - }); - } - } - - // Attempt to connect to the database - connectFunction(self.db, newServer, options, function(err, _server) { - // If we have an error - if(err) { - self.downServers[format("%s:%s", _server.host, _server.port)] = _server; - } - - // Connection function - var connectionFunction = function(_auth, _connection, _callback) { - var pending = _auth.length(); - - for(var j = 0; j < pending; j++) { - // Get the auth object - var _auth = _auth.get(j); - // Unpack the parameter - var username = _auth.username; - var password = _auth.password; - var options = { - authMechanism: _auth.authMechanism - , authSource: _auth.authdb - , connection: _connection - }; - - // If we have changed the service name - if(_auth.gssapiServiceName) - options.gssapiServiceName = _auth.gssapiServiceName; - - // Hold any error - var _error = null; - // Authenticate against the credentials - self.db.authenticate(username, password, options, function(err, result) { - _error = err != null ? err : _error; - // Adjust the pending authentication - pending = pending - 1; - // Finished up - if(pending == 0) _callback(_error ? _error : null, _error ? false : true); - }); - } - } - - // Run auths against the connections - if(self.auth.length() > 0) { - var connections = _server.allRawConnections(); - var pendingAuthConn = connections.length; - - // No connections we are done - if(connections.length == 0) { - // Set ha done - if(numberOfServersLeft == 0) { - self._haInProgress = false; - } - } - - // Final error object - var finalError = null; - // Go over all the connections - for(var j = 0; j < connections.length; j++) { - - // Execute against all the connections - connectionFunction(self.auth, connections[j], function(err, result) { - // Pending authentication - pendingAuthConn = pendingAuthConn - 1 ; - - // Save error if any - finalError = err ? err : finalError; - - // If we are done let's finish up - if(pendingAuthConn == 0) { - // Set ha done - if(numberOfServersLeft == 0) { - self._haInProgress = false; - } - - if(!err) { - add_server(self, _server); - } - - // If we have any buffered commands let's signal reconnect event - if(self._commandsStore.count() > 0) { - self.emit('reconnect'); - } - - // Execute any waiting reads - self._commandsStore.execute_writes(); - self._commandsStore.execute_queries(); - } - }); - } - } else { - if(!err) { - add_server(self, _server); - } - - // Set ha done - if(numberOfServersLeft == 0) { - self._haInProgress = false; - - // If we have any buffered commands let's signal reconnect event - if(self._commandsStore.count() > 0) { - self.emit('reconnect'); - } - - // Execute any waiting reads - self._commandsStore.execute_writes(); - self._commandsStore.execute_queries(); - } - } - })(); - } - } else { - self._haInProgress = false; - } - } - - // Connect all the server instances - for(var i = 0; i < this.servers.length; i++) { - // Get the connection - var server = this.servers[i]; - server.mongosInstance = this; - // Add server event handlers - server.on("close", errorOrCloseHandler(server)); - server.on("timeout", errorOrCloseHandler(server)); - server.on("error", errorOrCloseHandler(server)); - - // Configuration - var options = { - slaveOk: true, - poolSize: this.poolSize || server.poolSize, - socketOptions: { connectTimeoutMS: self._connectTimeoutMS }, - returnIsMasterResults: true - } - - // Connect the instance - server.connect(self.db, options, connectHandler(server)); - } -} - -/** - * @ignore - * Add a server to the list of up servers and sort them by ping time - */ -var add_server = function(self, _server) { - // Emit a new server joined - self.emit('joined', "mongos", null, _server); - // Get the server url - var server_key = format("%s:%s", _server.host, _server.port); - // Push to list of valid server - self.upServers[server_key] = _server; - // Remove the server from the list of downed servers - delete self.downServers[server_key]; - - // Sort the keys by ping time - var keys = Object.keys(self.upServers); - var _upServersSorted = {}; - var _upServers = [] - - // Get all the servers - for(var name in self.upServers) { - _upServers.push(self.upServers[name]); - } - - // Sort all the server - _upServers.sort(function(a, b) { - return a.runtimeStats['pingMs'] > b.runtimeStats['pingMs']; - }); - - // Rebuild the upServer - for(var i = 0; i < _upServers.length; i++) { - _upServersSorted[format("%s:%s", _upServers[i].host, _upServers[i].port)] = _upServers[i]; - } - - // Set the up servers - self.upServers = _upServersSorted; -} - -/** - * @ignore - * Just return the currently picked active connection - */ -Mongos.prototype.allServerInstances = function() { - return this.servers; -} - -/** - * @ignore - */ -Mongos.prototype.setSocketOptions = function(options) { - var servers = this.allServerInstances(); - for(var i = 0; i < servers.length; i++) { - servers[i].setSocketOptions(options); - } -} - -/** - * Always ourselves - * @ignore - */ -Mongos.prototype.setReadPreference = function() {} - -/** - * @ignore - */ -Mongos.prototype.allRawConnections = function() { - // Neeed to build a complete list of all raw connections, start with master server - var allConnections = []; - // Get all connected connections - for(var name in this.upServers) { - allConnections = allConnections.concat(this.upServers[name].allRawConnections()); - } - // Return all the conections - return allConnections; -} - -/** - * @ignore - */ -Mongos.prototype.isConnected = function() { - return Object.keys(this.upServers).length > 0; -} - -/** - * @ignore - */ -Mongos.prototype.isAutoReconnect = function() { - return true; -} - -/** - * @ignore - */ -Mongos.prototype.canWrite = Mongos.prototype.isConnected; - -/** - * @ignore - */ -Mongos.prototype.canRead = Mongos.prototype.isConnected; - -/** - * @ignore - */ -Mongos.prototype.isDestroyed = function() { - return this._serverState == 'destroyed'; -} - -/** - * @ignore - */ -Mongos.prototype.checkoutWriter = function() { - // Checkout a writer - var keys = Object.keys(this.upServers); - if(keys.length == 0) return null; - return this.upServers[keys[0]].checkoutWriter(); -} - -/** - * @ignore - */ -Mongos.prototype.checkoutReader = function(read) { - // If read is set to null default to primary - read = read || 'primary' - // If we have a read preference object unpack it - if(read != null && typeof read == 'object' && read['_type'] == 'ReadPreference') { - // Validate if the object is using a valid mode - if(!read.isValid()) throw new Error("Illegal readPreference mode specified, " + JSON.stringify(read)); - } else if(!ReadPreference.isValid(read)) { - throw new Error("Illegal readPreference mode specified, " + JSON.stringify(read)); - } - - // Checkout a writer - var keys = Object.keys(this.upServers); - if(keys.length == 0) return null; - return this.upServers[keys[0]].checkoutWriter(); -} - -/** - * @ignore - */ -Mongos.prototype.close = function(callback) { - var self = this; - // Set server status as disconnected - this._serverState = 'destroyed'; - // Number of connections to close - var numberOfConnectionsToClose = self.servers.length; - // If we have a ha process running kill it - if(self._replicasetTimeoutId != null) clearInterval(self._replicasetTimeoutId); - self._replicasetTimeoutId = null; - - // Emit close event - processor(function() { - self._emitAcrossAllDbInstances(self, null, "close", null, null, true) - }); - - // Flush out any remaining call handlers - self._flushAllCallHandlers(utils.toError("Connection Closed By Application")); - - // No up servers just return - if(Object.keys(this.upServers) == 0) { - return callback(null); - } - - // Close all the up servers - for(var name in this.upServers) { - this.upServers[name].close(function(err, result) { - numberOfConnectionsToClose = numberOfConnectionsToClose - 1; - - // Callback if we have one defined - if(numberOfConnectionsToClose == 0 && typeof callback == 'function') { - callback(null); - } - }); - } -} - -/** - * @ignore - * Return the used state - */ -Mongos.prototype._isUsed = function() { - return this._used; -} - -exports.Mongos = Mongos; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/connection/read_preference.js b/node_modules/mongodb/lib/mongodb/connection/read_preference.js deleted file mode 100644 index 6caafa9..0000000 --- a/node_modules/mongodb/lib/mongodb/connection/read_preference.js +++ /dev/null @@ -1,67 +0,0 @@ -/** - * A class representation of the Read Preference. - * - * Read Preferences - * - **ReadPreference.PRIMARY**, Read from primary only. All operations produce an error (throw an exception where applicable) if primary is unavailable. Cannot be combined with tags (This is the default.). - * - **ReadPreference.PRIMARY_PREFERRED**, Read from primary if available, otherwise a secondary. - * - **ReadPreference.SECONDARY**, Read from secondary if available, otherwise error. - * - **ReadPreference.SECONDARY_PREFERRED**, Read from a secondary if available, otherwise read from the primary. - * - **ReadPreference.NEAREST**, All modes read from among the nearest candidates, but unlike other modes, NEAREST will include both the primary and all secondaries in the random selection. - * - * @class Represents a Read Preference. - * @param {String} the read preference type - * @param {Object} tags - * @return {ReadPreference} - */ -var ReadPreference = function(mode, tags) { - if(!(this instanceof ReadPreference)) - return new ReadPreference(mode, tags); - this._type = 'ReadPreference'; - this.mode = mode; - this.tags = tags; -} - -/** - * @ignore - */ -ReadPreference.isValid = function(_mode) { - return (_mode == ReadPreference.PRIMARY || _mode == ReadPreference.PRIMARY_PREFERRED - || _mode == ReadPreference.SECONDARY || _mode == ReadPreference.SECONDARY_PREFERRED - || _mode == ReadPreference.NEAREST - || _mode == true || _mode == false || _mode == null); -} - -/** - * @ignore - */ -ReadPreference.prototype.isValid = function(mode) { - var _mode = typeof mode == 'string' ? mode : this.mode; - return ReadPreference.isValid(_mode); -} - -/** - * @ignore - */ -ReadPreference.prototype.toObject = function() { - var object = {mode:this.mode}; - - if(this.tags != null) { - object['tags'] = this.tags; - } - - return object; -} - -/** - * @ignore - */ -ReadPreference.PRIMARY = 'primary'; -ReadPreference.PRIMARY_PREFERRED = 'primaryPreferred'; -ReadPreference.SECONDARY = 'secondary'; -ReadPreference.SECONDARY_PREFERRED = 'secondaryPreferred'; -ReadPreference.NEAREST = 'nearest' - -/** - * @ignore - */ -exports.ReadPreference = ReadPreference; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/connection/repl_set/ha.js b/node_modules/mongodb/lib/mongodb/connection/repl_set/ha.js deleted file mode 100644 index 63f270d..0000000 --- a/node_modules/mongodb/lib/mongodb/connection/repl_set/ha.js +++ /dev/null @@ -1,448 +0,0 @@ -var DbCommand = require('../../commands/db_command').DbCommand - , format = require('util').format; - -var HighAvailabilityProcess = function(replset, options) { - this.replset = replset; - this.options = options; - this.server = null; - this.state = HighAvailabilityProcess.INIT; - this.selectedIndex = 0; -} - -HighAvailabilityProcess.INIT = 'init'; -HighAvailabilityProcess.RUNNING = 'running'; -HighAvailabilityProcess.STOPPED = 'stopped'; - -HighAvailabilityProcess.prototype.start = function() { - var self = this; - if(this.replset._state - && Object.keys(this.replset._state.addresses).length == 0) { - if(this.server) this.server.close(); - this.state = HighAvailabilityProcess.STOPPED; - return; - } - - if(this.server) this.server.close(); - // Start the running - this._haProcessInProcess = false; - this.state = HighAvailabilityProcess.RUNNING; - - // Get all possible reader servers - var candidate_servers = this.replset._state.getAllReadServers(); - if(candidate_servers.length == 0) { - return; - } - - // Select a candidate server for the connection - var server = candidate_servers[this.selectedIndex % candidate_servers.length]; - this.selectedIndex = this.selectedIndex + 1; - - // Unpack connection options - var connectTimeoutMS = self.options.connectTimeoutMS || 10000; - var socketTimeoutMS = self.options.socketTimeoutMS || 30000; - - // Just ensure we don't have a full cycle dependency - var Db = require('../../db').Db - var Server = require('../server').Server; - - // Set up a new server instance - var newServer = new Server(server.host, server.port, { - auto_reconnect: false - , returnIsMasterResults: true - , poolSize: 1 - , socketOptions: { - connectTimeoutMS: connectTimeoutMS, - socketTimeoutMS: socketTimeoutMS, - keepAlive: 100 - } - , ssl: self.replset.options.ssl - , sslValidate: self.replset.options.sslValidate - , sslCA: self.replset.options.sslCA - , sslCert: self.replset.options.sslCert - , sslKey: self.replset.options.sslKey - , sslPass: self.replset.options.sslPass - }); - - // Create new dummy db for app - self.db = new Db('local', newServer, {w:1}); - - // Set up the event listeners - newServer.once("error", _handle(this, newServer)); - newServer.once("close", _handle(this, newServer)); - newServer.once("timeout", _handle(this, newServer)); - newServer.name = format("%s:%s", server.host, server.port); - - // Let's attempt a connection over here - newServer.connect(self.db, function(err, result, _server) { - // Emit ha_connect - self.replset.emit("ha_connect", err, result, _server); - - if(self.state == HighAvailabilityProcess.STOPPED) { - _server.close(); - } - - if(err) { - // Close the server - _server.close(); - // Check if we can even do HA (is there anything running) - if(Object.keys(self.replset._state.addresses).length == 0) { - return; - } - - // Let's boot the ha timeout settings - setTimeout(function() { - self.start(); - }, self.options.haInterval); - } else { - self.server = _server; - // Let's boot the ha timeout settings - setTimeout(_timeoutHandle(self), self.options.haInterval); - } - }); -} - -HighAvailabilityProcess.prototype.stop = function() { - this.state = HighAvailabilityProcess.STOPPED; - if(this.server) this.server.close(); -} - -var _timeoutHandle = function(self) { - return function() { - if(self.state == HighAvailabilityProcess.STOPPED) { - // Stop all server instances - for(var name in self.replset._state.addresses) { - self.replset._state.addresses[name].close(); - delete self.replset._state.addresses[name]; - } - - // Finished pinging - return; - } - - // If the server is connected - if(self.server.isConnected() && !self._haProcessInProcess) { - // Start HA process - self._haProcessInProcess = true; - // Execute is master command - self.db._executeQueryCommand(DbCommand.createIsMasterCommand(self.db), - {failFast:true, connection: self.server.checkoutReader()} - , function(err, res) { - // Emit ha event - self.replset.emit("ha_ismaster", err, res); - - // If we have an error close - if(err) { - self.server.close(); - // Re-run loop - return setTimeout(_timeoutHandle(self), self.options.haInterval); - } - - // Master document - var master = res.documents[0]; - var hosts = master.hosts || []; - var reconnect_servers = []; - var state = self.replset._state; - - // We are in recovery mode, let's remove the current server - if(!master.ismaster - && !master.secondary - && state.addresses[master.me]) { - self.server.close(); - state.addresses[master.me].close(); - delete state.secondaries[master.me]; - // Re-run loop - return setTimeout(_timeoutHandle(self), self.options.haInterval); - } - - // We have a new master different front he current one - if((master.primary && state.master == null) - || (master.primary && state.master.name != master.primary)) { - - // Locate the primary and set it - if(state.addresses[master.primary]) { - if(state.master) state.master.close(); - delete state.secondaries[master.primary]; - state.master = state.addresses[master.primary]; - } - - // Emit joined event due to primary change - self.replset.emit('joined', "primary", master, state.master); - - // Set up the changes - if(state.master != null && state.master.isMasterDoc != null) { - state.master.isMasterDoc.ismaster = true; - state.master.isMasterDoc.secondary = false; - } else if(state.master != null) { - state.master.isMasterDoc = master; - state.master.isMasterDoc.ismaster = true; - state.master.isMasterDoc.secondary = false; - } - - // If we have any buffered commands let's signal reconnect event - if(self.replset._commandsStore.count() > 0) { - self.replset.emit('reconnect'); - } - - // Execute any waiting commands (queries or writes) - self.replset._commandsStore.execute_queries(); - self.replset._commandsStore.execute_writes(); - } - - // For all the hosts let's check that we have connections - for(var i = 0; i < hosts.length; i++) { - var host = hosts[i]; - - // Check if we need to reconnect to a server - if(state.addresses[host] == null) { - reconnect_servers.push(host); - } else if(state.addresses[host] && !state.addresses[host].isConnected()) { - state.addresses[host].close(); - delete state.secondaries[host]; - reconnect_servers.push(host); - } - } - - // Let's reconnect to any server needed - if(reconnect_servers.length > 0) { - _reconnect_servers(self, reconnect_servers); - } else { - self._haProcessInProcess = false - return setTimeout(_timeoutHandle(self), self.options.haInterval); - } - }); - } else if(!self.server.isConnected()) { - setTimeout(function() { - return self.start(); - }, self.options.haInterval); - } else { - setTimeout(_timeoutHandle(self), self.options.haInterval); - } - } -} - -var _reconnect_servers = function(self, reconnect_servers) { - if(reconnect_servers.length == 0) { - self._haProcessInProcess = false - return setTimeout(_timeoutHandle(self), self.options.haInterval); - } - - // Unpack connection options - var connectTimeoutMS = self.options.connectTimeoutMS || 10000; - var socketTimeoutMS = self.options.socketTimeoutMS || 0; - - // Server class - var Db = require('../../db').Db - var Server = require('../server').Server; - // Get the host - var host = reconnect_servers.shift(); - // Split it up - var _host = host.split(":")[0]; - var _port = parseInt(host.split(":")[1], 10); - - // Set up a new server instance - var newServer = new Server(_host, _port, { - auto_reconnect: false - , returnIsMasterResults: true - , poolSize: self.options.poolSize - , socketOptions: { - connectTimeoutMS: connectTimeoutMS, - socketTimeoutMS: socketTimeoutMS - } - , ssl: self.replset.options.ssl - , sslValidate: self.replset.options.sslValidate - , sslCA: self.replset.options.sslCA - , sslCert: self.replset.options.sslCert - , sslKey: self.replset.options.sslKey - , sslPass: self.replset.options.sslPass - }); - - // Create new dummy db for app - var db = new Db('local', newServer, {w:1}); - var state = self.replset._state; - - // Set up the event listeners - newServer.once("error", _repl_set_handler("error", self.replset, newServer)); - newServer.once("close", _repl_set_handler("close", self.replset, newServer)); - newServer.once("timeout", _repl_set_handler("timeout", self.replset, newServer)); - - // Set shared state - newServer.name = host; - newServer._callBackStore = self.replset._callBackStore; - newServer.replicasetInstance = self.replset; - newServer.enableRecordQueryStats(self.replset.recordQueryStats); - - // Let's attempt a connection over here - newServer.connect(db, function(err, result, _server) { - // Emit ha_connect - self.replset.emit("ha_connect", err, result, _server); - - if(self.state == HighAvailabilityProcess.STOPPED) { - _server.close(); - } - - // If we connected let's check what kind of server we have - if(!err) { - _apply_auths(self, db, _server, function(err, result) { - if(err) { - _server.close(); - // Process the next server - return setTimeout(function() { - _reconnect_servers(self, reconnect_servers); - }, self.options.haInterval); - } - - var doc = _server.isMasterDoc; - // Fire error on any unknown callbacks for this server - self.replset.__executeAllServerSpecificErrorCallbacks(_server.socketOptions.host, _server.socketOptions.port, err); - - if(doc.ismaster) { - // Emit primary added - self.replset.emit('joined', "primary", doc, _server); - - // If it was a secondary remove it - if(state.secondaries[doc.me]) { - delete state.secondaries[doc.me]; - } - - // Override any server in list of addresses - state.addresses[doc.me] = _server; - // Set server as master - state.master = _server; - - // If we have any buffered commands let's signal reconnect event - if(self.replset._commandsStore.count() > 0) { - self.replset.emit('reconnect'); - } - - // Execute any waiting writes - self.replset._commandsStore.execute_writes(); - } else if(doc.secondary) { - // Emit secondary added - self.replset.emit('joined', "secondary", doc, _server); - // Add the secondary to the state - state.secondaries[doc.me] = _server; - // Override any server in list of addresses - state.addresses[doc.me] = _server; - - // If we have any buffered commands let's signal reconnect event - if(self.replset._commandsStore.count() > 0) { - self.replset.emit('reconnect'); - } - - // Execute any waiting reads - self.replset._commandsStore.execute_queries(); - } else { - _server.close(); - } - - // Set any tags on the instance server - _server.name = doc.me; - _server.tags = doc.tags; - // Process the next server - setTimeout(function() { - _reconnect_servers(self, reconnect_servers); - }, self.options.haInterval); - }); - } else { - _server.close(); - self.replset.__executeAllServerSpecificErrorCallbacks(_server.socketOptions.host, _server.socketOptions.port, err); - - setTimeout(function() { - _reconnect_servers(self, reconnect_servers); - }, self.options.haInterval); - } - }); -} - -var _apply_auths = function(self, _db, _server, _callback) { - if(self.replset.auth.length() == 0) return _callback(null); - // Apply any authentication needed - if(self.replset.auth.length() > 0) { - var pending = self.replset.auth.length(); - var connections = _server.allRawConnections(); - var pendingAuthConn = connections.length; - // Connection function - var connectionFunction = function(auth, _connection, __callback) { - var pending = auth.length(); - - for(var j = 0; j < pending; j++) { - // Get the auth object - var _auth = auth.get(j); - // Unpack the parameter - var username = _auth.username; - var password = _auth.password; - var options = { - authMechanism: _auth.authMechanism - , authSource: _auth.authdb - , connection: _connection - }; - - // If we have changed the service name - if(_auth.gssapiServiceName) - options.gssapiServiceName = _auth.gssapiServiceName; - - // Hold any error - var _error = null; - - // Authenticate against the credentials - _db.authenticate(username, password, options, function(err, result) { - _error = err != null ? err : _error; - // Adjust the pending authentication - pending = pending - 1; - // Finished up - if(pending == 0) __callback(_error ? _error : null, _error ? false : true); - }); - } - } - - // Final error object - var finalError = null; - // Iterate over all the connections - for(var i = 0; i < connections.length; i++) { - connectionFunction(self.replset.auth, connections[i], function(err, result) { - // Pending authentication - pendingAuthConn = pendingAuthConn - 1 ; - - // Save error if any - finalError = err ? err : finalError; - - // If we are done let's finish up - if(pendingAuthConn == 0) { - _callback(null); - } - }); - } - } -} - -var _handle = function(self, server) { - return function(err) { - server.close(); - } -} - -var _repl_set_handler = function(event, self, server) { - var ReplSet = require('./repl_set').ReplSet; - - return function(err, doc) { - server.close(); - - // The event happened to a primary - // Remove it from play - if(self._state.isPrimary(server)) { - self._state.master == null; - self._serverState = ReplSet.REPLSET_READ_ONLY; - } else if(self._state.isSecondary(server)) { - delete self._state.secondaries[server.name]; - } - - // Unpack variables - var host = server.socketOptions.host; - var port = server.socketOptions.port; - - // Fire error on any unknown callbacks - self.__executeAllServerSpecificErrorCallbacks(host, port, err); - } -} - -exports.HighAvailabilityProcess = HighAvailabilityProcess; diff --git a/node_modules/mongodb/lib/mongodb/connection/repl_set/options.js b/node_modules/mongodb/lib/mongodb/connection/repl_set/options.js deleted file mode 100644 index 8b3d72b..0000000 --- a/node_modules/mongodb/lib/mongodb/connection/repl_set/options.js +++ /dev/null @@ -1,126 +0,0 @@ -var PingStrategy = require('./strategies/ping_strategy').PingStrategy - , StatisticsStrategy = require('./strategies/statistics_strategy').StatisticsStrategy - , ReadPreference = require('../read_preference').ReadPreference; - -var Options = function(options) { - options = options || {}; - this._options = options; - this.ha = options.ha || true; - this.haInterval = options.haInterval || 2000; - this.reconnectWait = options.reconnectWait || 1000; - this.retries = options.retries || 30; - this.rs_name = options.rs_name; - this.socketOptions = options.socketOptions || {}; - this.readPreference = options.readPreference; - this.readSecondary = options.read_secondary; - this.poolSize = options.poolSize == null ? 5 : options.poolSize; - this.strategy = options.strategy || 'ping'; - this.secondaryAcceptableLatencyMS = options.secondaryAcceptableLatencyMS || 15; - this.connectArbiter = options.connectArbiter || false; - this.connectWithNoPrimary = options.connectWithNoPrimary || false; - this.logger = options.logger; - this.ssl = options.ssl || false; - this.sslValidate = options.sslValidate || false; - this.sslCA = options.sslCA; - this.sslCert = options.sslCert; - this.sslKey = options.sslKey; - this.sslPass = options.sslPass; - this.emitOpen = options.emitOpen || true; -} - -Options.prototype.init = function() { - if(this.sslValidate && (!Array.isArray(this.sslCA) || this.sslCA.length == 0)) { - throw new Error("The driver expects an Array of CA certificates in the sslCA parameter when enabling sslValidate"); - } - - // Make sure strategy is one of the two allowed - if(this.strategy != null && (this.strategy != 'ping' && this.strategy != 'statistical' && this.strategy != 'none')) - throw new Error("Only ping or statistical strategies allowed"); - - if(this.strategy == null) this.strategy = 'ping'; - - // Set logger if strategy exists - if(this.strategyInstance) this.strategyInstance.logger = this.logger; - - // Unpack read Preference - var readPreference = this.readPreference; - // Validate correctness of Read preferences - if(readPreference != null) { - if(readPreference != ReadPreference.PRIMARY && readPreference != ReadPreference.PRIMARY_PREFERRED - && readPreference != ReadPreference.SECONDARY && readPreference != ReadPreference.SECONDARY_PREFERRED - && readPreference != ReadPreference.NEAREST && typeof readPreference != 'object' && readPreference['_type'] != 'ReadPreference') { - throw new Error("Illegal readPreference mode specified, " + JSON.stringify(readPreference)); - } - - this.readPreference = readPreference; - } else { - this.readPreference = null; - } - - // Ensure read_secondary is set correctly - if(this.readSecondary != null) - this.readSecondary = this.readPreference == ReadPreference.PRIMARY - || this.readPreference == false - || this.readPreference == null ? false : true; - - // Ensure correct slave set - if(this.readSecondary) this.slaveOk = true; - - // Set up logger if any set - this.logger = this.logger != null - && (typeof this.logger.debug == 'function') - && (typeof this.logger.error == 'function') - && (typeof this.logger.debug == 'function') - ? this.logger : {error:function(message, object) {}, log:function(message, object) {}, debug:function(message, object) {}}; - - // Connection timeout - this.connectTimeoutMS = typeof this.socketOptions.connectTimeoutMS == 'number' - ? this.socketOptions.connectTimeoutMS - : 1000; - - // Socket connection timeout - this.socketTimeoutMS = typeof this.socketOptions.socketTimeoutMS == 'number' - ? this.socketOptions.socketTimeoutMS - : 30000; -} - -Options.prototype.decorateAndClean = function(servers, callBackStore) { - var self = this; - - // var de duplicate list - var uniqueServers = {}; - // De-duplicate any servers in the seed list - for(var i = 0; i < servers.length; i++) { - var server = servers[i]; - // If server does not exist set it - if(uniqueServers[server.host + ":" + server.port] == null) { - uniqueServers[server.host + ":" + server.port] = server; - } - } - - // Let's set the deduplicated list of servers - var finalServers = []; - // Add the servers - for(var key in uniqueServers) { - finalServers.push(uniqueServers[key]); - } - - finalServers.forEach(function(server) { - // Ensure no server has reconnect on - server.options.auto_reconnect = false; - // Set up ssl options - server.ssl = self.ssl; - server.sslValidate = self.sslValidate; - server.sslCA = self.sslCA; - server.sslCert = self.sslCert; - server.sslKey = self.sslKey; - server.sslPass = self.sslPass; - server.poolSize = self.poolSize; - // Set callback store - server._callBackStore = callBackStore; - }); - - return finalServers; -} - -exports.Options = Options; diff --git a/node_modules/mongodb/lib/mongodb/connection/repl_set/repl_set.js b/node_modules/mongodb/lib/mongodb/connection/repl_set/repl_set.js deleted file mode 100644 index 0e95cfa..0000000 --- a/node_modules/mongodb/lib/mongodb/connection/repl_set/repl_set.js +++ /dev/null @@ -1,830 +0,0 @@ -var ReadPreference = require('../read_preference').ReadPreference - , DbCommand = require('../../commands/db_command').DbCommand - , inherits = require('util').inherits - , format = require('util').format - , timers = require('timers') - , Server = require('../server').Server - , utils = require('../../utils') - , PingStrategy = require('./strategies/ping_strategy').PingStrategy - , StatisticsStrategy = require('./strategies/statistics_strategy').StatisticsStrategy - , Options = require('./options').Options - , ReplSetState = require('./repl_set_state').ReplSetState - , HighAvailabilityProcess = require('./ha').HighAvailabilityProcess - , Base = require('../base').Base; - -var STATE_STARTING_PHASE_1 = 0; -var STATE_PRIMARY = 1; -var STATE_SECONDARY = 2; -var STATE_RECOVERING = 3; -var STATE_FATAL_ERROR = 4; -var STATE_STARTING_PHASE_2 = 5; -var STATE_UNKNOWN = 6; -var STATE_ARBITER = 7; -var STATE_DOWN = 8; -var STATE_ROLLBACK = 9; - -// Set processor, setImmediate if 0.10 otherwise nextTick -var processor = require('../../utils').processor(); - -/** - * ReplSet constructor provides replicaset functionality - * - * Options - * - **ha** {Boolean, default:true}, turn on high availability. - * - **haInterval** {Number, default:2000}, time between each replicaset status check. - * - **reconnectWait** {Number, default:1000}, time to wait in miliseconds before attempting reconnect. - * - **retries** {Number, default:30}, number of times to attempt a replicaset reconnect. - * - **rs_name** {String}, the name of the replicaset to connect to. - * - **socketOptions** {Object, default:null}, an object containing socket options to use (noDelay:(boolean), keepAlive:(number), connectTimeoutMS:(number), socketTimeoutMS:(number)) - * - **strategy** {String, default:'ping'}, selection strategy for reads choose between (ping, statistical and none, default is ping) - * - **secondaryAcceptableLatencyMS** {Number, default:15}, sets the range of servers to pick when using NEAREST (lowest ping ms + the latency fence, ex: range of 1 to (1 + 15) ms) - * - **connectWithNoPrimary** {Boolean, default:false}, sets if the driver should connect even if no primary is available - * - **connectArbiter** {Boolean, default:false}, sets if the driver should connect to arbiters or not. - * - **logger** {Object, default:null}, an object representing a logger that you want to use, needs to support functions debug, log, error **({error:function(message, object) {}, log:function(message, object) {}, debug:function(message, object) {}})**. - * - **poolSize** {Number, default:5}, number of connections in the connection pool for each server instance, set to 5 as default for legacy reasons. - * - **ssl** {Boolean, default:false}, use ssl connection (needs to have a mongod server with ssl support) - * - **sslValidate** {Boolean, default:false}, validate mongod server certificate against ca (needs to have a mongod server with ssl support, 2.4 or higher) - * - **sslCA** {Array, default:null}, Array of valid certificates either as Buffers or Strings (needs to have a mongod server with ssl support, 2.4 or higher) - * - **sslCert** {Buffer/String, default:null}, String or buffer containing the certificate we wish to present (needs to have a mongod server with ssl support, 2.4 or higher) - * - **sslKey** {Buffer/String, default:null}, String or buffer containing the certificate private key we wish to present (needs to have a mongod server with ssl support, 2.4 or higher) - * - **sslPass** {Buffer/String, default:null}, String or buffer containing the certificate password (needs to have a mongod server with ssl support, 2.4 or higher) - * - * @class Represents a - Replicaset Configuration - * @param {Array} list of server objects participating in the replicaset. - * @param {Object} [options] additional options for the replicaset connection. - */ -var ReplSet = exports.ReplSet = function(servers, options) { - // Set up basic - if(!(this instanceof ReplSet)) - return new ReplSet(servers, options); - - // Set up event emitter - Base.call(this); - - // Ensure we have a list of servers - if(!Array.isArray(servers)) throw Error("The parameter must be an array of servers and contain at least one server"); - // Ensure no Mongos's - for(var i = 0; i < servers.length; i++) { - if(!(servers[i] instanceof Server)) throw new Error("list of servers must be of type Server"); - } - - // Save the options - this.options = new Options(options); - // Ensure basic validation of options - this.options.init(); - - // Server state - this._serverState = ReplSet.REPLSET_DISCONNECTED; - // Add high availability process - this._haProcess = new HighAvailabilityProcess(this, this.options); - - // Let's iterate over all the provided server objects and decorate them - this.servers = this.options.decorateAndClean(servers, this._callBackStore); - // Throw error if no seed servers - if(this.servers.length == 0) throw new Error("No valid seed servers in the array"); - - // Let's set up our strategy object for picking secondaries - if(this.options.strategy == 'ping') { - // Create a new instance - this.strategyInstance = new PingStrategy(this, this.options.secondaryAcceptableLatencyMS); - } else if(this.options.strategy == 'statistical') { - // Set strategy as statistical - this.strategyInstance = new StatisticsStrategy(this); - // Add enable query information - this.enableRecordQueryStats(true); - } - - this.emitOpen = this.options.emitOpen || true; - // Set up a clean state - this._state = new ReplSetState(this); - // Current round robin selected server - this._currentServerChoice = 0; - // Ensure up the server callbacks - for(var i = 0; i < this.servers.length; i++) { - this.servers[i]._callBackStore = this._callBackStore; - this.servers[i].name = format("%s:%s", this.servers[i].host, this.servers[i].port) - this.servers[i].replicasetInstance = this; - this.servers[i].options.auto_reconnect = false; - this.servers[i].poolSize = this.options.poolSize; - this.servers[i].inheritReplSetOptionsFrom(this); - } - - // Allow setting the socketTimeoutMS on all connections - // to work around issues such as secondaries blocking due to compaction - utils.setSocketTimeoutProperty(this, this.options.socketOptions); -} - -/** - * @ignore - */ -inherits(ReplSet, Base); - -// Replicaset states -ReplSet.REPLSET_CONNECTING = 'connecting'; -ReplSet.REPLSET_DISCONNECTED = 'disconnected'; -ReplSet.REPLSET_CONNECTED = 'connected'; -ReplSet.REPLSET_RECONNECTING = 'reconnecting'; -ReplSet.REPLSET_DESTROYED = 'destroyed'; -ReplSet.REPLSET_READ_ONLY = 'readonly'; - -ReplSet.prototype.isAutoReconnect = function() { - return true; -} - -ReplSet.prototype.canWrite = function() { - return this._state.master && this._state.master.isConnected(); -} - -ReplSet.prototype.canRead = function(read) { - if((read == ReadPreference.PRIMARY - || (typeof read == 'object' && read.mode == ReadPreference.PRIMARY) - || read == null || read == false) && (this._state.master == null || !this._state.master.isConnected())) return false; - return Object.keys(this._state.secondaries).length > 0; -} - -/** - * @ignore - */ -ReplSet.prototype.enableRecordQueryStats = function(enable) { - // Set the global enable record query stats - this.recordQueryStats = enable; - - // Enable all the servers - for(var i = 0; i < this.servers.length; i++) { - this.servers[i].enableRecordQueryStats(enable); - } -} - -/** - * @ignore - */ -ReplSet.prototype.setSocketOptions = function(options) { - var servers = this.allServerInstances(); - - if(typeof options.socketTimeoutMS == 'number') { - this.options.socketOptions.socketTimeoutMS = options.socketTimeoutMS; - } - - if(typeof options.connectTimeoutMS == 'number') - this.options.socketOptions.connectTimeoutMS = options.connectTimeoutMS; - - for(var i = 0; i < servers.length; i++) { - servers[i].setSocketOptions(options); - } -} - -/** - * @ignore - */ -ReplSet.prototype.setReadPreference = function(preference) { - this.options.readPreference = preference; -} - -ReplSet.prototype.connect = function(parent, options, callback) { - if(this._serverState != ReplSet.REPLSET_DISCONNECTED) - return callback(new Error("in process of connection")); - - // If no callback throw - if(!(typeof callback == 'function')) - throw new Error("cannot call ReplSet.prototype.connect with no callback function"); - - var self = this; - // Save db reference - this.options.db = parent; - // Set replicaset as connecting - this._serverState = ReplSet.REPLSET_CONNECTING - // Copy all the servers to our list of seeds - var candidateServers = this.servers.slice(0); - // Pop the first server - var server = candidateServers.pop(); - server.name = format("%s:%s", server.host, server.port); - // Set up the options - var opts = { - returnIsMasterResults: true, - eventReceiver: server - } - - // Register some event listeners - this.once("fullsetup", function(err, db, replset) { - // Set state to connected - self._serverState = ReplSet.REPLSET_CONNECTED; - // Stop any process running - if(self._haProcess) self._haProcess.stop(); - // Start the HA process - self._haProcess.start(); - - // Emit fullsetup - processor(function() { - if(self.emitOpen) - self._emitAcrossAllDbInstances(self, null, "open", null, null, null); - - self._emitAcrossAllDbInstances(self, null, "fullsetup", null, null, null); - }); - - // If we have a strategy defined start it - if(self.strategyInstance) { - self.strategyInstance.start(); - } - - // Finishing up the call - callback(err, db, replset); - }); - - // Errors - this.once("connectionError", function(err, result) { - callback(err, result); - }); - - // Attempt to connect to the server - server.connect(this.options.db, opts, _connectHandler(this, candidateServers, server)); -} - -ReplSet.prototype.close = function(callback) { - var self = this; - // Set as destroyed - this._serverState = ReplSet.REPLSET_DESTROYED; - // Stop the ha - this._haProcess.stop(); - - // If we have a strategy stop it - if(this.strategyInstance) { - this.strategyInstance.stop(); - } - - // Kill all servers available - for(var name in this._state.addresses) { - this._state.addresses[name].close(); - } - - // Clean out the state - this._state = new ReplSetState(this); - - // Emit close event - processor(function() { - self._emitAcrossAllDbInstances(self, null, "close", null, null, true) - }); - - // Flush out any remaining call handlers - self._flushAllCallHandlers(utils.toError("Connection Closed By Application")); - - // Callback - if(typeof callback == 'function') - return callback(null, null); -} - -/** - * Creates a new server for the `replset` based on `host`. - * - * @param {String} host - host:port pair (localhost:27017) - * @param {ReplSet} replset - the ReplSet instance - * @return {Server} - * @ignore - */ -var createServer = function(self, host, options) { - // copy existing socket options to new server - var socketOptions = {} - if(options.socketOptions) { - var keys = Object.keys(options.socketOptions); - for(var k = 0; k < keys.length; k++) { - socketOptions[keys[k]] = options.socketOptions[keys[k]]; - } - } - - var parts = host.split(/:/); - if(1 === parts.length) { - parts[1] = Connection.DEFAULT_PORT; - } - - socketOptions.host = parts[0]; - socketOptions.port = parseInt(parts[1], 10); - - var serverOptions = { - readPreference: options.readPreference, - socketOptions: socketOptions, - poolSize: options.poolSize, - logger: options.logger, - auto_reconnect: false, - ssl: options.ssl, - sslValidate: options.sslValidate, - sslCA: options.sslCA, - sslCert: options.sslCert, - sslKey: options.sslKey, - sslPass: options.sslPass - } - - var server = new Server(socketOptions.host, socketOptions.port, serverOptions); - // Set up shared state - server._callBackStore = self._callBackStore; - server.replicasetInstance = self; - server.enableRecordQueryStats(self.recordQueryStats); - // Set up event handlers - server.on("close", _handler("close", self, server)); - server.on("error", _handler("error", self, server)); - server.on("timeout", _handler("timeout", self, server)); - return server; -} - -var _handler = function(event, self, server) { - return function(err, doc) { - // The event happened to a primary - // Remove it from play - if(self._state.isPrimary(server)) { - // Emit that the primary left the replicaset - self.emit('left', 'primary', server); - // Get the current master - var current_master = self._state.master; - self._state.master = null; - self._serverState = ReplSet.REPLSET_READ_ONLY; - - if(current_master != null) { - // Unpack variables - var host = current_master.socketOptions.host; - var port = current_master.socketOptions.port; - - // Fire error on any unknown callbacks - self.__executeAllServerSpecificErrorCallbacks(host, port, err); - } - } else if(self._state.isSecondary(server)) { - // Emit that a secondary left the replicaset - self.emit('left', 'secondary', server); - // Delete from the list - delete self._state.secondaries[server.name]; - } - - // If there is no more connections left and the setting is not destroyed - // set to disconnected - if(Object.keys(self._state.addresses).length == 0 - && self._serverState != ReplSet.REPLSET_DESTROYED) { - self._serverState = ReplSet.REPLSET_DISCONNECTED; - - // Emit close across all the attached db instances - self._dbStore.emit("close", new Error("replicaset disconnected, no valid servers contactable over tcp"), null, true); - } - - // Unpack variables - var host = server.socketOptions.host; - var port = server.socketOptions.port; - - // Fire error on any unknown callbacks - self.__executeAllServerSpecificErrorCallbacks(host, port, err); - } -} - -var locateNewServers = function(self, state, candidateServers, ismaster) { - // Retrieve the host - var hosts = ismaster.hosts; - // In candidate servers - var inCandidateServers = function(name, candidateServers) { - for(var i = 0; i < candidateServers.length; i++) { - if(candidateServers[i].name == name) return true; - } - - return false; - } - - // New servers - var newServers = []; - if(Array.isArray(hosts)) { - // Let's go over all the hosts - for(var i = 0; i < hosts.length; i++) { - if(!state.contains(hosts[i]) - && !inCandidateServers(hosts[i], candidateServers)) { - newServers.push(createServer(self, hosts[i], self.options)); - } - } - } - - // Return list of possible new servers - return newServers; -} - -var _connectHandler = function(self, candidateServers, instanceServer) { - return function(err, doc) { - // If we have an error add to the list - if(err) { - self._state.errors[instanceServer.name] = instanceServer; - } else { - delete self._state.errors[instanceServer.name]; - } - - if(!err) { - var ismaster = doc.documents[0] - - // Error the server if - if(!ismaster.ismaster - && !ismaster.secondary) { - self._state.errors[instanceServer.name] = instanceServer; - } - } - - - // No error let's analyse the ismaster command - if(!err && self._state.errors[instanceServer.name] == null) { - var ismaster = doc.documents[0] - - // If no replicaset name exists set the current one - if(self.options.rs_name == null) { - self.options.rs_name = ismaster.setName; - } - - // If we have a member that is not part of the set let's finish up - if(typeof ismaster.setName == 'string' && ismaster.setName != self.options.rs_name) { - return self.emit("connectionError", new Error("Replicaset name " + ismaster.setName + " does not match specified name " + self.options.rs_name)); - } - - // Add the error handlers - instanceServer.on("close", _handler("close", self, instanceServer)); - instanceServer.on("error", _handler("error", self, instanceServer)); - instanceServer.on("timeout", _handler("timeout", self, instanceServer)); - - // Set any tags on the instance server - instanceServer.name = ismaster.me; - instanceServer.tags = ismaster.tags; - - // Add the server to the list - self._state.addServer(instanceServer, ismaster); - - // Check if we have more servers to add (only check when done with initial set) - if(candidateServers.length == 0) { - // Get additional new servers that are not currently in set - var new_servers = locateNewServers(self, self._state, candidateServers, ismaster); - - // Locate any new servers that have not errored out yet - for(var i = 0; i < new_servers.length; i++) { - if(self._state.errors[new_servers[i].name] == null) { - candidateServers.push(new_servers[i]) - } - } - } - } - - // If the candidate server list is empty and no valid servers - if(candidateServers.length == 0 && - !self._state.hasValidServers()) { - return self.emit("connectionError", new Error("No valid replicaset instance servers found")); - } else if(candidateServers.length == 0) { - if(!self.options.connectWithNoPrimary && (self._state.master == null || !self._state.master.isConnected())) { - return self.emit("connectionError", new Error("No primary found in set")); - } - return self.emit("fullsetup", null, self.options.db, self); - } - - // Let's connect the next server - var nextServer = candidateServers.pop(); - - // Set up the options - var opts = { - returnIsMasterResults: true, - eventReceiver: nextServer - } - - // Attempt to connect to the server - nextServer.connect(self.options.db, opts, _connectHandler(self, candidateServers, nextServer)); - } -} - -ReplSet.prototype.isDestroyed = function() { - return this._serverState == ReplSet.REPLSET_DESTROYED; -} - -ReplSet.prototype.isConnected = function(read) { - var isConnected = false; - - if(read == null || read == ReadPreference.PRIMARY || read == false) - isConnected = this._state.master != null && this._state.master.isConnected(); - - if((read == ReadPreference.PRIMARY_PREFERRED || read == ReadPreference.SECONDARY_PREFERRED || read == ReadPreference.NEAREST) - && ((this._state.master != null && this._state.master.isConnected()) - || (this._state && this._state.secondaries && Object.keys(this._state.secondaries).length > 0))) { - isConnected = true; - } else if(read == ReadPreference.SECONDARY) { - isConnected = this._state && this._state.secondaries && Object.keys(this._state.secondaries).length > 0; - } - - // No valid connection return false - return isConnected; -} - -ReplSet.prototype.isMongos = function() { - return false; -} - -ReplSet.prototype.checkoutWriter = function() { - if(this._state.master) return this._state.master.checkoutWriter(); - return new Error("no writer connection available"); -} - -ReplSet.prototype.processIsMaster = function(_server, _ismaster) { - // Server in recovery mode, remove it from available servers - if(!_ismaster.ismaster && !_ismaster.secondary) { - // Locate the actual server - var server = this._state.addresses[_server.name]; - // Close the server, simulating the closing of the connection - // to get right removal semantics - if(server) server.close(); - // Execute any callback errors - _handler(null, this, server)(new Error("server is in recovery mode")); - } -} - -ReplSet.prototype.allRawConnections = function() { - var connections = []; - - for(var name in this._state.addresses) { - connections = connections.concat(this._state.addresses[name].allRawConnections()); - } - - return connections; -} - -/** - * @ignore - */ -ReplSet.prototype.allServerInstances = function() { - var self = this; - // If no state yet return empty - if(!self._state) return []; - // Close all the servers (concatenate entire list of servers first for ease) - var allServers = self._state.master != null ? [self._state.master] : []; - - // Secondary keys - var keys = Object.keys(self._state.secondaries); - // Add all secondaries - for(var i = 0; i < keys.length; i++) { - allServers.push(self._state.secondaries[keys[i]]); - } - - // Return complete list of all servers - return allServers; -} - -/** - * @ignore - */ -ReplSet.prototype.checkoutReader = function(readPreference, tags) { - var connection = null; - - // If we have a read preference object unpack it - if(typeof readPreference == 'object' && readPreference['_type'] == 'ReadPreference') { - // Validate if the object is using a valid mode - if(!readPreference.isValid()) throw new Error("Illegal readPreference mode specified, " + JSON.stringify(readPreference.mode)); - // Set the tag - tags = readPreference.tags; - readPreference = readPreference.mode; - } else if(typeof readPreference == 'object' && readPreference['_type'] != 'ReadPreference') { - return new Error("read preferences must be either a string or an instance of ReadPreference"); - } - - // Set up our read Preference, allowing us to override the readPreference - var finalReadPreference = readPreference != null ? readPreference : this.options.readPreference; - - // Ensure we unpack a reference - if(finalReadPreference != null && typeof finalReadPreference == 'object' && finalReadPreference['_type'] == 'ReadPreference') { - // Validate if the object is using a valid mode - if(!finalReadPreference.isValid()) throw new Error("Illegal readPreference mode specified, " + JSON.stringify(finalReadPreference.mode)); - // Set the tag - tags = finalReadPreference.tags; - readPreference = finalReadPreference.mode; - } - - // Finalize the read preference setup - finalReadPreference = finalReadPreference == true ? ReadPreference.SECONDARY_PREFERRED : finalReadPreference; - finalReadPreference = finalReadPreference == null ? ReadPreference.PRIMARY : finalReadPreference; - - // If we are reading from a primary - if(finalReadPreference == 'primary') { - // If we provide a tags set send an error - if(typeof tags == 'object' && tags != null) { - return new Error("PRIMARY cannot be combined with tags"); - } - - // If we provide a tags set send an error - if(this._state.master == null) { - return new Error("No replica set primary available for query with ReadPreference PRIMARY"); - } - - // Checkout a writer - return this.checkoutWriter(); - } - - // If we have specified to read from a secondary server grab a random one and read - // from it, otherwise just pass the primary connection - if((this.options.readSecondary || finalReadPreference == ReadPreference.SECONDARY_PREFERRED || finalReadPreference == ReadPreference.SECONDARY) && Object.keys(this._state.secondaries).length > 0) { - // If we have tags, look for servers matching the specific tag - if(this.strategyInstance != null) { - // Only pick from secondaries - var _secondaries = []; - for(var key in this._state.secondaries) { - _secondaries.push(this._state.secondaries[key]); - } - - if(finalReadPreference == ReadPreference.SECONDARY) { - // Check out the nearest from only the secondaries - connection = this.strategyInstance.checkoutConnection(tags, _secondaries); - } else { - connection = this.strategyInstance.checkoutConnection(tags, _secondaries); - // No candidate servers that match the tags, error - if(connection == null || connection instanceof Error) { - // No secondary server avilable, attemp to checkout a primary server - connection = this.checkoutWriter(); - // If no connection return an error - if(connection == null || connection instanceof Error) { - return new Error("No replica set members available for query"); - } - } - } - } else if(tags != null && typeof tags == 'object') { - // Get connection - connection = _pickFromTags(this, tags);// = function(self, readPreference, tags) { - // No candidate servers that match the tags, error - if(connection == null) { - return new Error("No replica set members available for query"); - } - } else { - connection = _roundRobin(this, tags); - } - } else if(finalReadPreference == ReadPreference.PRIMARY_PREFERRED) { - // Check if there is a primary available and return that if possible - connection = this.checkoutWriter(); - // If no connection available checkout a secondary - if(connection == null || connection instanceof Error) { - // If we have tags, look for servers matching the specific tag - if(tags != null && typeof tags == 'object') { - // Get connection - connection = _pickFromTags(this, tags);// = function(self, readPreference, tags) { - // No candidate servers that match the tags, error - if(connection == null) { - return new Error("No replica set members available for query"); - } - } else { - connection = _roundRobin(this, tags); - } - } - } else if(finalReadPreference == ReadPreference.SECONDARY_PREFERRED) { - // If we have tags, look for servers matching the specific tag - if(this.strategyInstance != null) { - connection = this.strategyInstance.checkoutConnection(tags); - - // No candidate servers that match the tags, error - if(connection == null || connection instanceof Error) { - // No secondary server avilable, attemp to checkout a primary server - connection = this.checkoutWriter(); - // If no connection return an error - if(connection == null || connection instanceof Error) { - var preferenceName = finalReadPreference == ReadPreference.SECONDARY ? 'secondary' : finalReadPreference; - return new Error("No replica set member available for query with ReadPreference " + preferenceName + " and tags " + JSON.stringify(tags)); - } - } - } else if(tags != null && typeof tags == 'object') { - // Get connection - connection = _pickFromTags(this, tags);// = function(self, readPreference, tags) { - // No candidate servers that match the tags, error - if(connection == null) { - // No secondary server avilable, attemp to checkout a primary server - connection = this.checkoutWriter(); - // If no connection return an error - if(connection == null || connection instanceof Error) { - var preferenceName = finalReadPreference == ReadPreference.SECONDARY ? 'secondary' : finalReadPreference; - return new Error("No replica set member available for query with ReadPreference " + preferenceName + " and tags " + JSON.stringify(tags)); - } - } - } - } else if(finalReadPreference == ReadPreference.NEAREST && this.strategyInstance != null) { - connection = this.strategyInstance.checkoutConnection(tags); - } else if(finalReadPreference == ReadPreference.NEAREST && this.strategyInstance == null) { - return new Error("A strategy for calculating nearness must be enabled such as ping or statistical"); - } else if(finalReadPreference == ReadPreference.SECONDARY && Object.keys(this._state.secondaries).length == 0) { - if(tags != null && typeof tags == 'object') { - var preferenceName = finalReadPreference == ReadPreference.SECONDARY ? 'secondary' : finalReadPreference; - return new Error("No replica set member available for query with ReadPreference " + preferenceName + " and tags " + JSON.stringify(tags)); - } else { - return new Error("No replica set secondary available for query with ReadPreference SECONDARY"); - } - } else { - connection = this.checkoutWriter(); - } - - // Return the connection - return connection; -} - -/** - * @ignore - */ -var _pickFromTags = function(self, tags) { - // If we have an array or single tag selection - var tagObjects = Array.isArray(tags) ? tags : [tags]; - // Iterate over all tags until we find a candidate server - for(var _i = 0; _i < tagObjects.length; _i++) { - // Grab a tag object - var tagObject = tagObjects[_i]; - // Matching keys - var matchingKeys = Object.keys(tagObject); - // Match all the servers that match the provdided tags - var keys = Object.keys(self._state.secondaries); - var candidateServers = []; - - for(var i = 0; i < keys.length; i++) { - var server = self._state.secondaries[keys[i]]; - // If we have tags match - if(server.tags != null) { - var matching = true; - // Ensure we have all the values - for(var j = 0; j < matchingKeys.length; j++) { - if(server.tags[matchingKeys[j]] != tagObject[matchingKeys[j]]) { - matching = false; - break; - } - } - - // If we have a match add it to the list of matching servers - if(matching) { - candidateServers.push(server); - } - } - } - - // If we have a candidate server return - if(candidateServers.length > 0) { - if(self.strategyInstance) return self.strategyInstance.checkoutConnection(tags, candidateServers); - // Set instance to return - return candidateServers[Math.floor(Math.random() * candidateServers.length)].checkoutReader(); - } - } - - // No connection found - return null; -} - -/** - * Pick a secondary using round robin - * - * @ignore - */ -function _roundRobin (replset, tags) { - var keys = Object.keys(replset._state.secondaries); - // Update index - replset._currentServerChoice = replset._currentServerChoice + 1; - // Pick a server - var key = keys[replset._currentServerChoice % keys.length]; - - var conn = null != replset._state.secondaries[key] - ? replset._state.secondaries[key].checkoutReader() - : null; - - // If connection is null fallback to first available secondary - if(null == conn) { - conn = pickFirstConnectedSecondary(replset, tags); - } - - return conn; -} - -/** - * @ignore - */ -var pickFirstConnectedSecondary = function pickFirstConnectedSecondary(self, tags) { - var keys = Object.keys(self._state.secondaries); - var connection; - - // Find first available reader if any - for(var i = 0; i < keys.length; i++) { - connection = self._state.secondaries[keys[i]].checkoutReader(); - if(connection) return connection; - } - - // If we still have a null, read from primary if it's not secondary only - if(self._readPreference == ReadPreference.SECONDARY_PREFERRED) { - connection = self._state.master.checkoutReader(); - if(connection) return connection; - } - - var preferenceName = self._readPreference == ReadPreference.SECONDARY_PREFERRED - ? 'secondary' - : self._readPreference; - - return new Error("No replica set member available for query with ReadPreference " - + preferenceName + " and tags " + JSON.stringify(tags)); -} - -/** - * Get list of secondaries - * @ignore - */ -Object.defineProperty(ReplSet.prototype, "secondaries", {enumerable: true - , get: function() { - return utils.objectToArray(this._state.secondaries); - } -}); - -/** - * Get list of secondaries - * @ignore - */ -Object.defineProperty(ReplSet.prototype, "arbiters", {enumerable: true - , get: function() { - return utils.objectToArray(this._state.arbiters); - } -}); - diff --git a/node_modules/mongodb/lib/mongodb/connection/repl_set/repl_set_state.js b/node_modules/mongodb/lib/mongodb/connection/repl_set/repl_set_state.js deleted file mode 100644 index 1fbd9c0..0000000 --- a/node_modules/mongodb/lib/mongodb/connection/repl_set/repl_set_state.js +++ /dev/null @@ -1,74 +0,0 @@ -/** - * Interval state object constructor - * - * @ignore - */ -var ReplSetState = function ReplSetState (replset) { - this.errorMessages = []; - this.secondaries = {}; - this.addresses = {}; - this.arbiters = {}; - this.passives = {}; - this.members = []; - this.errors = {}; - this.setName = null; - this.master = null; - this.replset = replset; -} - -ReplSetState.prototype.hasValidServers = function() { - var validServers = []; - if(this.master && this.master.isConnected()) return true; - - if(this.secondaries) { - var keys = Object.keys(this.secondaries) - for(var i = 0; i < keys.length; i++) { - if(this.secondaries[keys[i]].isConnected()) - return true; - } - } - - return false; -} - -ReplSetState.prototype.getAllReadServers = function() { - var candidate_servers = []; - for(var name in this.addresses) { - candidate_servers.push(this.addresses[name]); - } - - // Return all possible read candidates - return candidate_servers; -} - -ReplSetState.prototype.addServer = function(server, master) { - server.name = master.me; - - if(master.ismaster) { - this.master = server; - this.addresses[server.name] = server; - this.replset.emit('joined', "primary", master, server); - } else if(master.secondary) { - this.secondaries[server.name] = server; - this.addresses[server.name] = server; - this.replset.emit('joined', "secondary", master, server); - } else if(master.arbiters) { - this.arbiters[server.name] = server; - this.addresses[server.name] = server; - this.replset.emit('joined', "arbiter", master, server); - } -} - -ReplSetState.prototype.contains = function(host) { - return this.addresses[host] != null; -} - -ReplSetState.prototype.isPrimary = function(server) { - return this.master && this.master.name == server.name; -} - -ReplSetState.prototype.isSecondary = function(server) { - return this.secondaries[server.name] != null; -} - -exports.ReplSetState = ReplSetState; diff --git a/node_modules/mongodb/lib/mongodb/connection/repl_set/strategies/ping_strategy.js b/node_modules/mongodb/lib/mongodb/connection/repl_set/strategies/ping_strategy.js deleted file mode 100644 index 7e2a6c9..0000000 --- a/node_modules/mongodb/lib/mongodb/connection/repl_set/strategies/ping_strategy.js +++ /dev/null @@ -1,366 +0,0 @@ -var Server = require("../../server").Server - , format = require('util').format; - -// The ping strategy uses pings each server and records the -// elapsed time for the server so it can pick a server based on lowest -// return time for the db command {ping:true} -var PingStrategy = exports.PingStrategy = function(replicaset, secondaryAcceptableLatencyMS) { - this.replicaset = replicaset; - this.secondaryAcceptableLatencyMS = secondaryAcceptableLatencyMS; - this.state = 'disconnected'; - // Interval of ping attempts - this.pingInterval = replicaset.options.socketOptions.pingInterval || 5000; - // Timeout for ping response, default - no timeout - this.pingTimeout = replicaset.options.socketOptions.pingTimeout || null; - // Class instance - this.Db = require("../../../db").Db; - // Active db connections - this.dbs = {}; - // Current server index - this.index = 0; - // Logger api - this.Logger = null; -} - -// Starts any needed code -PingStrategy.prototype.start = function(callback) { - // already running? - if ('connected' == this.state) return; - - this.state = 'connected'; - - // Start ping server - this._pingServer(callback); -} - -// Stops and kills any processes running -PingStrategy.prototype.stop = function(callback) { - // Stop the ping process - this.state = 'disconnected'; - - // Stop all the server instances - for(var key in this.dbs) { - this.dbs[key].close(); - } - - // optional callback - callback && callback(null, null); -} - -PingStrategy.prototype.checkoutConnection = function(tags, secondaryCandidates) { - // Servers are picked based on the lowest ping time and then servers that lower than that + secondaryAcceptableLatencyMS - // Create a list of candidat servers, containing the primary if available - var candidateServers = []; - var self = this; - - // If we have not provided a list of candidate servers use the default setup - if(!Array.isArray(secondaryCandidates)) { - candidateServers = this.replicaset._state.master != null ? [this.replicaset._state.master] : []; - // Add all the secondaries - var keys = Object.keys(this.replicaset._state.secondaries); - for(var i = 0; i < keys.length; i++) { - candidateServers.push(this.replicaset._state.secondaries[keys[i]]) - } - } else { - candidateServers = secondaryCandidates; - } - - // Final list of eligable server - var finalCandidates = []; - - // If we have tags filter by tags - if(tags != null && typeof tags == 'object') { - // If we have an array or single tag selection - var tagObjects = Array.isArray(tags) ? tags : [tags]; - // Iterate over all tags until we find a candidate server - for(var _i = 0; _i < tagObjects.length; _i++) { - // Grab a tag object - var tagObject = tagObjects[_i]; - // Matching keys - var matchingKeys = Object.keys(tagObject); - // Remove any that are not tagged correctly - for(var i = 0; i < candidateServers.length; i++) { - var server = candidateServers[i]; - // If we have tags match - if(server.tags != null) { - var matching = true; - - // Ensure we have all the values - for(var j = 0; j < matchingKeys.length; j++) { - if(server.tags[matchingKeys[j]] != tagObject[matchingKeys[j]]) { - matching = false; - break; - } - } - - // If we have a match add it to the list of matching servers - if(matching) { - finalCandidates.push(server); - } - } - } - } - } else { - // Final array candidates - var finalCandidates = candidateServers; - } - - // Filter out any non-connected servers - finalCandidates = finalCandidates.filter(function(s) { - return s.isConnected(); - }) - - // Sort by ping time - finalCandidates.sort(function(a, b) { - return a.runtimeStats['pingMs'] > b.runtimeStats['pingMs']; - }); - - if(0 === finalCandidates.length) - return new Error("No replica set members available for query"); - - // find lowest server with a ping time - var lowest = finalCandidates.filter(function (server) { - return undefined != server.runtimeStats.pingMs; - })[0]; - - if(!lowest) { - lowest = finalCandidates[0]; - } - - // convert to integer - var lowestPing = lowest.runtimeStats.pingMs | 0; - - // determine acceptable latency - var acceptable = lowestPing + this.secondaryAcceptableLatencyMS; - - // remove any server responding slower than acceptable - var len = finalCandidates.length; - while(len--) { - if(finalCandidates[len].runtimeStats['pingMs'] > acceptable) { - finalCandidates.splice(len, 1); - } - } - - if(self.logger && self.logger.debug) { - self.logger.debug("Ping strategy selection order for tags", tags); - finalCandidates.forEach(function(c) { - self.logger.debug(format("%s:%s = %s ms", c.host, c.port, c.runtimeStats['pingMs']), null); - }) - } - - // If no candidates available return an error - if(finalCandidates.length == 0) - return new Error("No replica set members available for query"); - - // Ensure no we don't overflow - this.index = this.index % finalCandidates.length - // Pick a random acceptable server - var connection = finalCandidates[this.index].checkoutReader(); - // Point to next candidate (round robin style) - this.index = this.index + 1; - - if(self.logger && self.logger.debug) { - if(connection) - self.logger.debug(format("picked server %s:%s", connection.socketOptions.host, connection.socketOptions.port)); - } - - return connection; -} - -PingStrategy.prototype._pingServer = function(callback) { - var self = this; - - // Ping server function - var pingFunction = function() { - // Our state changed to disconnected or destroyed return - if(self.state == 'disconnected' || self.state == 'destroyed') return; - // If the replicaset is destroyed return - if(self.replicaset.isDestroyed() || self.replicaset._serverState == 'disconnected') return - - // Create a list of all servers we can send the ismaster command to - var allServers = self.replicaset._state.master != null ? [self.replicaset._state.master] : []; - - // Secondary keys - var keys = Object.keys(self.replicaset._state.secondaries); - // Add all secondaries - for(var i = 0; i < keys.length; i++) { - allServers.push(self.replicaset._state.secondaries[keys[i]]); - } - - // Number of server entries - var numberOfEntries = allServers.length; - - // We got keys - for(var i = 0; i < allServers.length; i++) { - - // We got a server instance - var server = allServers[i]; - - // Create a new server object, avoid using internal connections as they might - // be in an illegal state - new function(serverInstance) { - var _db = self.dbs[serverInstance.host + ":" + serverInstance.port]; - // If we have a db - if(_db != null) { - // Startup time of the command - var startTime = Date.now(); - - // Execute ping command in own scope - var _ping = function(__db, __serverInstance) { - - // Server unavailable. Checks only if pingTimeout defined & greater than 0 - var _failTimer = self.pingTimeout ? setTimeout(function () { - if(null != __serverInstance.runtimeStats && __serverInstance.isConnected()) { - __serverInstance.close(); - } - }, self.pingTimeout) : null; - - // Execute ping on this connection - __db.executeDbCommand({ping:1}, {failFast:true}, function(err) { - - // Server available - clearTimeout(_failTimer); - - // Emit the ping - self.replicaset.emit("ping", err, serverInstance); - - if(err) { - delete self.dbs[__db.serverConfig.host + ":" + __db.serverConfig.port]; - __db.close(); - return done(); - } - - if(null != __serverInstance.runtimeStats && __serverInstance.isConnected()) { - __serverInstance.runtimeStats['pingMs'] = Date.now() - startTime; - } - - __db.executeDbCommand({ismaster:1}, {failFast:true}, function(err, result) { - // Emit the ping - self.replicaset.emit("ping_ismaster", err, result, serverInstance); - - if(err) { - delete self.dbs[__db.serverConfig.host + ":" + __db.serverConfig.port]; - __db.close(); - return done(); - } - - // Process the ismaster for the server - if(result && result.documents && self.replicaset.processIsMaster) { - self.replicaset.processIsMaster(__serverInstance, result.documents[0]); - } - - // Done with the pinging - done(); - }); - }); - }; - // Ping - _ping(_db, serverInstance); - } else { - var connectTimeoutMS = self.replicaset.options.socketOptions - ? self.replicaset.options.socketOptions.connectTimeoutMS : 0 - - // Create a new master connection - var _server = new Server(serverInstance.host, serverInstance.port, { - auto_reconnect: false, - returnIsMasterResults: true, - slaveOk: true, - poolSize: 1, - socketOptions: { connectTimeoutMS: connectTimeoutMS }, - ssl: self.replicaset.options.ssl, - sslValidate: self.replicaset.options.sslValidate, - sslCA: self.replicaset.options.sslCA, - sslCert: self.replicaset.options.sslCert, - sslKey: self.replicaset.options.sslKey, - sslPass: self.replicaset.options.sslPass - }); - - // Create Db instance - var _db = new self.Db('local', _server, { safe: true }); - _db.on("close", function() { - delete self.dbs[this.serverConfig.host + ":" + this.serverConfig.port]; - }) - - var _ping = function(__db, __serverInstance) { - if(self.state == 'disconnected') { - self.stop(); - return; - } - - __db.open(function(err, db) { - // Emit ping connect - self.replicaset.emit("ping_connect", err, __serverInstance); - - if(self.state == 'disconnected' && __db != null) { - return __db.close(); - } - - if(err) { - delete self.dbs[__db.serverConfig.host + ":" + __db.serverConfig.port]; - __db.close(); - return done(); - } - - // Save instance - self.dbs[__db.serverConfig.host + ":" + __db.serverConfig.port] = __db; - - // Startup time of the command - var startTime = Date.now(); - - // Execute ping on this connection - __db.executeDbCommand({ping:1}, {failFast:true}, function(err) { - self.replicaset.emit("ping", err, __serverInstance); - - if(err) { - delete self.dbs[__db.serverConfig.host + ":" + __db.serverConfig.port]; - __db.close(); - return done(); - } - - if(null != __serverInstance.runtimeStats && __serverInstance.isConnected()) { - __serverInstance.runtimeStats['pingMs'] = Date.now() - startTime; - } - - __db.executeDbCommand({ismaster:1}, {failFast:true}, function(err, result) { - self.replicaset.emit("ping_ismaster", err, result, __serverInstance); - - if(err) { - delete self.dbs[__db.serverConfig.host + ":" + __db.serverConfig.port]; - __db.close(); - return done(); - } - - // Process the ismaster for the server - if(result && result.documents && self.replicaset.processIsMaster) { - self.replicaset.processIsMaster(__serverInstance, result.documents[0]); - } - - // Done with the pinging - done(); - }); - }); - }); - }; - - // Ping the server - _ping(_db, serverInstance); - } - - function done() { - // Adjust the number of checks - numberOfEntries--; - - // If we are done with all results coming back trigger ping again - if(0 === numberOfEntries && 'connected' == self.state) { - setTimeout(pingFunction, self.pingInterval); - } - } - }(server); - } - } - - // Start pingFunction - pingFunction(); - - callback && callback(null); -} diff --git a/node_modules/mongodb/lib/mongodb/connection/repl_set/strategies/statistics_strategy.js b/node_modules/mongodb/lib/mongodb/connection/repl_set/strategies/statistics_strategy.js deleted file mode 100644 index 32d23c3..0000000 --- a/node_modules/mongodb/lib/mongodb/connection/repl_set/strategies/statistics_strategy.js +++ /dev/null @@ -1,93 +0,0 @@ -// The Statistics strategy uses the measure of each end-start time for each -// query executed against the db to calculate the mean, variance and standard deviation -// and pick the server which the lowest mean and deviation -var StatisticsStrategy = exports.StatisticsStrategy = function(replicaset) { - this.replicaset = replicaset; - // Logger api - this.Logger = null; -} - -// Starts any needed code -StatisticsStrategy.prototype.start = function(callback) { - callback && callback(null, null); -} - -StatisticsStrategy.prototype.stop = function(callback) { - callback && callback(null, null); -} - -StatisticsStrategy.prototype.checkoutConnection = function(tags, secondaryCandidates) { - // Servers are picked based on the lowest ping time and then servers that lower than that + secondaryAcceptableLatencyMS - // Create a list of candidat servers, containing the primary if available - var candidateServers = []; - - // If we have not provided a list of candidate servers use the default setup - if(!Array.isArray(secondaryCandidates)) { - candidateServers = this.replicaset._state.master != null ? [this.replicaset._state.master] : []; - // Add all the secondaries - var keys = Object.keys(this.replicaset._state.secondaries); - for(var i = 0; i < keys.length; i++) { - candidateServers.push(this.replicaset._state.secondaries[keys[i]]) - } - } else { - candidateServers = secondaryCandidates; - } - - // Final list of eligable server - var finalCandidates = []; - - // If we have tags filter by tags - if(tags != null && typeof tags == 'object') { - // If we have an array or single tag selection - var tagObjects = Array.isArray(tags) ? tags : [tags]; - // Iterate over all tags until we find a candidate server - for(var _i = 0; _i < tagObjects.length; _i++) { - // Grab a tag object - var tagObject = tagObjects[_i]; - // Matching keys - var matchingKeys = Object.keys(tagObject); - // Remove any that are not tagged correctly - for(var i = 0; i < candidateServers.length; i++) { - var server = candidateServers[i]; - // If we have tags match - if(server.tags != null) { - var matching = true; - - // Ensure we have all the values - for(var j = 0; j < matchingKeys.length; j++) { - if(server.tags[matchingKeys[j]] != tagObject[matchingKeys[j]]) { - matching = false; - break; - } - } - - // If we have a match add it to the list of matching servers - if(matching) { - finalCandidates.push(server); - } - } - } - } - } else { - // Final array candidates - var finalCandidates = candidateServers; - } - - finalCandidates.sort(function(a, b) { - return a.runtimeStats.queryStats.sScore > b.runtimeStats.queryStats.sScore; - }); - - // If no candidates available return an error - if(finalCandidates.length == 0) return new Error("No replica set members available for query"); - - var bestCandidates = [finalCandidates[0]]; - for (var i = 1; i < finalCandidates.length; ++i) { - if (finalCandidates[i].runtimeStats.queryStats.sScore > finalCandidates[i - 1].runtimeStats.queryStats.sScore) { - break; - } else { - bestCandidates.push(finalCandidates[i]); - } - } - - return bestCandidates[Math.floor(Math.random() * bestCandidates.length)].checkoutReader(); -} diff --git a/node_modules/mongodb/lib/mongodb/connection/server.js b/node_modules/mongodb/lib/mongodb/connection/server.js deleted file mode 100644 index dfff183..0000000 --- a/node_modules/mongodb/lib/mongodb/connection/server.js +++ /dev/null @@ -1,945 +0,0 @@ -var Connection = require('./connection').Connection, - ReadPreference = require('./read_preference').ReadPreference, - DbCommand = require('../commands/db_command').DbCommand, - MongoReply = require('../responses/mongo_reply').MongoReply, - ConnectionPool = require('./connection_pool').ConnectionPool, - EventEmitter = require('events').EventEmitter, - ServerCapabilities = require('./server_capabilities').ServerCapabilities, - Base = require('./base').Base, - format = require('util').format, - utils = require('../utils'), - timers = require('timers'), - inherits = require('util').inherits; - -// Set processor, setImmediate if 0.10 otherwise nextTick -var processor = require('../utils').processor(); - -/** - * Class representing a single MongoDB Server connection - * - * Options - * - **ssl** {Boolean, default:false}, use ssl connection (needs to have a mongod server with ssl support) - * - **sslValidate** {Boolean, default:false}, validate mongod server certificate against ca (needs to have a mongod server with ssl support, 2.4 or higher) - * - **sslCA** {Array, default:null}, Array of valid certificates either as Buffers or Strings (needs to have a mongod server with ssl support, 2.4 or higher) - * - **sslCert** {Buffer/String, default:null}, String or buffer containing the certificate we wish to present (needs to have a mongod server with ssl support, 2.4 or higher) - * - **sslKey** {Buffer/String, default:null}, String or buffer containing the certificate private key we wish to present (needs to have a mongod server with ssl support, 2.4 or higher) - * - **sslPass** {Buffer/String, default:null}, String or buffer containing the certificate password (needs to have a mongod server with ssl support, 2.4 or higher) - * - **poolSize** {Number, default:5}, number of connections in the connection pool, set to 5 as default for legacy reasons. - * - **socketOptions** {Object, default:null}, an object containing socket options to use (noDelay:(boolean), keepAlive:(number), connectTimeoutMS:(number), socketTimeoutMS:(number)) - * - **logger** {Object, default:null}, an object representing a logger that you want to use, needs to support functions debug, log, error **({error:function(message, object) {}, log:function(message, object) {}, debug:function(message, object) {}})**. - * - **auto_reconnect** {Boolean, default:false}, reconnect on error. - * - **disableDriverBSONSizeCheck** {Boolean, default:false}, force the server to error if the BSON message is to big - * - * @class Represents a Server connection. - * @param {String} host the server host - * @param {Number} port the server port - * @param {Object} [options] optional options for insert command - */ -function Server(host, port, options) { - // Set up Server instance - if(!(this instanceof Server)) return new Server(host, port, options); - - // Set up event emitter - Base.call(this); - - // Ensure correct values - if(port != null && typeof port == 'object') { - options = port; - port = Connection.DEFAULT_PORT; - } - - var self = this; - this.host = host; - this.port = port; - this.options = options == null ? {} : options; - this.internalConnection; - this.internalMaster = false; - this.connected = false; - this.poolSize = this.options.poolSize == null ? 5 : this.options.poolSize; - this.disableDriverBSONSizeCheck = this.options.disableDriverBSONSizeCheck != null ? this.options.disableDriverBSONSizeCheck : false; - this._used = false; - this.replicasetInstance = null; - - // Emit open setup - this.emitOpen = this.options.emitOpen || true; - // Set ssl as connection method - this.ssl = this.options.ssl == null ? false : this.options.ssl; - // Set ssl validation - this.sslValidate = this.options.sslValidate == null ? false : this.options.sslValidate; - // Set the ssl certificate authority (array of Buffer/String keys) - this.sslCA = Array.isArray(this.options.sslCA) ? this.options.sslCA : null; - // Certificate to present to the server - this.sslCert = this.options.sslCert; - // Certificate private key if in separate file - this.sslKey = this.options.sslKey; - // Password to unlock private key - this.sslPass = this.options.sslPass; - // Server capabilities - this.serverCapabilities = null; - // Set server name - this.name = format("%s:%s", host, port); - - // Ensure we are not trying to validate with no list of certificates - if(this.sslValidate && (!Array.isArray(this.sslCA) || this.sslCA.length == 0)) { - throw new Error("The driver expects an Array of CA certificates in the sslCA parameter when enabling sslValidate"); - } - - // Contains the isMaster information returned from the server - this.isMasterDoc; - - // Set default connection pool options - this.socketOptions = this.options.socketOptions != null ? this.options.socketOptions : {}; - if(this.disableDriverBSONSizeCheck) this.socketOptions.disableDriverBSONSizeCheck = this.disableDriverBSONSizeCheck; - - // Set ssl up if it's defined - if(this.ssl) { - this.socketOptions.ssl = true; - // Set ssl validation - this.socketOptions.sslValidate = this.sslValidate == null ? false : this.sslValidate; - // Set the ssl certificate authority (array of Buffer/String keys) - this.socketOptions.sslCA = Array.isArray(this.sslCA) ? this.sslCA : null; - // Set certificate to present - this.socketOptions.sslCert = this.sslCert; - // Set certificate to present - this.socketOptions.sslKey = this.sslKey; - // Password to unlock private key - this.socketOptions.sslPass = this.sslPass; - } - - // Set up logger if any set - this.logger = this.options.logger != null - && (typeof this.options.logger.debug == 'function') - && (typeof this.options.logger.error == 'function') - && (typeof this.options.logger.log == 'function') - ? this.options.logger : {error:function(message, object) {}, log:function(message, object) {}, debug:function(message, object) {}}; - - // Just keeps list of events we allow - this.eventHandlers = {error:[], parseError:[], poolReady:[], message:[], close:[], timeout:[]}; - // Internal state of server connection - this._serverState = 'disconnected'; - // Contains state information about server connection - this._state = {'runtimeStats': {'queryStats':new RunningStats()}}; - // Do we record server stats or not - this.recordQueryStats = false; - - // Allow setting the socketTimeoutMS on all connections - // to work around issues such as secondaries blocking due to compaction - utils.setSocketTimeoutProperty(this, this.socketOptions); -}; - -/** - * @ignore - */ -inherits(Server, Base); - -// -// Deprecated, USE ReadPreferences class -// -Server.READ_PRIMARY = ReadPreference.PRIMARY; -Server.READ_SECONDARY = ReadPreference.SECONDARY_PREFERRED; -Server.READ_SECONDARY_ONLY = ReadPreference.SECONDARY; - -/** - * Always ourselves - * @ignore - */ -Server.prototype.setReadPreference = function(readPreference) { - this._readPreference = readPreference; -} - -/** - * @ignore - */ -Server.prototype.isMongos = function() { - return this.isMasterDoc != null && this.isMasterDoc['msg'] == "isdbgrid" ? true : false; -} - -/** - * @ignore - */ -Server.prototype._isUsed = function() { - return this._used; -} - -/** - * @ignore - */ -Server.prototype.close = function(callback) { - // Set server status as disconnected - this._serverState = 'destroyed'; - // Remove all local listeners - this.removeAllListeners(); - - if(this.connectionPool != null) { - // Remove all the listeners on the pool so it does not fire messages all over the place - this.connectionPool.removeAllEventListeners(); - // Close the connection if it's open - this.connectionPool.stop(true); - } - - // Emit close event - if(this.db && !this.isSetMember()) { - var self = this; - processor(function() { - self._emitAcrossAllDbInstances(self, null, "close", null, null, true) - }) - - // Flush out any remaining call handlers - self._flushAllCallHandlers(utils.toError("Connection Closed By Application")); - } - - // Peform callback if present - if(typeof callback === 'function') callback(null); -}; - -Server.prototype.isDestroyed = function() { - return this._serverState == 'destroyed'; -} - -/** - * @ignore - */ -Server.prototype.isConnected = function() { - return this.connectionPool != null && this.connectionPool.isConnected(); -} - -/** - * @ignore - */ -Server.prototype.canWrite = Server.prototype.isConnected; -Server.prototype.canRead = Server.prototype.isConnected; - -Server.prototype.isAutoReconnect = function() { - if(this.isSetMember()) return false; - return this.options.auto_reconnect != null ? this.options.auto_reconnect : true; -} - -/** - * @ignore - */ -Server.prototype.allServerInstances = function() { - return [this]; -} - -/** - * @ignore - */ -Server.prototype.isSetMember = function() { - return this.replicasetInstance != null || this.mongosInstance != null; -} - -/** - * @ignore - */ -Server.prototype.setSocketOptions = function(options) { - var connections = this.allRawConnections(); - for(var i = 0; i < connections.length; i++) { - connections[i].setSocketOptions(options); - } -} - -/** - * Assigns a replica set to this `server`. - * - * @param {ReplSet} replset - * @ignore - */ -Server.prototype.assignReplicaSet = function (replset) { - this.replicasetInstance = replset; - this.inheritReplSetOptionsFrom(replset); - this.enableRecordQueryStats(replset.recordQueryStats); -} - -/** - * Takes needed options from `replset` and overwrites - * our own options. - * - * @param {ReplSet} replset - * @ignore - */ -Server.prototype.inheritReplSetOptionsFrom = function (replset) { - this.socketOptions = {}; - this.socketOptions.connectTimeoutMS = replset.options.socketOptions.connectTimeoutMS || 30000; - - if(replset.options.ssl) { - // Set ssl on - this.socketOptions.ssl = true; - // Set ssl validation - this.socketOptions.sslValidate = replset.options.sslValidate == null ? false : replset.options.sslValidate; - // Set the ssl certificate authority (array of Buffer/String keys) - this.socketOptions.sslCA = Array.isArray(replset.options.sslCA) ? replset.options.sslCA : null; - // Set certificate to present - this.socketOptions.sslCert = replset.options.sslCert; - // Set certificate to present - this.socketOptions.sslKey = replset.options.sslKey; - // Password to unlock private key - this.socketOptions.sslPass = replset.options.sslPass; - } - - // If a socket option object exists clone it - if(utils.isObject(replset.options.socketOptions)) { - var keys = Object.keys(replset.options.socketOptions); - for(var i = 0; i < keys.length; i++) - this.socketOptions[keys[i]] = replset.options.socketOptions[keys[i]]; - } -} - -/** - * Opens this server connection. - * - * @ignore - */ -Server.prototype.connect = function(dbInstance, options, callback) { - if('function' === typeof options) callback = options, options = {}; - if(options == null) options = {}; - if(!('function' === typeof callback)) callback = null; - var self = this; - // Save the options - this.options = options; - - // Currently needed to work around problems with multiple connections in a pool with ssl - // TODO fix if possible - if(this.ssl == true) { - // Set up socket options for ssl - this.socketOptions.ssl = true; - // Set ssl validation - this.socketOptions.sslValidate = this.sslValidate == null ? false : this.sslValidate; - // Set the ssl certificate authority (array of Buffer/String keys) - this.socketOptions.sslCA = Array.isArray(this.sslCA) ? this.sslCA : null; - // Set certificate to present - this.socketOptions.sslCert = this.sslCert; - // Set certificate to present - this.socketOptions.sslKey = this.sslKey; - // Password to unlock private key - this.socketOptions.sslPass = this.sslPass; - } - - // Let's connect - var server = this; - // Let's us override the main receiver of events - var eventReceiver = options.eventReceiver != null ? options.eventReceiver : this; - // Save reference to dbInstance - this.db = dbInstance; // `db` property matches ReplSet and Mongos - this.dbInstances = [dbInstance]; - - // Force connection pool if there is one - if(server.connectionPool) server.connectionPool.stop(); - // Set server state to connecting - this._serverState = 'connecting'; - - if(server.connectionPool != null) { - // Remove all the listeners on the pool so it does not fire messages all over the place - this.connectionPool.removeAllEventListeners(); - // Close the connection if it's open - this.connectionPool.stop(true); - } - - this.connectionPool = new ConnectionPool(this.host, this.port, this.poolSize, dbInstance.bson, this.socketOptions); - var connectionPool = this.connectionPool; - // If ssl is not enabled don't wait between the pool connections - if(this.ssl == null || !this.ssl) connectionPool._timeToWait = null; - // Set logger on pool - connectionPool.logger = this.logger; - connectionPool.bson = dbInstance.bson; - - // Set basic parameters passed in - var returnIsMasterResults = options.returnIsMasterResults == null ? false : options.returnIsMasterResults; - - // Create a default connect handler, overriden when using replicasets - var connectCallback = function(_server) { - return function(err, reply) { - // ensure no callbacks get called twice - var internalCallback = callback; - callback = null; - - // Assign the server - _server = _server != null ? _server : server; - - // If something close down the connection and removed the callback before - // proxy killed connection etc, ignore the erorr as close event was isssued - if(err != null && internalCallback == null) return; - // Internal callback - if(err != null) return internalCallback(err, null, _server); - _server.master = reply.documents[0].ismaster == 1 ? true : false; - _server.connectionPool.setMaxBsonSize(reply.documents[0].maxBsonObjectSize); - _server.connectionPool.setMaxMessageSizeBytes(reply.documents[0].maxMessageSizeBytes); - _server.connectionPool.setMaxWriteBatchSize(reply.documents[0].maxWriteBatchSize); - // Set server state to connEcted - _server._serverState = 'connected'; - // Set server as connected - _server.connected = true; - // Save document returned so we can query it - _server.isMasterDoc = reply.documents[0]; - - if(self.emitOpen) { - _server._emitAcrossAllDbInstances(_server, eventReceiver, "open", null, returnIsMasterResults ? reply : null, null); - self.emitOpen = false; - } else { - _server._emitAcrossAllDbInstances(_server, eventReceiver, "reconnect", null, returnIsMasterResults ? reply : null, null); - } - - // Set server capabilities - server.serverCapabilities = new ServerCapabilities(_server.isMasterDoc); - - // If we have it set to returnIsMasterResults - if(returnIsMasterResults) { - internalCallback(null, reply, _server); - } else { - internalCallback(null, dbInstance, _server); - } - } - }; - - // Let's us override the main connect callback - var connectHandler = options.connectHandler == null ? connectCallback(server) : options.connectHandler; - - // Set up on connect method - connectionPool.on("poolReady", function() { - // Create db command and Add the callback to the list of callbacks by the request id (mapping outgoing messages to correct callbacks) - var db_command = DbCommand.NcreateIsMasterCommand(dbInstance, dbInstance.databaseName); - // Check out a reader from the pool - var connection = connectionPool.checkoutConnection(); - // Register handler for messages - server._registerHandler(db_command, false, connection, connectHandler); - // Write the command out - connection.write(db_command); - }) - - // Set up item connection - connectionPool.on("message", function(message) { - // Attempt to parse the message - try { - // Create a new mongo reply - var mongoReply = new MongoReply() - // Parse the header - mongoReply.parseHeader(message, connectionPool.bson) - - // If message size is not the same as the buffer size - // something went terribly wrong somewhere - if(mongoReply.messageLength != message.length) { - // Emit the error - if(eventReceiver.listeners("error") && eventReceiver.listeners("error").length > 0) eventReceiver.emit("error", new Error("bson length is different from message length"), server); - // Remove all listeners - server.removeAllListeners(); - } else { - var startDate = new Date().getTime(); - - // Callback instance - var callbackInfo = server._findHandler(mongoReply.responseTo.toString()); - // Abort if not a valid callbackInfo, don't try to call it - if(callbackInfo == null || callbackInfo.info == null) return; - - // The command executed another request, log the handler again under that request id - if(mongoReply.requestId > 0 && mongoReply.cursorId.toString() != "0" - && callbackInfo && callbackInfo.info && callbackInfo.info.exhaust) { - server._reRegisterHandler(mongoReply.requestId, callbackInfo); - } - - // Parse the body - mongoReply.parseBody(message, connectionPool.bson, callbackInfo.info.raw, function(err) { - if(err != null) { - // If pool connection is already closed - if(server._serverState === 'disconnected') return; - // Set server state to disconnected - server._serverState = 'disconnected'; - // Remove all listeners and close the connection pool - server.removeAllListeners(); - connectionPool.stop(true); - - // If we have a callback return the error - if(typeof callback === 'function') { - // ensure no callbacks get called twice - var internalCallback = callback; - callback = null; - // Perform callback - internalCallback(err, null, server); - } else if(server.isSetMember()) { - if(server.listeners("parseError") && server.listeners("parseError").length > 0) server.emit("parseError", utils.toError(err), server); - } else { - if(eventReceiver.listeners("parseError") && eventReceiver.listeners("parseError").length > 0) eventReceiver.emit("parseError", utils.toError(err), server); - } - - // If we are a single server connection fire errors correctly - if(!server.isSetMember()) { - // Fire all callback errors - server.__executeAllCallbacksWithError(err); - // Emit error - server._emitAcrossAllDbInstances(server, eventReceiver, "parseError", server, null, true); - } - // Short cut - return; - } - - // Let's record the stats info if it's enabled - if(server.recordQueryStats == true && server._state['runtimeStats'] != null - && server._state.runtimeStats['queryStats'] instanceof RunningStats) { - // Add data point to the running statistics object - server._state.runtimeStats.queryStats.push(new Date().getTime() - callbackInfo.info.start); - } - - // Dispatch the call - server._callHandler(mongoReply.responseTo, mongoReply, null); - - // If we have an error about the server not being master or primary - if((mongoReply.responseFlag & (1 << 1)) != 0 - && mongoReply.documents[0].code - && mongoReply.documents[0].code == 13436) { - server.close(); - } - }); - } - } catch (err) { - // Throw error in next tick - processor(function() { - throw err; - }) - } - }); - - // Handle timeout - connectionPool.on("timeout", function(err) { - // If pool connection is already closed - if(server._serverState === 'disconnected' - || server._serverState === 'destroyed') return; - // Set server state to disconnected - server._serverState = 'disconnected'; - // If we have a callback return the error - if(typeof callback === 'function') { - // ensure no callbacks get called twice - var internalCallback = callback; - callback = null; - // Perform callback - internalCallback(err, null, server); - } else if(server.isSetMember()) { - if(server.listeners("timeout") && server.listeners("timeout").length > 0) server.emit("timeout", err, server); - } else { - if(eventReceiver.listeners("timeout") && eventReceiver.listeners("timeout").length > 0) eventReceiver.emit("timeout", err, server); - } - - // If we are a single server connection fire errors correctly - if(!server.isSetMember()) { - // Fire all callback errors - server.__executeAllCallbacksWithError(err); - // Emit error - server._emitAcrossAllDbInstances(server, eventReceiver, "timeout", err, server, true); - } - - // If we have autoConnect enabled let's fire up an attempt to reconnect - if(server.isAutoReconnect() - && !server.isSetMember() - && (server._serverState != 'destroyed') - && !server._reconnectInProgreess) { - // Set the number of retries - server._reconnect_retries = server.db.numberOfRetries; - // Attempt reconnect - server._reconnectInProgreess = true; - setTimeout(__attemptReconnect(server), server.db.retryMiliSeconds); - } - }); - - // Handle errors - connectionPool.on("error", function(message, connection, error_options) { - // If pool connection is already closed - if(server._serverState === 'disconnected' - || server._serverState === 'destroyed') return; - - // Set server state to disconnected - server._serverState = 'disconnected'; - // Error message - var error_message = new Error(message && message.err ? message.err : message); - // Error message coming from ssl - if(error_options && error_options.ssl) error_message.ssl = true; - - // If we have a callback return the error - if(typeof callback === 'function') { - // ensure no callbacks get called twice - var internalCallback = callback; - callback = null; - // Perform callback - internalCallback(error_message, null, server); - } else if(server.isSetMember()) { - if(server.listeners("error") && server.listeners("error").length > 0) server.emit("error", error_message, server); - } else { - if(eventReceiver.listeners("error") && eventReceiver.listeners("error").length > 0) eventReceiver.emit("error", error_message, server); - } - - // If we are a single server connection fire errors correctly - if(!server.isSetMember()) { - // Fire all callback errors - server.__executeAllCallbacksWithError(error_message); - // Emit error - server._emitAcrossAllDbInstances(server, eventReceiver, "error", error_message, server, true); - } - - // If we have autoConnect enabled let's fire up an attempt to reconnect - if(server.isAutoReconnect() - && !server.isSetMember() - && (server._serverState != 'destroyed') - && !server._reconnectInProgreess) { - - // Set the number of retries - server._reconnect_retries = server.db.numberOfRetries; - // Attempt reconnect - server._reconnectInProgreess = true; - setTimeout(__attemptReconnect(server), server.db.retryMiliSeconds); - } - }); - - // Handle close events - connectionPool.on("close", function() { - // If pool connection is already closed - if(server._serverState === 'disconnected' - || server._serverState === 'destroyed') return; - // Set server state to disconnected - server._serverState = 'disconnected'; - // If we have a callback return the error - if(typeof callback == 'function') { - // ensure no callbacks get called twice - var internalCallback = callback; - callback = null; - // Perform callback - internalCallback(new Error("connection closed"), null, server); - } else if(server.isSetMember()) { - if(server.listeners("close") && server.listeners("close").length > 0) server.emit("close", new Error("connection closed"), server); - } else { - if(eventReceiver.listeners("close") && eventReceiver.listeners("close").length > 0) eventReceiver.emit("close", new Error("connection closed"), server); - } - - // If we are a single server connection fire errors correctly - if(!server.isSetMember()) { - // Fire all callback errors - server.__executeAllCallbacksWithError(new Error("connection closed")); - // Emit error - server._emitAcrossAllDbInstances(server, eventReceiver, "close", server, null, true); - } - - // If we have autoConnect enabled let's fire up an attempt to reconnect - if(server.isAutoReconnect() - && !server.isSetMember() - && (server._serverState != 'destroyed') - && !server._reconnectInProgreess) { - - // Set the number of retries - server._reconnect_retries = server.db.numberOfRetries; - // Attempt reconnect - server._reconnectInProgreess = true; - setTimeout(__attemptReconnect(server), server.db.retryMiliSeconds); - } - }); - - /** - * @ignore - */ - var __attemptReconnect = function(server) { - return function() { - // Attempt reconnect - server.connect(server.db, server.options, function(err, result) { - server._reconnect_retries = server._reconnect_retries - 1; - - if(err) { - // Retry - if(server._reconnect_retries == 0 || server._serverState == 'destroyed') { - server._serverState = 'connected'; - server._reconnectInProgreess = false - // Fire all callback errors - return server.__executeAllCallbacksWithError(new Error("failed to reconnect to server")); - } else { - return setTimeout(__attemptReconnect(server), server.db.retryMiliSeconds); - } - } else { - // Set as authenticating (isConnected will be false) - server._serverState = 'authenticating'; - // Apply any auths, we don't try to catch any errors here - // as there are nowhere to simply propagate them to - self._apply_auths(server.db, function(err, result) { - server._serverState = 'connected'; - server._reconnectInProgreess = false; - - // Execute any buffered reads and writes - server._commandsStore.execute_queries(); - server._commandsStore.execute_writes(); - // Emit reconnect event - server.emit('reconnect'); - }); - } - }); - } - } - - // If we have a parser error we are in an unknown state, close everything and emit - // error - connectionPool.on("parseError", function(err) { - // If pool connection is already closed - if(server._serverState === 'disconnected' - || server._serverState === 'destroyed') return; - // Set server state to disconnected - server._serverState = 'disconnected'; - // If we have a callback return the error - if(typeof callback === 'function') { - // ensure no callbacks get called twice - var internalCallback = callback; - callback = null; - // Perform callback - internalCallback(utils.toError(err), null, server); - } else if(server.isSetMember()) { - if(server.listeners("parseError") && server.listeners("parseError").length > 0) server.emit("parseError", utils.toError(err), server); - } else { - if(eventReceiver.listeners("parseError") && eventReceiver.listeners("parseError").length > 0) eventReceiver.emit("parseError", utils.toError(err), server); - } - - // If we are a single server connection fire errors correctly - if(!server.isSetMember()) { - // Fire all callback errors - server.__executeAllCallbacksWithError(utils.toError(err)); - // Emit error - server._emitAcrossAllDbInstances(server, eventReceiver, "parseError", server, null, true); - // Emit close event - if(eventReceiver.listeners("close") && eventReceiver.listeners("close").length > 0) eventReceiver.emit("close", new Error("connection closed"), server); } - }); - - // Boot up connection poole, pass in a locator of callbacks - connectionPool.start(); -} - -/** - * @ignore - */ -Server.prototype.allRawConnections = function() { - return this.connectionPool != null ? this.connectionPool.getAllConnections() : []; -} - -/** - * Check if a writer can be provided - * @ignore - */ -var canCheckoutWriter = function(self, read) { - // We cannot write to an arbiter or secondary server - if(self.isMasterDoc && self.isMasterDoc['arbiterOnly'] == true) { - return new Error("Cannot write to an arbiter"); - } if(self.isMasterDoc && self.isMasterDoc['secondary'] == true) { - return new Error("Cannot write to a secondary"); - } else if(read == true && self._readPreference == ReadPreference.SECONDARY && self.isMasterDoc && self.isMasterDoc['ismaster'] == true) { - return new Error("Cannot read from primary when secondary only specified"); - } else if(!self.isMasterDoc) { - return new Error("Cannot determine state of server"); - } - - // Return no error - return null; -} - -/** - * @ignore - */ -Server.prototype.checkoutWriter = function(read) { - if(this._serverState == 'disconnected' || this._serverState == 'destroyed') - return null; - if(read == true) return this.connectionPool.checkoutConnection(); - // Check if are allowed to do a checkout (if we try to use an arbiter f.ex) - var result = canCheckoutWriter(this, read); - // If the result is null check out a writer - if(result == null && this.connectionPool != null) { - var connection = this.connectionPool.checkoutConnection(); - // Add server capabilities to the connection - if(connection) - connection.serverCapabilities = this.serverCapabilities; - return connection; - } else if(result == null) { - return null; - } else { - return result; - } -} - -/** - * Check if a reader can be provided - * @ignore - */ -var canCheckoutReader = function(self) { - // We cannot write to an arbiter or secondary server - if(self.isMasterDoc && self.isMasterDoc['arbiterOnly'] == true && self.isSetMember()) { - return new Error("Cannot write to an arbiter"); - } else if(self._readPreference != null) { - // If the read preference is Primary and the instance is not a master return an error - if((self._readPreference == ReadPreference.PRIMARY) && self.isMasterDoc && self.isMasterDoc['ismaster'] != true) { - return new Error("Read preference is Server.PRIMARY and server is not master"); - } else if(self._readPreference == ReadPreference.SECONDARY && self.isMasterDoc && self.isMasterDoc['ismaster'] == true) { - return new Error("Cannot read from primary when secondary only specified"); - } - } else if(!self.isMasterDoc) { - return new Error("Cannot determine state of server"); - } - - // Return no error - return null; -} - -/** - * @ignore - */ -Server.prototype.checkoutReader = function(read) { - if(this._serverState == 'disconnected' || this._serverState == 'destroyed') - return null; - // Check if are allowed to do a checkout (if we try to use an arbiter f.ex) - var result = canCheckoutReader(this); - // If the result is null check out a writer - if(result == null && this.connectionPool != null) { - var connection = this.connectionPool.checkoutConnection(); - // Add server capabilities to the connection - if(connection) - connection.serverCapabilities = this.serverCapabilities; - return connection; - } else if(result == null) { - return null; - } else { - return result; - } -} - -/** - * @ignore - */ -Server.prototype.enableRecordQueryStats = function(enable) { - this.recordQueryStats = enable; -} - -/** - * Internal statistics object used for calculating average and standard devitation on - * running queries - * @ignore - */ -var RunningStats = function() { - var self = this; - this.m_n = 0; - this.m_oldM = 0.0; - this.m_oldS = 0.0; - this.m_newM = 0.0; - this.m_newS = 0.0; - - // Define getters - Object.defineProperty(this, "numDataValues", { enumerable: true - , get: function () { return this.m_n; } - }); - - Object.defineProperty(this, "mean", { enumerable: true - , get: function () { return (this.m_n > 0) ? this.m_newM : 0.0; } - }); - - Object.defineProperty(this, "variance", { enumerable: true - , get: function () { return ((this.m_n > 1) ? this.m_newS/(this.m_n - 1) : 0.0); } - }); - - Object.defineProperty(this, "standardDeviation", { enumerable: true - , get: function () { return Math.sqrt(this.variance); } - }); - - Object.defineProperty(this, "sScore", { enumerable: true - , get: function () { - var bottom = this.mean + this.standardDeviation; - if(bottom == 0) return 0; - return ((2 * this.mean * this.standardDeviation)/(bottom)); - } - }); -} - -/** - * @ignore - */ -RunningStats.prototype.push = function(x) { - // Update the number of samples - this.m_n = this.m_n + 1; - - // See Knuth TAOCP vol 2, 3rd edition, page 232 - if(this.m_n == 1) { - this.m_oldM = this.m_newM = x; - this.m_oldS = 0.0; - } else { - this.m_newM = this.m_oldM + (x - this.m_oldM) / this.m_n; - this.m_newS = this.m_oldS + (x - this.m_oldM) * (x - this.m_newM); - // set up for next iteration - this.m_oldM = this.m_newM; - this.m_oldS = this.m_newS; - } -} - -/** - * @ignore - */ -Object.defineProperty(Server.prototype, "autoReconnect", { enumerable: true - , get: function () { - return this.options['auto_reconnect'] == null ? false : this.options['auto_reconnect']; - } -}); - -/** - * @ignore - */ -Object.defineProperty(Server.prototype, "connection", { enumerable: true - , get: function () { - return this.internalConnection; - } - , set: function(connection) { - this.internalConnection = connection; - } -}); - -/** - * @ignore - */ -Object.defineProperty(Server.prototype, "master", { enumerable: true - , get: function () { - return this.internalMaster; - } - , set: function(value) { - this.internalMaster = value; - } -}); - -/** - * @ignore - */ -Object.defineProperty(Server.prototype, "primary", { enumerable: true - , get: function () { - return this; - } -}); - -/** - * Getter for query Stats - * @ignore - */ -Object.defineProperty(Server.prototype, "queryStats", { enumerable: true - , get: function () { - return this._state.runtimeStats.queryStats; - } -}); - -/** - * @ignore - */ -Object.defineProperty(Server.prototype, "runtimeStats", { enumerable: true - , get: function () { - return this._state.runtimeStats; - } -}); - -/** - * Get Read Preference method - * @ignore - */ -Object.defineProperty(Server.prototype, "readPreference", { enumerable: true - , get: function () { - if(this._readPreference == null && this.readSecondary) { - return Server.READ_SECONDARY; - } else if(this._readPreference == null && !this.readSecondary) { - return Server.READ_PRIMARY; - } else { - return this._readPreference; - } - } -}); - -/** - * @ignore - */ -exports.Server = Server; diff --git a/node_modules/mongodb/lib/mongodb/connection/server_capabilities.js b/node_modules/mongodb/lib/mongodb/connection/server_capabilities.js deleted file mode 100644 index 68d42ea..0000000 --- a/node_modules/mongodb/lib/mongodb/connection/server_capabilities.js +++ /dev/null @@ -1,48 +0,0 @@ -var ServerCapabilities = function(isMasterResult) { - // Capabilities - var aggregationCursor = false; - var writeCommands = false; - var textSearch = false; - var authCommands = false; - var maxNumberOfDocsInBatch = isMasterResult.maxWriteBatchSize || 1000; - - if(isMasterResult.minWireVersion >= 0) { - textSearch = true; - } - - if(isMasterResult.maxWireVersion >= 1) { - aggregationCursor = true; - authCommands = true; - } - - if(isMasterResult.maxWireVersion >= 2) { - writeCommands = true; - } - - // If no min or max wire version set to 0 - if(isMasterResult.minWireVersion == null) { - isMasterResult.minWireVersion = 0; - } - - if(isMasterResult.maxWireVersion == null) { - isMasterResult.maxWireVersion = 0; - } - - // Map up read only parameters - setup_get_property(this, "hasAggregationCursor", aggregationCursor); - setup_get_property(this, "hasWriteCommands", writeCommands); - setup_get_property(this, "hasTextSearch", textSearch); - setup_get_property(this, "hasAuthCommands", authCommands); - setup_get_property(this, "minWireVersion", isMasterResult.minWireVersion); - setup_get_property(this, "maxWireVersion", isMasterResult.maxWireVersion); - setup_get_property(this, "maxNumberOfDocsInBatch", maxNumberOfDocsInBatch); -} - -var setup_get_property = function(object, name, value) { - Object.defineProperty(object, name, { - enumerable: true - , get: function () { return value; } - }); -} - -exports.ServerCapabilities = ServerCapabilities; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/connection/url_parser.js b/node_modules/mongodb/lib/mongodb/connection/url_parser.js deleted file mode 100644 index 4db9579..0000000 --- a/node_modules/mongodb/lib/mongodb/connection/url_parser.js +++ /dev/null @@ -1,265 +0,0 @@ -var fs = require('fs'), - ReadPreference = require('./read_preference').ReadPreference; - -exports.parse = function(url, options) { - // Ensure we have a default options object if none set - options = options || {}; - // Variables - var connection_part = ''; - var auth_part = ''; - var query_string_part = ''; - var dbName = 'admin'; - - // Must start with mongodb - if(url.indexOf("mongodb://") != 0) - throw Error("URL must be in the format mongodb://user:pass@host:port/dbname"); - // If we have a ? mark cut the query elements off - if(url.indexOf("?") != -1) { - query_string_part = url.substr(url.indexOf("?") + 1); - connection_part = url.substring("mongodb://".length, url.indexOf("?")) - } else { - connection_part = url.substring("mongodb://".length); - } - - // Check if we have auth params - if(connection_part.indexOf("@") != -1) { - auth_part = connection_part.split("@")[0]; - connection_part = connection_part.split("@")[1]; - } - - // Check if the connection string has a db - if(connection_part.indexOf(".sock") != -1) { - if(connection_part.indexOf(".sock/") != -1) { - dbName = connection_part.split(".sock/")[1]; - connection_part = connection_part.split("/", connection_part.indexOf(".sock") + ".sock".length); - } - } else if(connection_part.indexOf("/") != -1) { - dbName = connection_part.split("/")[1]; - connection_part = connection_part.split("/")[0]; - } - - // Result object - var object = {}; - - // Pick apart the authentication part of the string - var authPart = auth_part || ''; - var auth = authPart.split(':', 2); - if(options['uri_decode_auth']){ - auth[0] = decodeURIComponent(auth[0]); - if(auth[1]){ - auth[1] = decodeURIComponent(auth[1]); - } - } - - // Add auth to final object if we have 2 elements - if(auth.length == 2) object.auth = {user: auth[0], password: auth[1]}; - - // Variables used for temporary storage - var hostPart; - var urlOptions; - var servers; - var serverOptions = {socketOptions: {}}; - var dbOptions = {read_preference_tags: []}; - var replSetServersOptions = {socketOptions: {}}; - // Add server options to final object - object.server_options = serverOptions; - object.db_options = dbOptions; - object.rs_options = replSetServersOptions; - object.mongos_options = {}; - - // Let's check if we are using a domain socket - if(url.match(/\.sock/)) { - // Split out the socket part - var domainSocket = url.substring( - url.indexOf("mongodb://") + "mongodb://".length - , url.lastIndexOf(".sock") + ".sock".length); - // Clean out any auth stuff if any - if(domainSocket.indexOf("@") != -1) domainSocket = domainSocket.split("@")[1]; - servers = [{domain_socket: domainSocket}]; - } else { - // Split up the db - hostPart = connection_part; - // Parse all server results - servers = hostPart.split(',').map(function(h) { - var _host, _port, ipv6match; - //check if it matches [IPv6]:port, where the port number is optional - if ((ipv6match = /\[([^\]]+)\](?:\:(.+))?/.exec(h))) { - _host = ipv6match[1]; - _port = parseInt(ipv6match[2], 10) || 27017; - } else { - //otherwise assume it's IPv4, or plain hostname - var hostPort = h.split(':', 2); - _host = hostPort[0] || 'localhost'; - _port = hostPort[1] != null ? parseInt(hostPort[1], 10) : 27017; - // Check for localhost?safe=true style case - if(_host.indexOf("?") != -1) _host = _host.split(/\?/)[0]; - } - // Return the mapped object - return {host: _host, port: _port}; - }); - } - - // Get the db name - object.dbName = dbName || 'admin'; - // Split up all the options - urlOptions = (query_string_part || '').split(/[&;]/); - // Ugh, we have to figure out which options go to which constructor manually. - urlOptions.forEach(function(opt) { - if(!opt) return; - var splitOpt = opt.split('='), name = splitOpt[0], value = splitOpt[1]; - // Options implementations - switch(name) { - case 'slaveOk': - case 'slave_ok': - serverOptions.slave_ok = (value == 'true'); - dbOptions.slaveOk = (value == 'true'); - break; - case 'maxPoolSize': - case 'poolSize': - serverOptions.poolSize = parseInt(value, 10); - replSetServersOptions.poolSize = parseInt(value, 10); - break; - case 'autoReconnect': - case 'auto_reconnect': - serverOptions.auto_reconnect = (value == 'true'); - break; - case 'minPoolSize': - throw new Error("minPoolSize not supported"); - case 'maxIdleTimeMS': - throw new Error("maxIdleTimeMS not supported"); - case 'waitQueueMultiple': - throw new Error("waitQueueMultiple not supported"); - case 'waitQueueTimeoutMS': - throw new Error("waitQueueTimeoutMS not supported"); - case 'uuidRepresentation': - throw new Error("uuidRepresentation not supported"); - case 'ssl': - if(value == 'prefer') { - serverOptions.ssl = value; - replSetServersOptions.ssl = value; - break; - } - serverOptions.ssl = (value == 'true'); - replSetServersOptions.ssl = (value == 'true'); - break; - case 'replicaSet': - case 'rs_name': - replSetServersOptions.rs_name = value; - break; - case 'reconnectWait': - replSetServersOptions.reconnectWait = parseInt(value, 10); - break; - case 'retries': - replSetServersOptions.retries = parseInt(value, 10); - break; - case 'readSecondary': - case 'read_secondary': - replSetServersOptions.read_secondary = (value == 'true'); - break; - case 'fsync': - dbOptions.fsync = (value == 'true'); - break; - case 'journal': - dbOptions.journal = (value == 'true'); - break; - case 'safe': - dbOptions.safe = (value == 'true'); - break; - case 'nativeParser': - case 'native_parser': - dbOptions.native_parser = (value == 'true'); - break; - case 'connectTimeoutMS': - serverOptions.socketOptions.connectTimeoutMS = parseInt(value, 10); - replSetServersOptions.socketOptions.connectTimeoutMS = parseInt(value, 10); - break; - case 'socketTimeoutMS': - serverOptions.socketOptions.socketTimeoutMS = parseInt(value, 10); - replSetServersOptions.socketOptions.socketTimeoutMS = parseInt(value, 10); - break; - case 'w': - dbOptions.w = parseInt(value, 10); - if(isNaN(dbOptions.w)) dbOptions.w = value; - break; - case 'authSource': - dbOptions.authSource = value; - break; - case 'gssapiServiceName': - dbOptions.gssapiServiceName = value; - break; - case 'authMechanism': - if(value == 'GSSAPI') { - // If no password provided decode only the principal - if(object.auth == null) { - var urlDecodeAuthPart = decodeURIComponent(authPart); - if(urlDecodeAuthPart.indexOf("@") == -1) throw new Error("GSSAPI requires a provided principal"); - object.auth = {user: urlDecodeAuthPart, password: null}; - } else { - object.auth.user = decodeURIComponent(object.auth.user); - } - } else if(value == 'MONGODB-X509') { - object.auth = {user: decodeURIComponent(authPart)}; - } - - // Only support GSSAPI or MONGODB-CR for now - if(value != 'GSSAPI' - && value != 'MONGODB-X509' - && value != 'SCRAM-SHA-1' - && value != 'MONGODB-CR' - && value != 'PLAIN') - throw new Error("only GSSAPI, PLAIN, MONGODB-X509, SCRAM-SHA-1 or MONGODB-CR is supported by authMechanism"); - - // Authentication mechanism - dbOptions.authMechanism = value; - break; - case 'wtimeoutMS': - dbOptions.wtimeout = parseInt(value, 10); - break; - case 'readPreference': - if(!ReadPreference.isValid(value)) throw new Error("readPreference must be either primary/primaryPreferred/secondary/secondaryPreferred/nearest"); - dbOptions.read_preference = value; - break; - case 'readPreferenceTags': - // Decode the value - value = decodeURIComponent(value); - // Contains the tag object - var tagObject = {}; - if(value == null || value == '') { - dbOptions.read_preference_tags.push(tagObject); - break; - } - - // Split up the tags - var tags = value.split(/\,/); - for(var i = 0; i < tags.length; i++) { - var parts = tags[i].trim().split(/\:/); - tagObject[parts[0]] = parts[1]; - } - - // Set the preferences tags - dbOptions.read_preference_tags.push(tagObject); - break; - default: - break; - } - }); - - // No tags: should be null (not []) - if(dbOptions.read_preference_tags.length === 0) { - dbOptions.read_preference_tags = null; - } - - // Validate if there are an invalid write concern combinations - if((dbOptions.w == -1 || dbOptions.w == 0) && ( - dbOptions.journal == true - || dbOptions.fsync == true - || dbOptions.safe == true)) throw new Error("w set to -1 or 0 cannot be combined with safe/w/journal/fsync") - - // If no read preference set it to primary - if(!dbOptions.read_preference) dbOptions.read_preference = 'primary'; - - // Add servers to result - object.servers = servers; - // Returned parsed object - return object; -} diff --git a/node_modules/mongodb/lib/mongodb/cursor.js b/node_modules/mongodb/lib/mongodb/cursor.js deleted file mode 100644 index 050cc9c..0000000 --- a/node_modules/mongodb/lib/mongodb/cursor.js +++ /dev/null @@ -1,1038 +0,0 @@ -var QueryCommand = require('./commands/query_command').QueryCommand, - GetMoreCommand = require('./commands/get_more_command').GetMoreCommand, - KillCursorCommand = require('./commands/kill_cursor_command').KillCursorCommand, - Long = require('bson').Long, - ReadPreference = require('./connection/read_preference').ReadPreference, - CursorStream = require('./cursorstream'), - timers = require('timers'), - utils = require('./utils'); - -// Set processor, setImmediate if 0.10 otherwise nextTick -var processor = require('./utils').processor(); - -/** - * Constructor for a cursor object that handles all the operations on query result - * using find. This cursor object is unidirectional and cannot traverse backwards. Clients should not be creating a cursor directly, - * but use find to acquire a cursor. (INTERNAL TYPE) - * - * Options - * - **skip** {Number} skip number of documents to skip. - * - **limit** {Number}, limit the number of results to return. -1 has a special meaning and is used by Db.eval. A value of 1 will also be treated as if it were -1. - * - **sort** {Array | Object}, set to sort the documents coming back from the query. Array of indexes, [['a', 1]] etc. - * - **hint** {Object}, hint force the query to use a specific index. - * - **explain** {Boolean}, explain return the explaination of the query. - * - **snapshot** {Boolean}, snapshot Snapshot mode assures no duplicates are returned. - * - **timeout** {Boolean}, timeout allow the query to timeout. - * - **tailable** {Boolean}, tailable allow the cursor to be tailable. - * - **awaitdata** {Boolean}, awaitdata allow the cursor to wait for data, only applicable for tailable cursor. - * - **oplogReplay** {Boolean}, sets an internal flag, only applicable for tailable cursor. - * - **batchSize** {Number}, batchSize the number of the subset of results to request the database to return for every request. This should initially be greater than 1 otherwise the database will automatically close the cursor. The batch size can be set to 1 with cursorInstance.batchSize after performing the initial query to the database. - * - **raw** {Boolean}, raw return all query documents as raw buffers (default false). - * - **read** {Boolean}, read specify override of read from source (primary/secondary). - * - **returnKey** {Boolean}, returnKey only return the index key. - * - **maxScan** {Number}, maxScan limit the number of items to scan. - * - **min** {Number}, min set index bounds. - * - **max** {Number}, max set index bounds. - * - **maxTimeMS** {Number}, number of miliseconds to wait before aborting the query. - * - **showDiskLoc** {Boolean}, showDiskLoc show disk location of results. - * - **comment** {String}, comment you can put a $comment field on a query to make looking in the profiler logs simpler. - * - **numberOfRetries** {Number}, numberOfRetries if using awaidata specifies the number of times to retry on timeout. - * - **dbName** {String}, dbName override the default dbName. - * - **tailableRetryInterval** {Number}, tailableRetryInterval specify the miliseconds between getMores on tailable cursor. - * - **exhaust** {Boolean}, exhaust have the server send all the documents at once as getMore packets. - * - **partial** {Boolean}, partial have the sharded system return a partial result from mongos. - * - * @class Represents a Cursor. - * @param {Db} db the database object to work with. - * @param {Collection} collection the collection to query. - * @param {Object} selector the query selector. - * @param {Object} fields an object containing what fields to include or exclude from objects returned. - * @param {Object} [options] additional options for the collection. -*/ -function Cursor(db, collection, selector, fields, options) { - this.db = db; - this.collection = collection; - this.selector = selector; - this.fields = fields; - options = !options ? {} : options; - - this.skipValue = options.skip == null ? 0 : options.skip; - this.limitValue = options.limit == null ? 0 : options.limit; - this.sortValue = options.sort; - this.hint = options.hint; - this.explainValue = options.explain; - this.snapshot = options.snapshot; - this.timeout = options.timeout == null ? true : options.timeout; - this.tailable = options.tailable; - this.awaitdata = options.awaitdata; - this.oplogReplay = options.oplogReplay; - this.numberOfRetries = options.numberOfRetries == null ? 5 : options.numberOfRetries; - this.currentNumberOfRetries = this.numberOfRetries; - this.batchSizeValue = options.batchSize == null ? 0 : options.batchSize; - this.raw = options.raw == null ? false : options.raw; - this.readPreference = options.readPreference == null ? ReadPreference.PRIMARY : options.readPreference; - this.returnKey = options.returnKey; - this.maxScan = options.maxScan; - this.min = options.min; - this.max = options.max; - this.showDiskLoc = options.showDiskLoc; - this.comment = options.comment; - this.tailableRetryInterval = options.tailableRetryInterval || 100; - this.exhaust = options.exhaust || false; - this.partial = options.partial || false; - this.slaveOk = options.slaveOk || false; - this.maxTimeMSValue = options.maxTimeMS; - this.connection = options.connection; - - this.totalNumberOfRecords = 0; - this.items = []; - this.cursorId = Long.fromInt(0); - - // This name - this.dbName = options.dbName; - - // State variables for the cursor - this.state = Cursor.INIT; - // Keep track of the current query run - this.queryRun = false; - this.getMoreTimer = false; - - // If we are using a specific db execute against it - if(this.dbName != null) { - this.collectionName = this.dbName + "." + this.collection.collectionName; - } else { - this.collectionName = (this.db.databaseName ? this.db.databaseName + "." : '') + this.collection.collectionName; - } -} - -/** - * Clones a given cursor but uses new options - * @param {Cursor} cursor the cursor to clone. - * @return {Object} [options] additional options for the collection when cloning. - */ -Cursor.cloneWithOptions = function(cursor, options) { - return new Cursor(cursor.db, cursor.collection, cursor.selector, cursor.fields, options); -} - -/** - * Resets this cursor to its initial state. All settings like the query string, - * tailable, batchSizeValue, skipValue and limits are preserved. - * - * @return {Cursor} returns itself with rewind applied. - * @api public - */ -Cursor.prototype.rewind = function() { - var self = this; - - if (self.state != Cursor.INIT) { - if (self.state != Cursor.CLOSED) { - self.close(function() {}); - } - - self.numberOfReturned = 0; - self.totalNumberOfRecords = 0; - self.items = []; - self.cursorId = Long.fromInt(0); - self.state = Cursor.INIT; - self.queryRun = false; - } - - return self; -} - - -/** - * Returns an array of documents. The caller is responsible for making sure that there - * is enough memory to store the results. Note that the array only contain partial - * results when this cursor had been previouly accessed. In that case, - * cursor.rewind() can be used to reset the cursor. - * - * @param {Function} callback This will be called after executing this method successfully. The first parameter will contain the Error object if an error occured, or null otherwise. The second parameter will contain an array of BSON deserialized objects as a result of the query. - * @return {null} - * @api public - */ -Cursor.prototype.toArray = function(callback) { - var self = this; - - if(!callback) { - throw new Error('callback is mandatory'); - } - - if(this.tailable) { - callback(new Error("Tailable cursor cannot be converted to array"), null); - } else if(this.state != Cursor.CLOSED) { - // return toArrayExhaust(self, callback); - // If we are using exhaust we can't use the quick fire method - if(self.exhaust) return toArrayExhaust(self, callback); - // Quick fire using trampoline to avoid nextTick - self.nextObject({noReturn: true}, function(err, result) { - if(err) return callback(utils.toError(err), null); - if(self.cursorId.toString() == "0") { - self.state = Cursor.CLOSED; - return callback(null, self.items); - } - - // Let's issue getMores until we have no more records waiting - getAllByGetMore(self, function(err, done) { - self.state = Cursor.CLOSED; - if(err) return callback(utils.toError(err), null); - // Let's release the internal list - var items = self.items; - self.items = null; - // Return all the items - callback(null, items); - }); - }) - - } else { - callback(new Error("Cursor is closed"), null); - } -} - -var toArrayExhaust = function(self, callback) { - var items = []; - - self.each(function(err, item) { - if(err != null) { - return callback(utils.toError(err), null); - } - - if(item != null && Array.isArray(items)) { - items.push(item); - } else { - var resultItems = items; - items = null; - self.items = []; - callback(null, resultItems); - } - }); -} - -var getAllByGetMore = function(self, callback) { - getMore(self, {noReturn: true}, function(err, result) { - if(err) return callback(utils.toError(err)); - if(result == null) return callback(null, null); - if(self.cursorId.toString() == "0") return callback(null, null); - getAllByGetMore(self, callback); - }) -}; - -/** - * Iterates over all the documents for this cursor. As with **{cursor.toArray}**, - * not all of the elements will be iterated if this cursor had been previouly accessed. - * In that case, **{cursor.rewind}** can be used to reset the cursor. However, unlike - * **{cursor.toArray}**, the cursor will only hold a maximum of batch size elements - * at any given time if batch size is specified. Otherwise, the caller is responsible - * for making sure that the entire result can fit the memory. - * - * @param {Function} callback this will be called for while iterating every document of the query result. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the document. - * @return {null} - * @api public - */ -Cursor.prototype.each = function(callback) { - var self = this; - var fn; - - if (!callback) { - throw new Error('callback is mandatory'); - } - - if(this.state != Cursor.CLOSED) { - // If we are using exhaust we can't use the quick fire method - if(self.exhaust) return eachExhaust(self, callback); - // Quick fire using trampoline to avoid nextTick - if(this.items.length > 0) { - // Trampoline all the entries - while(fn = loop(self, callback)) fn(self, callback); - // Call each again - self.each(callback); - } else { - self.nextObject(function(err, item) { - - if(err) { - self.state = Cursor.CLOSED; - return callback(utils.toError(err), item); - } - - if(item == null) return callback(null, null); - callback(null, item); - self.each(callback); - }) - } - } else { - callback(new Error("Cursor is closed"), null); - } -}; - -// Special for exhaust command as we don't initiate the actual result sets -// the server just sends them as they arrive meaning we need to get the IO event -// loop happen so we can receive more data from the socket or we return to early -// after the first fetch and loose all the incoming getMore's automatically issued -// from the server. -var eachExhaust = function(self, callback) { - //FIX: stack overflow (on deep callback) (cred: https://github.com/limp/node-mongodb-native/commit/27da7e4b2af02035847f262b29837a94bbbf6ce2) - processor(function(){ - // Fetch the next object until there is no more objects - self.nextObject(function(err, item) { - if(err != null) return callback(err, null); - if(item != null) { - callback(null, item); - eachExhaust(self, callback); - } else { - // Close the cursor if done - self.state = Cursor.CLOSED; - callback(err, null); - } - }); - }); -} - -// Trampoline emptying the number of retrieved items -// without incurring a nextTick operation -var loop = function(self, callback) { - // No more items we are done - if(self.items.length == 0) return; - // Get the next document - var doc = self.items.shift(); - // Callback - callback(null, doc); - // Loop - return loop; -} - -/** - * Determines how many result the query for this cursor will return - * - * @param {Boolean} applySkipLimit if set to true will apply the skip and limits set on the cursor. Defaults to false. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the number of results or null if an error occured. - * @return {null} - * @api public - */ -Cursor.prototype.count = function(applySkipLimit, callback) { - if(typeof applySkipLimit == 'function') { - callback = applySkipLimit; - applySkipLimit = false; - } - - var options = {}; - if(applySkipLimit) { - if(typeof this.skipValue == 'number') options.skip = this.skipValue; - if(typeof this.limitValue == 'number') options.limit = this.limitValue; - } - - // If maxTimeMS set - if(typeof this.maxTimeMSValue == 'number') options.maxTimeMS = this.maxTimeMSValue; - // Do we have a hint add it to the options - if(this.hint) options.hint = this.hint; - - // Call count command - this.collection.count(this.selector, options, callback); -}; - -/** - * Sets the sort parameter of this cursor to the given value. - * - * This method has the following method signatures: - * (keyOrList, callback) - * (keyOrList, direction, callback) - * - * @param {String|Array|Object} keyOrList This can be a string or an array. If passed as a string, the string will be the field to sort. If passed an array, each element will represent a field to be sorted and should be an array that contains the format [string, direction]. - * @param {String|Number} direction this determines how the results are sorted. "asc", "ascending" or 1 for asceding order while "desc", "desceding or -1 for descending order. Note that the strings are case insensitive. - * @param {Function} callback this will be called after executing this method. The first parameter will contain an error object when the cursor is already closed while the second parameter will contain a reference to this object upon successful execution. - * @return {Cursor} an instance of this object. - * @api public - */ -Cursor.prototype.sort = function(keyOrList, direction, callback) { - callback = callback || function(){}; - if(typeof direction === "function") { callback = direction; direction = null; } - - if(this.tailable) { - callback(new Error("Tailable cursor doesn't support sorting"), null); - } else if(this.queryRun == true || this.state == Cursor.CLOSED) { - callback(new Error("Cursor is closed"), null); - } else { - var order = keyOrList; - - if(direction != null) { - order = [[keyOrList, direction]]; - } - - this.sortValue = order; - callback(null, this); - } - return this; -}; - -/** - * Sets the limit parameter of this cursor to the given value. - * - * @param {Number} limit the new limit. - * @param {Function} [callback] this optional callback will be called after executing this method. The first parameter will contain an error object when the limit given is not a valid number or when the cursor is already closed while the second parameter will contain a reference to this object upon successful execution. - * @return {Cursor} an instance of this object. - * @api public - */ -Cursor.prototype.limit = function(limit, callback) { - if(this.tailable) { - if(callback) { - callback(new Error("Tailable cursor doesn't support limit"), null); - } else { - throw new Error("Tailable cursor doesn't support limit"); - } - } else if(this.queryRun == true || this.state == Cursor.CLOSED) { - if(callback) { - callback(new Error("Cursor is closed"), null); - } else { - throw new Error("Cursor is closed"); - } - } else { - if(limit != null && limit.constructor != Number) { - if(callback) { - callback(new Error("limit requires an integer"), null); - } else { - throw new Error("limit requires an integer"); - } - } else { - this.limitValue = limit; - if(callback) return callback(null, this); - } - } - - return this; -}; - -/** - * Specifies a time limit for a query operation. After the specified - * time is exceeded, the operation will be aborted and an error will be - * returned to the client. If maxTimeMS is null, no limit is applied. - * - * @param {Number} maxTimeMS the maxTimeMS for the query. - * @param {Function} [callback] this optional callback will be called after executing this method. The first parameter will contain an error object when the limit given is not a valid number or when the cursor is already closed while the second parameter will contain a reference to this object upon successful execution. - * @return {Cursor} an instance of this object. - * @api public - */ -Cursor.prototype.maxTimeMS = function(maxTimeMS, callback) { - if(typeof maxTimeMS != 'number') { - throw new Error("maxTimeMS must be a number"); - } - - // Save the maxTimeMS option - this.maxTimeMSValue = maxTimeMS; - // Return the cursor for chaining - return this; -}; - -/** - * Sets the read preference for the cursor - * - * @param {String} the read preference for the cursor, one of Server.READ_PRIMARY, Server.READ_SECONDARY, Server.READ_SECONDARY_ONLY - * @param {Function} [callback] this optional callback will be called after executing this method. The first parameter will contain an error object when the read preference given is not a valid number or when the cursor is already closed while the second parameter will contain a reference to this object upon successful execution. - * @return {Cursor} an instance of this object. - * @api public - */ -Cursor.prototype.setReadPreference = function(readPreference, tags, callback) { - if(typeof tags == 'function') callback = tags; - - var _mode = readPreference != null && typeof readPreference == 'object' ? readPreference.mode : readPreference; - - if(this.queryRun == true || this.state == Cursor.CLOSED) { - if(callback == null) throw new Error("Cannot change read preference on executed query or closed cursor"); - callback(new Error("Cannot change read preference on executed query or closed cursor")); - } else if(_mode != null && _mode != 'primary' - && _mode != 'secondaryOnly' && _mode != 'secondary' - && _mode != 'nearest' && _mode != 'primaryPreferred' && _mode != 'secondaryPreferred') { - if(callback == null) throw new Error("only readPreference of primary, secondary, secondaryPreferred, primaryPreferred or nearest supported"); - callback(new Error("only readPreference of primary, secondary, secondaryPreferred, primaryPreferred or nearest supported")); - } else { - this.readPreference = readPreference; - if(callback != null) callback(null, this); - } - - return this; -} - -/** - * Sets the skip parameter of this cursor to the given value. - * - * @param {Number} skip the new skip value. - * @param {Function} [callback] this optional callback will be called after executing this method. The first parameter will contain an error object when the skip value given is not a valid number or when the cursor is already closed while the second parameter will contain a reference to this object upon successful execution. - * @return {Cursor} an instance of this object. - * @api public - */ -Cursor.prototype.skip = function(skip, callback) { - callback = callback || function(){}; - - if(this.tailable) { - callback(new Error("Tailable cursor doesn't support skip"), null); - } else if(this.queryRun == true || this.state == Cursor.CLOSED) { - callback(new Error("Cursor is closed"), null); - } else { - if(skip != null && skip.constructor != Number) { - callback(new Error("skip requires an integer"), null); - } else { - this.skipValue = skip; - callback(null, this); - } - } - - return this; -}; - -/** - * Sets the batch size parameter of this cursor to the given value. - * - * @param {Number} batchSize the new batch size. - * @param {Function} [callback] this optional callback will be called after executing this method. The first parameter will contain an error object when the batchSize given is not a valid number or when the cursor is already closed while the second parameter will contain a reference to this object upon successful execution. - * @return {Cursor} an instance of this object. - * @api public - */ -Cursor.prototype.batchSize = function(batchSize, callback) { - if(this.state == Cursor.CLOSED) { - if(callback != null) { - return callback(new Error("Cursor is closed"), null); - } else { - throw new Error("Cursor is closed"); - } - } else if(batchSize != null && batchSize.constructor != Number) { - if(callback != null) { - return callback(new Error("batchSize requires an integer"), null); - } else { - throw new Error("batchSize requires an integer"); - } - } else { - this.batchSizeValue = batchSize; - if(callback != null) return callback(null, this); - } - - return this; -}; - -/** - * The limit used for the getMore command - * - * @return {Number} The number of records to request per batch. - * @ignore - * @api private - */ -var limitRequest = function(self) { - var requestedLimit = self.limitValue; - var absLimitValue = Math.abs(self.limitValue); - var absBatchValue = Math.abs(self.batchSizeValue); - - if(absLimitValue > 0) { - if (absBatchValue > 0) { - requestedLimit = Math.min(absLimitValue, absBatchValue); - } - } else { - requestedLimit = self.batchSizeValue; - } - - return requestedLimit; -}; - - -/** - * Generates a QueryCommand object using the parameters of this cursor. - * - * @return {QueryCommand} The command object - * @ignore - * @api private - */ -var generateQueryCommand = function(self) { - // Unpack the options - var queryOptions = QueryCommand.OPTS_NONE; - if(!self.timeout) { - queryOptions |= QueryCommand.OPTS_NO_CURSOR_TIMEOUT; - } - - if(self.tailable) { - queryOptions |= QueryCommand.OPTS_TAILABLE_CURSOR; - self.skipValue = self.limitValue = 0; - - // if awaitdata is set - if(self.awaitdata) { - queryOptions |= QueryCommand.OPTS_AWAIT_DATA; - } - - // This sets an internal undocumented flag. Clients should not depend on its - // behavior! - if(self.oplogReplay) { - queryOptions |= QueryCommand.OPTS_OPLOG_REPLAY; - } - } - - if(self.exhaust) { - queryOptions |= QueryCommand.OPTS_EXHAUST; - } - - // Unpack the read preference to set slave ok correctly - var readPreference = self.readPreference instanceof ReadPreference ? self.readPreference.mode : self.readPreference; - - // if(self.read == 'secondary') - if(readPreference == ReadPreference.PRIMARY_PREFERRED - || readPreference == ReadPreference.SECONDARY - || readPreference == ReadPreference.SECONDARY_PREFERRED - || readPreference == ReadPreference.NEAREST) { - queryOptions |= QueryCommand.OPTS_SLAVE; - } - - // Override slaveOk from the user - if(self.slaveOk) { - queryOptions |= QueryCommand.OPTS_SLAVE; - } - - if(self.partial) { - queryOptions |= QueryCommand.OPTS_PARTIAL; - } - - // limitValue of -1 is a special case used by Db#eval - var numberToReturn = self.limitValue == -1 ? -1 : limitRequest(self); - - // Check if we need a special selector - if(self.sortValue != null || self.explainValue != null || self.hint != null || self.snapshot != null - || self.returnKey != null || self.maxScan != null || self.min != null || self.max != null - || self.showDiskLoc != null || self.comment != null || typeof self.maxTimeMSValue == 'number') { - - // order by - var orderBy = utils.formattedOrderClause(self.sortValue); - - // Build special selector - var specialSelector = {'$query':self.selector}; - if(orderBy) specialSelector['orderby'] = orderBy; - if(self.hint != null && self.hint.constructor == Object) specialSelector['$hint'] = self.hint; - if(self.snapshot != null) specialSelector['$snapshot'] = self.snapshot; - if(self.returnKey != null) specialSelector['$returnKey'] = self.returnKey; - if(self.maxScan != null) specialSelector['$maxScan'] = self.maxScan; - if(self.min != null) specialSelector['$min'] = self.min; - if(self.max != null) specialSelector['$max'] = self.max; - if(self.showDiskLoc != null) specialSelector['$showDiskLoc'] = self.showDiskLoc; - if(self.comment != null) specialSelector['$comment'] = self.comment; - - // If we are querying the $cmd collection we need to add maxTimeMS as a field - // otherwise for a normal query it's a "special selector" $maxTimeMS - if(typeof self.maxTimeMSValue == 'number' - && self.collectionName.indexOf('.$cmd') != -1) { - specialSelector['maxTimeMS'] = self.maxTimeMSValue; - } else if(typeof self.maxTimeMSValue == 'number' - && self.collectionName.indexOf('.$cmd') == -1) { - specialSelector['$maxTimeMS'] = self.maxTimeMSValue; - } - - // If we have explain set only return a single document with automatic cursor close - if(self.explainValue) { - numberToReturn = (-1)*Math.abs(numberToReturn); - specialSelector['$explain'] = true; - } - - // Return the query - return new QueryCommand(self.db, self.collectionName, queryOptions, self.skipValue, numberToReturn, specialSelector, self.fields); - } else { - return new QueryCommand(self.db, self.collectionName, queryOptions, self.skipValue, numberToReturn, self.selector, self.fields); - } -}; - -/** - * @return {Object} Returns an object containing the sort value of this cursor with - * the proper formatting that can be used internally in this cursor. - * @ignore - * @api private - */ -Cursor.prototype.formattedOrderClause = function() { - return utils.formattedOrderClause(this.sortValue); -}; - -/** - * Converts the value of the sort direction into its equivalent numerical value. - * - * @param sortDirection {String|number} Range of acceptable values: - * 'ascending', 'descending', 'asc', 'desc', 1, -1 - * - * @return {number} The equivalent numerical value - * @throws Error if the given sortDirection is invalid - * @ignore - * @api private - */ -Cursor.prototype.formatSortValue = function(sortDirection) { - return utils.formatSortValue(sortDirection); -}; - -/** - * Gets the next document from the cursor. - * - * @param {Function} callback this will be called after executing this method. The first parameter will contain an error object on error while the second parameter will contain a document from the returned result or null if there are no more results. - * @api public - */ -Cursor.prototype.nextObject = function(options, callback) { - var self = this; - - if(typeof options == 'function') { - callback = options; - options = {}; - } - - if(self.state == Cursor.INIT) { - var cmd; - try { - cmd = generateQueryCommand(self); - } catch (err) { - return callback(err, null); - } - - // No need to check the keys - var queryOptions = {exhaust: self.exhaust - , raw:self.raw - , readPreference:self.readPreference - , connection:self.connection - , checkKeys: false}; - - // Execute command - var commandHandler = function(err, result) { - // If on reconnect, the command got given a different connection, switch - // the whole cursor to it. - self.connection = queryOptions.connection; - self.state = Cursor.OPEN; // Adjust the state of the cursor - if(err != null && result == null) return callback(utils.toError(err), null); - - if(err == null && (result == null || result.documents == null || !Array.isArray(result.documents))) { - return self.close(function() {callback(new Error("command failed to return results"), null);}); - } - - if(err == null && result && result.documents[0] && result.documents[0]['$err']) { - return self.close(function() {callback(utils.toError(result.documents[0]['$err']), null);}); - } - - if(err == null && result && result.documents[0] && result.documents[0]['errmsg']) { - return self.close(function() {callback(utils.toError(result.documents[0]), null);}); - } - - self.queryRun = true; - self.cursorId = result.cursorId; - self.totalNumberOfRecords = result.numberReturned; - - // Add the new documents to the list of items, using forloop to avoid - // new array allocations and copying - for(var i = 0; i < result.documents.length; i++) { - self.items.push(result.documents[i]); - } - - // If we have noReturn set just return (not modifying the internal item list) - // used for toArray - if(options.noReturn) { - return callback(null, true); - } - - // Ignore callbacks until the cursor is dead for exhausted - if(self.exhaust && result.cursorId.toString() == "0") { - self.nextObject(callback); - } else if(self.exhaust == false || self.exhaust == null) { - self.nextObject(callback); - } - }; - - // If we have no connection set on this cursor check one out - if(self.connection == null) { - try { - self.connection = self.db.serverConfig.checkoutReader(this.readPreference); - - // Check if we have an error from the checkout Reader function - if(self.connection instanceof Error) { - return callback(utils.toError(self.connection), null); - } - - // Add to the query options - queryOptions.connection = self.connection; - } catch(err) { - return callback(utils.toError(err), null); - } - } - - // Execute the command - self.db._executeQueryCommand(cmd, queryOptions, commandHandler); - // Set the command handler to null - commandHandler = null; - } else if(self.items.length) { - callback(null, self.items.shift()); - } else if(self.cursorId.greaterThan(Long.fromInt(0))) { - getMore(self, callback); - } else { - // Force cursor to stay open - return self.close(function() {callback(null, null);}); - } -} - -/** - * Gets more results from the database if any. - * - * @param {Function} callback this will be called after executing this method. The first parameter will contain an error object on error while the second parameter will contain a document from the returned result or null if there are no more results. - * @ignore - * @api private - */ -var getMore = function(self, options, callback) { - var limit = 0; - - if(typeof options == 'function') { - callback = options; - options = {}; - } - - if(self.state == Cursor.GET_MORE) return callback(null, null); - - // Set get more in progress - self.state = Cursor.GET_MORE; - - // Set options - if (!self.tailable && self.limitValue > 0) { - limit = self.limitValue - self.totalNumberOfRecords; - if (limit < 1) { - self.close(function() {callback(null, null);}); - return; - } - } - - try { - var getMoreCommand = new GetMoreCommand( - self.db - , self.collectionName - , limitRequest(self) - , self.cursorId - ); - - // Set up options - var command_options = { - readPreference: self.readPreference - , raw: self.raw - , connection:self.connection - }; - - // Execute the command - self.db._executeQueryCommand(getMoreCommand, command_options, function(err, result) { - var cbValue; - - // Get more done - self.state = Cursor.OPEN; - - if(err != null) { - self.state = Cursor.CLOSED; - return callback(utils.toError(err), null); - } - - // Ensure we get a valid result - if(!result || !result.documents) { - self.state = Cursor.CLOSED; - return callback(utils.toError("command failed to return results"), null) - } - - // If we have a timed out query - if((result.responseFlag & (1 << 0)) != 0) { - self.state = Cursor.CLOSED; - return callback(utils.toError("cursor killed or timed out"), null); - } - - // If the QueryFailure flag is set - if((result.responseFlag & (1 << 1)) != 0) { - self.state = Cursor.CLOSED; - return callback(utils.toError("QueryFailure flag set on getmore command"), null); - } - - try { - var isDead = 1 === result.responseFlag && result.cursorId.isZero(); - - self.cursorId = result.cursorId; - self.totalNumberOfRecords += result.numberReturned; - - // Determine if there's more documents to fetch - if(result.numberReturned > 0) { - if (self.limitValue > 0) { - var excessResult = self.totalNumberOfRecords - self.limitValue; - - if (excessResult > 0) { - result.documents.splice(-1 * excessResult, excessResult); - } - } - - // Reset the tries for awaitdata if we are using it - self.currentNumberOfRetries = self.numberOfRetries; - // Get the documents - for(var i = 0; i < result.documents.length; i++) { - self.items.push(result.documents[i]); - } - - // Don's shift a document out as we need it for toArray - if(options.noReturn) { - cbValue = true; - } else { - cbValue = self.items.shift(); - } - } else if(self.tailable && !isDead && self.awaitdata) { - // Excute the tailable cursor once more, will timeout after ~4 sec if awaitdata used - self.currentNumberOfRetries = self.currentNumberOfRetries - 1; - if(self.currentNumberOfRetries == 0) { - self.close(function() { - callback(new Error("tailable cursor timed out"), null); - }); - } else { - getMore(self, callback); - } - } else if(self.tailable && !isDead) { - self.getMoreTimer = setTimeout(function() { getMore(self, callback); }, self.tailableRetryInterval); - } else { - self.close(function() {callback(null, null); }); - } - - result = null; - } catch(err) { - callback(utils.toError(err), null); - } - if (cbValue != null) callback(null, cbValue); - }); - - getMoreCommand = null; - } catch(err) { - // Get more done - self.state = Cursor.OPEN; - - var handleClose = function() { - callback(utils.toError(err), null); - }; - - self.close(handleClose); - handleClose = null; - } -} - -/** - * Gets a detailed information about how the query is performed on this cursor and how - * long it took the database to process it. - * - * @param {Function} callback this will be called after executing this method. The first parameter will always be null while the second parameter will be an object containing the details. - * @api public - */ -Cursor.prototype.explain = function(callback) { - var limit = (-1)*Math.abs(this.limitValue); - - // Create a new cursor and fetch the plan - var cursor = new Cursor(this.db, this.collection, this.selector, this.fields, { - skip: this.skipValue - , limit:limit - , sort: this.sortValue - , hint: this.hint - , explain: true - , snapshot: this.snapshot - , timeout: this.timeout - , tailable: this.tailable - , batchSize: this.batchSizeValue - , slaveOk: this.slaveOk - , raw: this.raw - , readPreference: this.readPreference - , returnKey: this.returnKey - , maxScan: this.maxScan - , min: this.min - , max: this.max - , showDiskLoc: this.showDiskLoc - , comment: this.comment - , awaitdata: this.awaitdata - , oplogReplay: this.oplogReplay - , numberOfRetries: this.numberOfRetries - , dbName: this.dbName - }); - - // Fetch the explaination document - cursor.nextObject(function(err, item) { - if(err != null) return callback(utils.toError(err), null); - // close the cursor - cursor.close(function(err, result) { - if(err != null) return callback(utils.toError(err), null); - callback(null, item); - }); - }); -}; - -/** - * Returns a Node Transform Stream interface for this cursor. - * - * Options - * - **transform** {Function} function of type function(object) { return transformed }, allows for transformation of data before emitting. - * - * @return {CursorStream} returns a stream object. - * @api public - */ -Cursor.prototype.stream = function stream(options) { - return new CursorStream(this, options); -} - -/** - * Close the cursor. - * - * @param {Function} callback this will be called after executing this method. The first parameter will always contain null while the second parameter will contain a reference to this cursor. - * @return {null} - * @api public - */ -Cursor.prototype.close = function(callback) { - var self = this - this.getMoreTimer && clearTimeout(this.getMoreTimer); - // Close the cursor if not needed - if(this.cursorId instanceof Long && this.cursorId.greaterThan(Long.fromInt(0))) { - try { - var command = new KillCursorCommand(this.db, [this.cursorId]); - // Added an empty callback to ensure we don't throw any null exceptions - this.db._executeQueryCommand(command, {readPreference:self.readPreference, raw:self.raw, connection:self.connection}); - } catch(err) {} - } - - // Null out the connection - self.connection = null; - // Reset cursor id - this.cursorId = Long.fromInt(0); - // Set to closed status - this.state = Cursor.CLOSED; - - if(callback) { - callback(null, self); - self.items = []; - } - - return this; -}; - -/** - * Check if the cursor is closed or open. - * - * @return {Boolean} returns the state of the cursor. - * @api public - */ -Cursor.prototype.isClosed = function() { - return this.state == Cursor.CLOSED ? true : false; -}; - -/** - * Init state - * - * @classconstant INIT - **/ -Cursor.INIT = 0; - -/** - * Cursor open - * - * @classconstant OPEN - **/ -Cursor.OPEN = 1; - -/** - * Cursor closed - * - * @classconstant CLOSED - **/ -Cursor.CLOSED = 2; - -/** - * Cursor performing a get more - * - * @classconstant OPEN - **/ -Cursor.GET_MORE = 3; - -/** - * @ignore - * @api private - */ -exports.Cursor = Cursor; diff --git a/node_modules/mongodb/lib/mongodb/cursorstream.js b/node_modules/mongodb/lib/mongodb/cursorstream.js deleted file mode 100644 index 4370f45..0000000 --- a/node_modules/mongodb/lib/mongodb/cursorstream.js +++ /dev/null @@ -1,167 +0,0 @@ -var timers = require('timers'); - -// Set processor, setImmediate if 0.10 otherwise nextTick -var processor = require('./utils').processor(); - -/** - * Module dependecies. - */ -var Stream = require('stream').Stream; - -/** - * CursorStream - * - * Returns a stream interface for the **cursor**. - * - * Options - * - **transform** {Function} function of type function(object) { return transformed }, allows for transformation of data before emitting. - * - * Events - * - **data** {function(item) {}} the data event triggers when a document is ready. - * - **error** {function(err) {}} the error event triggers if an error happens. - * - **close** {function() {}} the end event triggers when there is no more documents available. - * - * @class Represents a CursorStream. - * @param {Cursor} cursor a cursor object that the stream wraps. - * @return {Stream} - */ -function CursorStream(cursor, options) { - if(!(this instanceof CursorStream)) return new CursorStream(cursor); - options = options ? options : {}; - - Stream.call(this); - - this.readable = true; - this.paused = false; - this._cursor = cursor; - this._destroyed = null; - this.options = options; - - // give time to hook up events - var self = this; - process.nextTick(function() { - self._init(); - }); -} - -/** - * Inherit from Stream - * @ignore - * @api private - */ -CursorStream.prototype.__proto__ = Stream.prototype; - -/** - * Flag stating whether or not this stream is readable. - */ -CursorStream.prototype.readable; - -/** - * Flag stating whether or not this stream is paused. - */ -CursorStream.prototype.paused; - -/** - * Initialize the cursor. - * @ignore - * @api private - */ -CursorStream.prototype._init = function () { - if (this._destroyed) return; - this._next(); -} - -/** - * Pull the next document from the cursor. - * @ignore - * @api private - */ -CursorStream.prototype._next = function () { - if(this.paused || this._destroyed) return; - - var self = this; - // Get the next object - processor(function() { - if(self.paused || self._destroyed) return; - - self._cursor.nextObject(function (err, doc) { - self._onNextObject(err, doc); - }); - }); -} - -/** - * Handle each document as its returned from the cursor. - * @ignore - * @api private - */ -CursorStream.prototype._onNextObject = function (err, doc) { - if(err) { - this.destroy(err); - return this.emit('end'); - } - - // when doc is null we hit the end of the cursor - if(!doc && (this._cursor.state == 1 || this._cursor.state == 2)) { - this.emit('end') - return this.destroy(); - } else if(doc) { - var data = typeof this.options.transform == 'function' ? this.options.transform(doc) : doc; - this.emit('data', data); - this._next(); - } -} - -/** - * Pauses the stream. - * - * @api public - */ -CursorStream.prototype.pause = function () { - this.paused = true; -} - -/** - * Resumes the stream. - * - * @api public - */ -CursorStream.prototype.resume = function () { - var self = this; - - // Don't do anything if we are not paused - if(!this.paused) return; - if(!this._cursor.state == 3) return; - - process.nextTick(function() { - self.paused = false; - // Only trigger more fetching if the cursor is open - self._next(); - }) -} - -/** - * Destroys the stream, closing the underlying - * cursor. No more events will be emitted. - * - * @api public - */ -CursorStream.prototype.destroy = function (err) { - if (this._destroyed) return; - this._destroyed = true; - this.readable = false; - - this._cursor.close(); - - if(err && this.listeners('error').length > 0) { - return this.emit('error', err); - } - - this.emit('close'); -} - -// TODO - maybe implement the raw option to pass binary? -//CursorStream.prototype.setEncoding = function () { -//} - -module.exports = exports = CursorStream; diff --git a/node_modules/mongodb/lib/mongodb/db.js b/node_modules/mongodb/lib/mongodb/db.js deleted file mode 100644 index 3715486..0000000 --- a/node_modules/mongodb/lib/mongodb/db.js +++ /dev/null @@ -1,2179 +0,0 @@ -/** - * Module dependencies. - * @ignore - */ -var QueryCommand = require('./commands/query_command').QueryCommand - , DbCommand = require('./commands/db_command').DbCommand - , MongoReply = require('./responses/mongo_reply').MongoReply - , Admin = require('./admin').Admin - , Collection = require('./collection').Collection - , Server = require('./connection/server').Server - , ReplSet = require('./connection/repl_set/repl_set').ReplSet - , ReadPreference = require('./connection/read_preference').ReadPreference - , Mongos = require('./connection/mongos').Mongos - , Cursor = require('./cursor').Cursor - , EventEmitter = require('events').EventEmitter - , InsertCommand = require('./commands/insert_command').InsertCommand - , f = require('util').format - , inherits = require('util').inherits - , crypto = require('crypto') - , timers = require('timers') - , utils = require('./utils') - - // Authentication methods - , mongodb_cr_authenticate = require('./auth/mongodb_cr.js').authenticate - , mongodb_gssapi_authenticate = require('./auth/mongodb_gssapi.js').authenticate - , mongodb_sspi_authenticate = require('./auth/mongodb_sspi.js').authenticate - , mongodb_plain_authenticate = require('./auth/mongodb_plain.js').authenticate - , mongodb_x509_authenticate = require('./auth/mongodb_x509.js').authenticate - , mongodb_scram_authenticate = require('./auth/mongodb_scram.js').authenticate; - -var hasKerberos = false; -// Check if we have a the kerberos library -try { - require('kerberos'); - hasKerberos = true; -} catch(err) {} - -// Set processor, setImmediate if 0.10 otherwise nextTick -var processor = require('./utils').processor(); - -/** - * Create a new Db instance. - * - * Options - * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowledgement of write and w >= 1, w = 'majority' or tag acknowledges the write - * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) - * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal - * - **j**, (Boolean, default:false) write waits for journal sync before returning - * - **readPreference** {String}, the preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). - * - **native_parser** {Boolean, default:false}, use c++ bson parser. - * - **forceServerObjectId** {Boolean, default:false}, force server to create _id fields instead of client. - * - **pkFactory** {Object}, object overriding the basic ObjectID primary key generation. - * - **serializeFunctions** {Boolean, default:false}, serialize functions. - * - **raw** {Boolean, default:false}, perform operations using raw bson buffers. - * - **recordQueryStats** {Boolean, default:false}, record query statistics during execution. - * - **retryMiliSeconds** {Number, default:5000}, number of milliseconds between retries. - * - **numberOfRetries** {Number, default:5}, number of retries off connection. - * - **logger** {Object, default:null}, an object representing a logger that you want to use, needs to support functions debug, log, error **({error:function(message, object) {}, log:function(message, object) {}, debug:function(message, object) {}})**. - * - **slaveOk** {Number, default:null}, force setting of SlaveOk flag on queries (only use when explicitly connecting to a secondary server). - * - **promoteLongs** {Boolean, default:true}, when deserializing a Long will fit it into a Number if it's smaller than 53 bits - * - **bufferMaxEntries** {Number, default: -1}, sets a cap on how many operations the driver will buffer up before giving up on getting a working connection, default is -1 which is unlimited - * - * @class Represents a Db - * @param {String} databaseName name of the database. - * @param {Object} serverConfig server config object. - * @param {Object} [options] additional options for the collection. - */ -function Db(databaseName, serverConfig, options) { - if(!(this instanceof Db)) return new Db(databaseName, serverConfig, options); - EventEmitter.call(this); - var self = this; - this.databaseName = databaseName; - this.serverConfig = serverConfig; - this.options = options == null ? {} : options; - // State to check against if the user force closed db - this._applicationClosed = false; - // Fetch the override flag if any - var overrideUsedFlag = this.options['override_used_flag'] == null ? false : this.options['override_used_flag']; - - // Verify that nobody is using this config - if(!overrideUsedFlag && this.serverConfig != null && typeof this.serverConfig == 'object' && this.serverConfig._isUsed && this.serverConfig._isUsed()) { - throw new Error('A Server or ReplSet instance cannot be shared across multiple Db instances'); - } else if(!overrideUsedFlag && typeof this.serverConfig == 'object'){ - // Set being used - this.serverConfig._used = true; - } - - // Allow slaveOk override - this.slaveOk = this.options['slave_ok'] == null ? false : this.options['slave_ok']; - this.slaveOk = this.options['slaveOk'] == null ? this.slaveOk : this.options['slaveOk']; - - // Number of operations to buffer before failure - this.bufferMaxEntries = typeof this.options['bufferMaxEntries'] == 'number' ? this.options['bufferMaxEntries'] : -1; - - // Ensure we have a valid db name - validateDatabaseName(databaseName); - - // Contains all the connections for the db - try { - this.native_parser = this.options.native_parser; - // The bson lib - var bsonLib = this.bsonLib = this.options.native_parser ? require('bson').BSONNative : require('bson').BSONPure; - bsonLib = require('bson').BSONPure; - // Fetch the serializer object - var BSON = bsonLib.BSON; - - // Create a new instance - this.bson = new BSON([bsonLib.Long, bsonLib.ObjectID, bsonLib.Binary, bsonLib.Code, bsonLib.DBRef, bsonLib.Symbol, bsonLib.Double, bsonLib.Timestamp, bsonLib.MaxKey, bsonLib.MinKey]); - this.bson.promoteLongs = this.options.promoteLongs == null ? true : this.options.promoteLongs; - - // Backward compatibility to access types - this.bson_deserializer = bsonLib; - this.bson_serializer = bsonLib; - - // Add any overrides to the serializer and deserializer - this.bson_deserializer.promoteLongs = this.options.promoteLongs == null ? true : this.options.promoteLongs; - } catch (err) { - // If we tried to instantiate the native driver - var msg = 'Native bson parser not compiled, please compile ' - + 'or avoid using native_parser=true'; - throw Error(msg); - } - - // Internal state of the server - this._state = 'disconnected'; - - this.pkFactory = this.options.pkFactory == null ? bsonLib.ObjectID : this.options.pkFactory; - this.forceServerObjectId = this.options.forceServerObjectId != null ? this.options.forceServerObjectId : false; - - // Added safe - this.safe = this.options.safe == null ? false : this.options.safe; - - // If we have not specified a "safe mode" we just print a warning to the console - if(this.options.safe == null - && this.options.w == null - && this.options.j == null - && this.options.journal == null - && this.options.fsync == null) { - console.log("========================================================================================"); - console.log("= Please ensure that you set the default write concern for the database by setting ="); - console.log("= one of the options ="); - console.log("= ="); - console.log("= w: (value of > -1 or the string 'majority'), where < 1 means ="); - console.log("= no write acknowledgement ="); - console.log("= journal: true/false, wait for flush to journal before acknowledgement ="); - console.log("= fsync: true/false, wait for flush to file system before acknowledgement ="); - console.log("= ="); - console.log("= For backward compatibility safe is still supported and ="); - console.log("= allows values of [true | false | {j:true} | {w:n, wtimeout:n} | {fsync:true}] ="); - console.log("= the default value is false which means the driver receives does not ="); - console.log("= return the information of the success/error of the insert/update/remove ="); - console.log("= ="); - console.log("= ex: new Db(new Server('localhost', 27017), {safe:false}) ="); - console.log("= ="); - console.log("= http://www.mongodb.org/display/DOCS/getLastError+Command ="); - console.log("= ="); - console.log("= The default of no acknowledgement will change in the very near future ="); - console.log("= ="); - console.log("= This message will disappear when the default safe is set on the driver Db ="); - console.log("========================================================================================"); - } - - // Internal states variables - this.notReplied ={}; - this.isInitializing = true; - this.openCalled = false; - - // Command queue, keeps a list of incoming commands that need to be executed once the connection is up - this.commands = []; - - // Set up logger - this.logger = this.options.logger != null - && (typeof this.options.logger.debug == 'function') - && (typeof this.options.logger.error == 'function') - && (typeof this.options.logger.log == 'function') - ? this.options.logger : {error:function(message, object) {}, log:function(message, object) {}, debug:function(message, object) {}}; - - // Associate the logger with the server config - this.serverConfig.logger = this.logger; - if(this.serverConfig.strategyInstance) this.serverConfig.strategyInstance.logger = this.logger; - this.tag = new Date().getTime(); - // Just keeps list of events we allow - this.eventHandlers = {error:[], parseError:[], poolReady:[], message:[], close:[]}; - - // Controls serialization options - this.serializeFunctions = this.options.serializeFunctions != null ? this.options.serializeFunctions : false; - - // Raw mode - this.raw = this.options.raw != null ? this.options.raw : false; - - // Record query stats - this.recordQueryStats = this.options.recordQueryStats != null ? this.options.recordQueryStats : false; - - // If we have server stats let's make sure the driver objects have it enabled - if(this.recordQueryStats == true) { - this.serverConfig.enableRecordQueryStats(true); - } - - // Retry information - this.retryMiliSeconds = this.options.retryMiliSeconds != null ? this.options.retryMiliSeconds : 1000; - this.numberOfRetries = this.options.numberOfRetries != null ? this.options.numberOfRetries : 60; - - // Set default read preference if any - this.readPreference = this.options.readPreference; - - // Set slaveOk if we have specified a secondary or secondary preferred readPreference - if(this.readPreference == ReadPreference.SECONDARY || - this.readPreference == ReadPreference.SECONDARY_PREFERRED) { - this.slaveOk = true; - } - - // Set read preference on serverConfig if none is set - // but the db one was - if(this.serverConfig.options.readPreference != null) { - this.serverConfig.setReadPreference(this.serverConfig.options.readPreference); - } else if(this.readPreference != null) { - this.serverConfig.setReadPreference(this.readPreference); - } - - // Ensure we keep a reference to this db - this.serverConfig._dbStore.add(this); -}; - -/** - * @ignore - */ -function validateDatabaseName(databaseName) { - if(typeof databaseName !== 'string') throw new Error("database name must be a string"); - if(databaseName.length === 0) throw new Error("database name cannot be the empty string"); - if(databaseName == '$external') return; - - var invalidChars = [" ", ".", "$", "/", "\\"]; - for(var i = 0; i < invalidChars.length; i++) { - if(databaseName.indexOf(invalidChars[i]) != -1) throw new Error("database names cannot contain the character '" + invalidChars[i] + "'"); - } -} - -/** - * @ignore - */ -inherits(Db, EventEmitter); - -/** - * Initialize the database connection. - * - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the index information or null if an error occurred. - * @return {null} - * @api public - */ -Db.prototype.open = function(callback) { - var self = this; - - // Check that the user has not called this twice - if(this.openCalled) { - // Close db - this.close(); - // Throw error - throw new Error("db object already connecting, open cannot be called multiple times"); - } - - // If we have a specified read preference - if(this.readPreference != null) this.serverConfig.setReadPreference(this.readPreference); - - // Set that db has been opened - this.openCalled = true; - - // Set the status of the server - self._state = 'connecting'; - - // Set up connections - if(self.serverConfig instanceof Server || self.serverConfig instanceof ReplSet || self.serverConfig instanceof Mongos) { - // Ensure we have the original options passed in for the server config - var connect_options = {}; - for(var name in self.serverConfig.options) { - connect_options[name] = self.serverConfig.options[name] - } - connect_options.firstCall = true; - - // Attempt to connect - self.serverConfig.connect(self, connect_options, function(err, result) { - if(err != null) { - // Close db to reset connection - return self.close(function () { - // Return error from connection - return callback(err, null); - }); - } - // Set the status of the server - self._state = 'connected'; - // If we have queued up commands execute a command to trigger replays - if(self.commands.length > 0) _execute_queued_command(self); - // Callback - process.nextTick(function() { - try { - callback(null, self); - } catch(err) { - self.close(); - throw err; - } - }); - }); - } else { - try { - callback(Error("Server parameter must be of type Server, ReplSet or Mongos"), null); - } catch(err) { - self.close(); - throw err; - } - } -}; - -/** - * Create a new Db instance sharing the current socket connections. - * - * @param {String} dbName the name of the database we want to use. - * @return {Db} a db instance using the new database. - * @api public - */ -Db.prototype.db = function(dbName) { - // Copy the options and add out internal override of the not shared flag - var options = {}; - for(var key in this.options) { - options[key] = this.options[key]; - } - - // Add override flag - options['override_used_flag'] = true; - // Check if the db already exists and reuse if it's the case - var db = this.serverConfig._dbStore.fetch(dbName); - - // Create a new instance - if(!db) { - db = new Db(dbName, this.serverConfig, options); - } - - // Return the db object - return db; -}; - -/** - * Close the current db connection, including all the child db instances. Emits close event and calls optional callback. - * - * @param {Boolean} [forceClose] connection can never be reused. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results or null if an error occurred. - * @return {null} - * @api public - */ -Db.prototype.close = function(forceClose, callback) { - var self = this; - // Ensure we force close all connections - this._applicationClosed = false; - - if(typeof forceClose == 'function') { - callback = forceClose; - } else if(typeof forceClose == 'boolean') { - this._applicationClosed = forceClose; - } - - this.serverConfig.close(function(err, result) { - // You can reuse the db as everything is shut down - self.openCalled = false; - // If we have a callback call it - if(callback) callback(err, result); - }); -}; - -/** - * Access the Admin database - * - * @param {Function} [callback] returns the results. - * @return {Admin} the admin db object. - * @api public - */ -Db.prototype.admin = function(callback) { - if(callback == null) return new Admin(this); - callback(null, new Admin(this)); -}; - -/** - * Get the list of all collection names for the specified db - * - * Options - * - **namesOnly** {String, default:false}, Return only the full collection namespace. - * - **filter** {String|Object, default:null}, Filter collections by this filter (string or object) - * - * @param {String} [collectionName] the collection name we wish to filter by. - * @param {Object} [options] additional options during update. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the collection names or null if an error occurred. - * @return {null} - * @api public - */ -Db.prototype.listCollections = function(name, options, callback) { - var args = Array.prototype.slice.call(arguments, 0); - callback = args.pop(); - name = args.length ? args.shift() : null; - options = args.length ? args.shift() || {} : {}; - var self = this; - - // Only passed in options - if(name != null && typeof name == 'object') options = name, name = null; - // Do we have a filter - var filter = options.filter || {}; - - // Fallback to pre 2.8 list collections - var fallbackListCollections = function() { - // Ensure we have a filter - filter = filter || {}; - // Set the name variable for the filter - if(typeof name == 'string') filter.name = f("%s.%s", self.databaseName, name); - // Get the system namespace collection as a cursor - var cursor = self.collection(DbCommand.SYSTEM_NAMESPACE_COLLECTION).find(filter); - // Get all documents - cursor.toArray(function(err, documents) { - if(err != null) return callback(err, null); - - // Filter out all the non valid names - var filtered_documents = documents.filter(function(document) { - if(document.name.indexOf('$') != -1) return false; - return true; - }); - - // If we are returning only the names - if(options.namesOnly) { - filtered_documents = filtered_documents.map(function(document) { return document.name }); - } - - // Return filtered items - callback(null, filtered_documents); - }); - } - - // Set up the listCollectionsCommand - var listCollectionsCommand = {listCollections:1}; - // Add the optional filter if available - if(filter) listCollectionsCommand.filter = filter; - // Set the name variable for the filter - if(typeof name == 'string') filter.name = name; - - // Attempt to execute the collection list - self.command(listCollectionsCommand, function(err, result) { - if(err) return fallbackListCollections(); - // List of result documents that have been filtered - var filtered_documents = result.collections.filter(function(document) { - if(name && document.name != name) return false; - if(document.name.indexOf('$') != -1) return false; - return true; - }); - - // If we are returning only the names - if(options.namesOnly) { - filtered_documents = filtered_documents.map(function(document) { return document.name }); - } - - // Return filtered items - callback(null, filtered_documents); - }); -}; - -/** - * Get the list of all collection names for the specified db - * - * Options - * - **namesOnly** {String, default:false}, Return only the full collection namespace. - * - * @param {String} [collectionName] the collection name we wish to filter by. - * @param {Object} [options] additional options during update. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the collection names or null if an error occurred. - * @return {null} - * @api public - */ -Db.prototype.collectionNames = function(collectionName, options, callback) { - var args = Array.prototype.slice.call(arguments, 0); - this.listCollections.apply(this, args); -}; - -/** - * Fetch a specific collection (containing the actual collection information). If the application does not use strict mode you can - * can use it without a callback in the following way. var collection = db.collection('mycollection'); - * - * Options -* - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowledgement of write and w >= 1, w = 'majority' or tag acknowledges the write - * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) - * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal - * - **j**, (Boolean, default:false) write waits for journal sync before returning - * - **serializeFunctions** {Boolean, default:false}, serialize functions on the document. - * - **raw** {Boolean, default:false}, perform all operations using raw bson objects. - * - **pkFactory** {Object}, object overriding the basic ObjectID primary key generation. - * - **readPreference** {String}, the preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). - * - **strict**, (Boolean, default:false) returns an error if the collection does not exist - * - * @param {String} collectionName the collection name we wish to access. - * @param {Object} [options] returns option results. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the collection or null if an error occurred. - * @return {null} - * @api public - */ -Db.prototype.collection = function(collectionName, options, callback) { - if(typeof options == 'function') callback = options, options = {}; - options = options || {}; - var self = this; - - if(options == null || !options.strict) { - try { - var collection = new Collection(self, collectionName, self.pkFactory, options); - if(callback) callback(null, collection); - return collection; - } catch(err) { - if(callback) return callback(err); - throw err; - } - } - - // Strict mode - if(typeof callback != 'function') { - throw utils.toError(f("A callback is required in strict mode. While getting collection %s.", collectionName)); - } - - self.listCollections(collectionName, function(err, collections) { - if(err != null) return callback(err, null); - if(collections.length == 0) return callback(utils.toError(f("Collection %s does not exist. Currently in strict mode.", collectionName)), null); - - try { - return callback(null, new Collection(self, collectionName, self.pkFactory, options)); - } catch(err) { - return callback(err, null); - } - }); -}; - -/** - * Fetch all collections for the current db. - * - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the collections or null if an error occurred. - * @return {null} - * @api public - */ -Db.prototype.collections = function(callback) { - var self = this; - // Let's get the collection names - self.collectionNames(function(err, documents) { - if(err != null) return callback(err, null); - var collections = []; - documents.forEach(function(document) { - collections.push(new Collection(self, document.name.replace(self.databaseName + ".", ''), self.pkFactory)); - }); - // Return the collection objects - callback(null, collections); - }); -}; - -/** - * Evaluate javascript on the server - * - * Options - * - **nolock** {Boolean, default:false}, Tell MongoDB not to block on the evaulation of the javascript. - * - * @param {Code} code javascript to execute on server. - * @param {Object|Array} [parameters] the parameters for the call. - * @param {Object} [options] the options - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from eval or null if an error occurred. - * @return {null} - * @api public - */ -Db.prototype.eval = function(code, parameters, options, callback) { - // Unpack calls - var args = Array.prototype.slice.call(arguments, 1); - callback = args.pop(); - parameters = args.length ? args.shift() : parameters; - options = args.length ? args.shift() || {} : {}; - - var finalCode = code; - var finalParameters = []; - // If not a code object translate to one - if(!(finalCode instanceof this.bsonLib.Code)) { - finalCode = new this.bsonLib.Code(finalCode); - } - - // Ensure the parameters are correct - if(parameters != null && parameters.constructor != Array && typeof parameters !== 'function') { - finalParameters = [parameters]; - } else if(parameters != null && parameters.constructor == Array && typeof parameters !== 'function') { - finalParameters = parameters; - } - - // Create execution selector - var cmd = {'$eval':finalCode, 'args':finalParameters}; - // Check if the nolock parameter is passed in - if(options['nolock']) { - cmd['nolock'] = options['nolock']; - } - - // Set primary read preference - options.readPreference = ReadPreference.PRIMARY; - - // Execute the command - this.command(cmd, options, function(err, result) { - if(err) return callback(err, null); - if(result && result.ok == 1) return callback(null, result.retval); - if(result) return callback(new Error("eval failed: " + result.errmsg), null); - callback(err, result); - }); -}; - -/** - * Dereference a dbref, against a db - * - * @param {DBRef} dbRef db reference object we wish to resolve. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from dereference or null if an error occurred. - * @return {null} - * @api public - */ -Db.prototype.dereference = function(dbRef, callback) { - var db = this; - // If we have a db reference then let's get the db first - if(dbRef.db != null) db = this.db(dbRef.db); - // Fetch the collection and find the reference - var collection = db.collection(dbRef.namespace); - collection.findOne({'_id':dbRef.oid}, function(err, result) { - callback(err, result); - }); -} - -/** - * Logout user from server, fire off on all connections and remove all auth info - * - * Options - * - **authMechanism** {String, default:MONGODB-CR}, The authentication mechanism to use, GSSAPI or MONGODB-CR - * - **authdb** {String}, The Db to authenticate against instead of this - * - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from logout or null if an error occurred. - * @param {Object} [options] the options - * @return {null} - * @api public - */ -Db.prototype.logout = function(options, callback) { - var self = this; - // Unpack calls - var args = Array.prototype.slice.call(arguments, 0); - callback = args.pop(); - options = args.length ? args.shift() || {} : {}; - - // We have passed in an auth db - var runDb = options.authdb ? this.db(options.authdb) : this; - - // Number of connections we need to logout from - var numberOfConnections = this.serverConfig.allRawConnections().length; - // logout command - var cmd = {'logout':1}; - // Add onAll to login to ensure all connection are logged out - options.onAll = true; - - // Execute the command - runDb.command(cmd, options, function(err, result) { - // Count down - numberOfConnections = numberOfConnections - 1; - // Work around the case where the number of connections are 0 - if(numberOfConnections == 0 && typeof callback == 'function') { - var internalCallback = callback; - callback = null; - - // Remove the db from auths - self.serverConfig.auth.remove(self.databaseName); - // Callback with result - internalCallback(null, result.ok == 1 ? true : false); - } - }); -} - -/** - * Authenticate a user against the server. - * authMechanism - * Options - * - **authMechanism** {String, default:MONGODB-CR}, The authentication mechanism to use, GSSAPI or MONGODB-CR - * - **authdb** {String}, The Db to authenticate against instead of this - * - * @param {String} username username. - * @param {String} password password. - * @param {Object} [options] the options - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from authentication or null if an error occurred. - * @return {null} - * @api public - */ -Db.prototype.authenticate = function(username, password, options, callback) { - var self = this; - - if(typeof options == 'function') { - callback = options; - options = {}; - } - - // Set default mechanism - if(!options.authMechanism) { - options.authMechanism = 'DEFAULT'; - } else if(options.authMechanism != 'GSSAPI' - && options.authMechanism != 'MONGODB-CR' - && options.authMechanism != 'MONGODB-X509' - && options.authMechanism != 'SCRAM-SHA-1' - && options.authMechanism != 'PLAIN') { - return callback(new Error("only GSSAPI, PLAIN, MONGODB-X509, SCRAM-SHA-1 or MONGODB-CR is supported by authMechanism")); - } - - // the default db to authenticate against is 'this' - // if authententicate is called from a retry context, it may be another one, like admin - var authdb = options.authdb ? options.authdb : self.databaseName; - authdb = options.authSource ? options.authSource : authdb; - - // Callback - var _callback = function(err, result) { - if(self.listeners("authenticated").length > 0) { - self.emit("authenticated", err, result); - } - - // Return to caller - callback(err, result); - } - - // If classic auth delegate to auth command - if(options.authMechanism == 'MONGODB-CR') { - mongodb_cr_authenticate(self, username, password, authdb, options, _callback); - } else if(options.authMechanism == 'PLAIN') { - mongodb_plain_authenticate(self, username, password, options, _callback); - } else if(options.authMechanism == 'MONGODB-X509') { - mongodb_x509_authenticate(self, username, password, options, _callback); - } else if(options.authMechanism == 'SCRAM-SHA-1') { - mongodb_scram_authenticate(self, username, password, authdb, options, _callback); - } else if(options.authMechanism == 'DEFAULT') { - // Get a server - var servers = this.serverConfig.allServerInstances(); - // if the max wire protocol version >= 3 do scram otherwise mongodb_cr - if(servers.length > 0 && servers[0].isMasterDoc && servers[0].isMasterDoc.maxWireVersion >= 3) { - mongodb_scram_authenticate(self, username, password, authdb, options, _callback); - } else { - mongodb_cr_authenticate(self, username, password, authdb, options, _callback); - } - } else if(options.authMechanism == 'GSSAPI') { - // - // Kerberos library is not installed, throw and error - if(hasKerberos == false) { - console.log("========================================================================================"); - console.log("= Please make sure that you install the Kerberos library to use GSSAPI ="); - console.log("= ="); - console.log("= npm install -g kerberos ="); - console.log("= ="); - console.log("= The Kerberos package is not installed by default for simplicities sake ="); - console.log("= and needs to be global install ="); - console.log("========================================================================================"); - throw new Error("Kerberos library not installed"); - } - - if(process.platform == 'win32') { - mongodb_sspi_authenticate(self, username, password, authdb, options, _callback); - } else { - // We have the kerberos library, execute auth process - mongodb_gssapi_authenticate(self, username, password, authdb, options, _callback); - } - } -}; - -/** - * Add a user to the database. - * - * Options - * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowledgement of write and w >= 1, w = 'majority' or tag acknowledges the write - * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) - * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal - * - **j**, (Boolean, default:false) write waits for journal sync before returning - * - **customData**, (Object, default:{}) custom data associated with the user (only Mongodb 2.6 or higher) - * - **roles**, (Array, default:[]) roles associated with the created user (only Mongodb 2.6 or higher) - * - * @param {String} username username. - * @param {String} password password. - * @param {Object} [options] additional options during update. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from addUser or null if an error occurred. - * @return {null} - * @api public - */ -Db.prototype.addUser = function(username, password, options, callback) { - // Checkout a write connection to get the server capabilities - var connection = this.serverConfig.checkoutWriter(); - if(connection != null - && connection.serverCapabilities != null - && connection.serverCapabilities.hasAuthCommands) { - return _executeAuthCreateUserCommand(this, username, password, options, callback); - } - - // Unpack the parameters - var self = this; - var args = Array.prototype.slice.call(arguments, 2); - callback = args.pop(); - options = args.length ? args.shift() || {} : {}; - - // Get the error options - var errorOptions = _getWriteConcern(this, options); - errorOptions.w = errorOptions.w == null ? 1 : errorOptions.w; - // Use node md5 generator - var md5 = crypto.createHash('md5'); - // Generate keys used for authentication - md5.update(username + ":mongo:" + password); - var userPassword = md5.digest('hex'); - // Fetch a user collection - var collection = this.collection(DbCommand.SYSTEM_USER_COLLECTION); - // Check if we are inserting the first user - collection.count({}, function(err, count) { - // We got an error (f.ex not authorized) - if(err != null) return callback(err, null); - // Check if the user exists and update i - collection.find({user: username}, {dbName: options['dbName']}).toArray(function(err, documents) { - // We got an error (f.ex not authorized) - if(err != null) return callback(err, null); - // Add command keys - var commandOptions = errorOptions; - commandOptions.dbName = options['dbName']; - commandOptions.upsert = true; - - // We have a user, let's update the password or upsert if not - collection.update({user: username},{$set: {user: username, pwd: userPassword}}, commandOptions, function(err, results, full) { - if(count == 0 && err) { - callback(null, [{user:username, pwd:userPassword}]); - } else if(err) { - callback(err, null) - } else { - callback(null, [{user:username, pwd:userPassword}]); - } - }); - }); - }); -}; - -/** - * @ignore - */ -var _executeAuthCreateUserCommand = function(self, username, password, options, callback) { - // Special case where there is no password ($external users) - if(typeof username == 'string' - && password != null && typeof password == 'object') { - callback = options; - options = password; - password = null; - } - - // Unpack all options - if(typeof options == 'function') { - callback = options; - options = {}; - } - - // Error out if we digestPassword set - if(options.digestPassword != null) { - throw utils.toError("The digestPassword option is not supported via add_user. Please use db.command('createUser', ...) instead for this option."); - } - - // Get additional values - var customData = options.customData != null ? options.customData : {}; - var roles = Array.isArray(options.roles) ? options.roles : []; - var maxTimeMS = typeof options.maxTimeMS == 'number' ? options.maxTimeMS : null; - - // If not roles defined print deprecated message - if(roles.length == 0) { - console.log("Creating a user without roles is deprecated in MongoDB >= 2.6"); - } - - // Get the error options - var writeConcern = _getWriteConcern(self, options); - var commandOptions = {writeCommand:true}; - if(options['dbName']) commandOptions.dbName = options['dbName']; - - // Add maxTimeMS to options if set - if(maxTimeMS != null) commandOptions.maxTimeMS = maxTimeMS; - - // Check the db name and add roles if needed - if((self.databaseName.toLowerCase() == 'admin' || options.dbName == 'admin') && !Array.isArray(options.roles)) { - roles = ['root'] - } else if(!Array.isArray(options.roles)) { - roles = ['dbOwner'] - } - - // Build the command to execute - var command = { - createUser: username - , customData: customData - , roles: roles - , digestPassword:false - , writeConcern: writeConcern - } - - // Use node md5 generator - var md5 = crypto.createHash('md5'); - // Generate keys used for authentication - md5.update(username + ":mongo:" + password); - var userPassword = md5.digest('hex'); - - // No password - if(typeof password == 'string') { - command.pwd = userPassword; - } - - // Execute the command - self.command(command, commandOptions, function(err, result) { - if(err) return callback(err, null); - callback(!result.ok ? utils.toError("Failed to add user " + username) : null - , result.ok ? [{user: username, pwd: ''}] : null); - }) -} - -/** - * Remove a user from a database - * - * Options - * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowledgement of write and w >= 1, w = 'majority' or tag acknowledges the write - * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) - * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal - * - **j**, (Boolean, default:false) write waits for journal sync before returning - * - * @param {String} username username. - * @param {Object} [options] additional options during update. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from removeUser or null if an error occurred. - * @return {null} - * @api public - */ -Db.prototype.removeUser = function(username, options, callback) { - // Checkout a write connection to get the server capabilities - var connection = this.serverConfig.checkoutWriter(); - if(connection != null && connection.serverCapabilities != null && connection.serverCapabilities.hasAuthCommands) { - return _executeAuthRemoveUserCommand(this, username, options, callback); - } - - // Unpack the parameters - var self = this; - var args = Array.prototype.slice.call(arguments, 1); - callback = args.pop(); - options = args.length ? args.shift() || {} : {}; - - // Figure out the safe mode settings - var safe = self.safe != null && self.safe == false ? {w: 1} : self.safe; - // Override with options passed in if applicable - safe = options != null && options['safe'] != null ? options['safe'] : safe; - // Ensure it's at least set to safe - safe = safe == null ? {w: 1} : safe; - - // Fetch a user collection - var collection = this.collection(DbCommand.SYSTEM_USER_COLLECTION); - collection.findOne({user: username}, {dbName: options['dbName']}, function(err, user) { - if(user != null) { - // Add command keys - var commandOptions = safe; - commandOptions.dbName = options['dbName']; - - collection.remove({user: username}, commandOptions, function(err, result) { - callback(err, true); - }); - } else { - callback(err, false); - } - }); -}; - -var _executeAuthRemoveUserCommand = function(self, username, options, callback) { - // Unpack all options - if(typeof options == 'function') { - callback = options; - options = {}; - } - - // Get the error options - var writeConcern = _getWriteConcern(self, options); - var commandOptions = {writeCommand:true}; - if(options['dbName']) commandOptions.dbName = options['dbName']; - - // Get additional values - var maxTimeMS = typeof options.maxTimeMS == 'number' ? options.maxTimeMS : null; - - // Add maxTimeMS to options if set - if(maxTimeMS != null) commandOptions.maxTimeMS = maxTimeMS; - - // Build the command to execute - var command = { - dropUser: username - , writeConcern: writeConcern - } - - // Execute the command - self.command(command, commandOptions, function(err, result) { - if(err) return callback(err, null); - callback(null, result.ok ? true : false); - }) -} - -/** - * Creates a collection on a server pre-allocating space, need to create f.ex capped collections. - * - * Options -* - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowledgement of write and w >= 1, w = 'majority' or tag acknowledges the write - * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) - * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal - * - **j**, (Boolean, default:false) write waits for journal sync before returning - * - **serializeFunctions** {Boolean, default:false}, serialize functions on the document. - * - **raw** {Boolean, default:false}, perform all operations using raw bson objects. - * - **pkFactory** {Object}, object overriding the basic ObjectID primary key generation. - * - **capped** {Boolean, default:false}, create a capped collection. - * - **size** {Number}, the size of the capped collection in bytes. - * - **max** {Number}, the maximum number of documents in the capped collection. - * - **autoIndexId** {Boolean, default:true}, create an index on the _id field of the document, True by default on MongoDB 2.2 or higher off for version < 2.2. - * - **readPreference** {String}, the preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). - * - **strict**, (Boolean, default:false) throws an error if collection already exists - * - * @param {String} collectionName the collection name we wish to access. - * @param {Object} [options] returns option results. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from createCollection or null if an error occurred. - * @return {null} - * @api public - */ -Db.prototype.createCollection = function(collectionName, options, callback) { - var self = this; - if(typeof options == 'function') { - callback = options; - options = {}; - } - - // Figure out the safe mode settings - var safe = self.safe != null && self.safe == false ? {w: 1} : self.safe; - // Override with options passed in if applicable - safe = options != null && options['safe'] != null ? options['safe'] : safe; - // Ensure it's at least set to safe - safe = safe == null ? {w: 1} : safe; - // Check if we have the name - this.listCollections(collectionName, function(err, collections) { - if(err != null) return callback(err, null); - if(collections.length > 0 && options.strict) { - return callback(utils.toError(f("Collection %s already exists. Currently in strict mode.", collectionName)), null); - } else if (collections.length > 0) { - try { return callback(null, new Collection(self, collectionName, self.pkFactory, options)); } - catch(err) { return callback(err); } - } - - // logout command - var cmd = {'create':collectionName}; - - for(var name in options) { - if(options[name] != null && typeof options[name] != 'function') cmd[name] = options[name]; - } - - // Execute the command - self.command(cmd, options, function(err, result) { - if(err && err.code && err.code != 48 && options && options.strict) return callback(err, null); - try { - callback(null, new Collection(self, collectionName, self.pkFactory, options)); - } catch(err) { - callback(utils.toError(err), null); - } - }); - }); -}; - -var _getReadConcern = function(self, options) { - if(options.readPreference) return options.readPreference; - if(self.readPreference) return self.readPreference; - return 'primary'; -} - -/** - * Execute a command hash against MongoDB. This lets you acess any commands not available through the api on the server. - * - * Options - * - **readPreference** {String}, the preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). - * - **maxTimeMS** {Number}, number of milliseconds to wait before aborting the query. - * - **ignoreCommandFilter** {Boolean}, overrides the default redirection of certain commands to primary. - * - **writeCommand** {Boolean, default: false}, signals this is a write command and to ignore read preferences - * - **checkKeys** {Boolean, default: false}, overrides the default not to check the key names for the command - * - * @param {Object} selector the command hash to send to the server, ex: {ping:1}. - * @param {Object} [options] additional options for the command. - * @param {Function} callback this will be called after executing this method. The command always return the whole result of the command as the second parameter. - * @return {null} - * @api public - */ -Db.prototype.command = function(selector, options, callback) { - if(typeof options == 'function') { - callback = options; - options = {}; - } - - // Make a shallow copy so no modifications happen on the original - options = utils.shallowObjectCopy(options); - - // Ignore command preference (I know what I'm doing) - var ignoreCommandFilter = options.ignoreCommandFilter ? options.ignoreCommandFilter : false; - - // Get read preference if we set one - var readPreference = _getReadConcern(this, options); - - // Ensure only commands who support read Prefrences are exeuted otherwise override and use Primary - if(readPreference != false && ignoreCommandFilter == false) { - if(selector['group'] || selector['aggregate'] || selector['collStats'] || selector['dbStats'] - || selector['count'] || selector['distinct'] || selector['geoNear'] || selector['geoSearch'] - || selector['geoWalk'] || selector['text'] || selector['cursorInfo'] - || selector['parallelCollectionScan'] - || (selector['mapreduce'] && (selector.out == 'inline' || selector.out.inline))) { - // Set the read preference - options.readPreference = readPreference; - } else { - options.readPreference = ReadPreference.PRIMARY; - } - } else if(readPreference != false) { - options.readPreference = readPreference; - } - - // Add the maxTimeMS option to the command if specified - if(typeof options.maxTimeMS == 'number') { - selector.maxTimeMS = options.maxTimeMS - } - - // Command options - var command_options = {}; - - // Do we have an override for checkKeys - if(typeof options['checkKeys'] == 'boolean') command_options['checkKeys'] = options['checkKeys']; - command_options['checkKeys'] = typeof options['checkKeys'] == 'boolean' ? options['checkKeys'] : false; - if(typeof options['serializeFunctions'] == 'boolean') command_options['serializeFunctions'] = options['serializeFunctions']; - if(options['dbName']) command_options['dbName'] = options['dbName']; - - // If we have a write command, remove readPreference as an option - if((options.writeCommand - || selector['findAndModify'] - || selector['insert'] || selector['update'] || selector['delete'] - || selector['createUser'] || selector['updateUser'] || selector['removeUser']) - && options.readPreference) { - delete options['readPreference']; - } - - // Add a write concern if we have passed in any - if(options.w || options.wtimeout || options.j || options.fsync || options.safe) { - selector.writeConcern = {}; - if(options.safe) selector.writeConcern.w = 1; - if(options.w) selector.writeConcern.w = options.w; - if(options.wtimeout) selector.writeConcern.wtimeout = options.wtimeout; - if(options.j) selector.writeConcern.j = options.j; - if(options.fsync) selector.writeConcern.fsync = options.fsync; - } - - // If we have an actual writeConcern object override - if(options.writeConcern) { - selector.writeConcern = writeConcern; - } - - // Check if we need to set slaveOk - if(command_options.readPreference != 'primary') - command_options.slaveOk = true; - - // Execution db - var execDb = typeof options.auth == 'string' ? this.db(options.auth) : this; - execDb = typeof options.authdb == 'string' ? this.db(options.authdb) : execDb; - - // Execute a query command - this._executeQueryCommand(DbCommand.createDbSlaveOkCommand(execDb, selector, command_options), options, function(err, results, connection) { - if(options.returnConnection) { - if(err) return callback(err, null, connection); - if(results == null || results.documents == null) return callback(new Error("command failed to return result")); - if(results.documents[0].errmsg) - return callback(utils.toError(results.documents[0]), null, connection); - callback(null, results.documents[0], connection); - } else { - if(err) return callback(err, null); - if(results == null || results.documents == null) return callback(new Error("command failed to return result")); - if(results.documents[0].errmsg) - return callback(utils.toError(results.documents[0]), null); - callback(null, results.documents[0]); - } - }); -}; - -/** - * Drop a collection from the database, removing it permanently. New accesses will create a new collection. - * - * @param {String} collectionName the name of the collection we wish to drop. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from dropCollection or null if an error occurred. - * @return {null} - * @api public - */ -Db.prototype.dropCollection = function(collectionName, callback) { - var self = this; - callback || (callback = function(){}); - - // Command to execute - var cmd = {'drop':collectionName} - - // Execute the command - this.command(cmd, {}, function(err, result) { - if(err) return callback(err, null); - if(result.ok) return callback(null, true); - callback(null, false); - }); -}; - -/** - * Rename a collection. - * - * Options - * - **dropTarget** {Boolean, default:false}, drop the target name collection if it previously exists. - * - * @param {String} fromCollection the name of the current collection we wish to rename. - * @param {String} toCollection the new name of the collection. - * @param {Object} [options] returns option results. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from renameCollection or null if an error occurred. - * @return {null} - * @api public - */ -Db.prototype.renameCollection = function(fromCollection, toCollection, options, callback) { - var self = this; - - if(typeof options == 'function') { - callback = options; - options = {} - } - - // Add return new collection - options.new_collection = true; - - // Execute using the collection method - this.collection(fromCollection).rename(toCollection, options, callback); -}; - -/** - * Runs a command on the database. - * @ignore - * @api private - */ -Db.prototype.executeDbCommand = function(command_hash, options, callback) { - if(callback == null) { callback = options; options = {}; } - this._executeQueryCommand(DbCommand.createDbSlaveOkCommand(this, command_hash, options), options, function(err, result) { - if(callback) callback(err, result); - }); -}; - -/** - * Runs a command on the database as admin. - * @ignore - * @api private - */ -Db.prototype.executeDbAdminCommand = function(command_hash, options, callback) { - if(typeof options == 'function') { - callback = options; - options = {} - } - - if(options.readPreference) { - options.readPreference = options.readPreference; - } - - this._executeQueryCommand(DbCommand.createAdminDbCommand(this, command_hash), options, function(err, result) { - if(callback) callback(err, result); - }); -}; - -/** - * Creates an index on the collection. - * - * Options -* - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowledgement of write and w >= 1, w = 'majority' or tag acknowledges the write - * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) - * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal - * - **j**, (Boolean, default:false) write waits for journal sync before returning - * - **unique** {Boolean, default:false}, creates an unique index. - * - **sparse** {Boolean, default:false}, creates a sparse index. - * - **background** {Boolean, default:false}, creates the index in the background, yielding whenever possible. - * - **min** {Number}, for geospatial indexes set the lower bound for the co-ordinates. - * - **max** {Number}, for geospatial indexes set the high bound for the co-ordinates. - * - **v** {Number}, specify the format version of the indexes. - * - **expireAfterSeconds** {Number}, allows you to expire data on indexes applied to a data (MongoDB 2.2 or higher) - * - **name** {String}, override the autogenerated index name (useful if the resulting name is larger than 128 bytes) - * - * @param {String} collectionName name of the collection to create the index on. - * @param {Object} fieldOrSpec fieldOrSpec that defines the index. - * @param {Object} [options] additional options during update. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from createIndex or null if an error occurred. - * @return {null} - * @api public - */ -Db.prototype.createIndex = function(collectionName, fieldOrSpec, options, callback) { - var self = this; - var args = Array.prototype.slice.call(arguments, 2); - callback = args.pop(); - options = args.length ? args.shift() || {} : {}; - options = typeof callback === 'function' ? options : callback; - options = options == null ? {} : options; - - // Get the error options - var writeConcern = _getWriteConcern(self, options); - // Ensure we have a callback - if(_hasWriteConcern(writeConcern) && typeof callback != 'function') { - throw new Error("Cannot use a writeConcern without a provided callback"); - } - - // Attempt to run using createIndexes command - createIndexUsingCreateIndexes(self, collectionName, fieldOrSpec, options, function(err, result) { - if(err == null) { - return callback(err, result); - } - - // Create command - var command = createCreateIndexCommand(self, collectionName, fieldOrSpec, options); - // Default command options - var commandOptions = {}; - - // If we have error conditions set handle them - if(_hasWriteConcern(writeConcern) && typeof callback == 'function') { - // Set safe option - commandOptions['safe'] = writeConcern; - // If we have an error option - if(typeof writeConcern == 'object') { - var keys = Object.keys(writeConcern); - for(var i = 0; i < keys.length; i++) { - commandOptions[keys[i]] = writeConcern[keys[i]]; - } - } - - // Execute insert command - self._executeInsertCommand(command, commandOptions, function(err, result) { - if(err != null) return callback(err, null); - if(result == null || result.documents == null) return callback(new Error("command failed to return result")); - - result = result && result.documents; - if (result[0].err) { - callback(utils.toError(result[0])); - } else { - callback(null, command.documents[0].name); - } - }); - } else { - // Execute insert command - var result = self._executeInsertCommand(command, commandOptions, function() {}); - // If no callback just return - if(!callback) return; - // If error return error - if(result instanceof Error) { - return callback(result); - } - // Otherwise just return - return callback(null, null); - } - }); -}; - -var createCreateIndexCommand = function(db, collectionName, fieldOrSpec, options) { - var indexParameters = utils.parseIndexOptions(fieldOrSpec); - var fieldHash = indexParameters.fieldHash; - var keys = indexParameters.keys; - - // Generate the index name - var indexName = typeof options.name == 'string' - ? options.name - : indexParameters.name; - - var selector = { - 'ns': db.databaseName + "." + collectionName, - 'key': fieldHash, - 'name': indexName - } - - // Ensure we have a correct finalUnique - var finalUnique = options == null || 'object' === typeof options - ? false - : options; - - // Set up options - options = options == null || typeof options == 'boolean' - ? {} - : options; - - // Add all the options - var keysToOmit = Object.keys(selector); - for(var optionName in options) { - if(keysToOmit.indexOf(optionName) == -1) { - selector[optionName] = options[optionName]; - } - } - - if(selector['unique'] == null) - selector['unique'] = finalUnique; - - var name = db.databaseName + "." + DbCommand.SYSTEM_INDEX_COLLECTION; - var cmd = new InsertCommand(db, name, false); - return cmd.add(selector); -} - -var createIndexUsingCreateIndexes = function(self, collectionName, fieldOrSpec, options, callback) { - // Build the index - var indexParameters = utils.parseIndexOptions(fieldOrSpec); - // Generate the index name - var indexName = typeof options.name == 'string' - ? options.name - : indexParameters.name; - - // Set up the index - var indexes = [{ - name: indexName - , key: indexParameters.fieldHash - }]; - - // merge all the options - var keysToOmit = Object.keys(indexes[0]); - for(var optionName in options) { - if(keysToOmit.indexOf(optionName) == -1) { - indexes[0][optionName] = options[optionName]; - } - } - - // Create command - var command = {createIndexes: collectionName, indexes: indexes}; - // Build the command - self.command(command, options, function(err, result) { - if(err) return callback(err, null); - if(result.ok == 0) { - return callback(utils.toError(result), null); - } - - // Return the indexName for backward compatibility - callback(null, indexName); - }); -} - -/** - * Ensures that an index exists, if it does not it creates it - * - * Options - * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowledgement of write and w >= 1, w = 'majority' or tag acknowledges the write - * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) - * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal - * - **j**, (Boolean, default:false) write waits for journal sync before returning - * - **unique** {Boolean, default:false}, creates an unique index. - * - **sparse** {Boolean, default:false}, creates a sparse index. - * - **background** {Boolean, default:false}, creates the index in the background, yielding whenever possible. - * - **min** {Number}, for geospatial indexes set the lower bound for the co-ordinates. - * - **max** {Number}, for geospatial indexes set the high bound for the co-ordinates. - * - **v** {Number}, specify the format version of the indexes. - * - **expireAfterSeconds** {Number}, allows you to expire data on indexes applied to a data (MongoDB 2.2 or higher) - * - **name** {String}, override the autogenerated index name (useful if the resulting name is larger than 128 bytes) - * - * @param {String} collectionName name of the collection to create the index on. - * @param {Object} fieldOrSpec fieldOrSpec that defines the index. - * @param {Object} [options] additional options during update. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from ensureIndex or null if an error occurred. - * @return {null} - * @api public - */ -Db.prototype.ensureIndex = function(collectionName, fieldOrSpec, options, callback) { - var self = this; - - if(typeof callback === 'undefined' && typeof options === 'function') { - callback = options; - options = {}; - } - - // Ensure non empty options - options = options || {}; - - // Get the error options - var writeConcern = _getWriteConcern(this, options); - // Make sure we don't try to do a write concern without a callback - if(_hasWriteConcern(writeConcern) && callback == null) - throw new Error("Cannot use a writeConcern without a provided callback"); - - // Create command - var command = createCreateIndexCommand(this, collectionName, fieldOrSpec, options); - var index_name = command.documents[0].name; - - // Check if the index allready exists - this.indexInformation(collectionName, writeConcern, function(err, indexInformation) { - if(err != null) return callback(err, null); - // If the index does not exist, create it - if(!indexInformation[index_name]) { - self.createIndex(collectionName, fieldOrSpec, options, callback); - } else { - if(typeof callback === 'function') return callback(null, index_name); - } - }); -}; - -/** - * Returns the information available on allocated cursors. - * - * Options - * - **readPreference** {String}, the preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). - * - * @param {Object} [options] additional options during update. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from cursorInfo or null if an error occurred. - * @return {null} - * @api public - */ -Db.prototype.cursorInfo = function(options, callback) { - var args = Array.prototype.slice.call(arguments, 0); - callback = args.pop(); - options = args.length ? args.shift() || {} : {}; - - // cursorInfo command - var cmd = {'cursorInfo':1}; - - // Execute the command - this.command(cmd, options, function(err, result) { - if(err) return callback(err, null); - callback(null, result); - }); -}; - -/** - * Drop an index on a collection. - * - * @param {String} collectionName the name of the collection where the command will drop an index. - * @param {String} indexName name of the index to drop. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from dropIndex or null if an error occurred. - * @return {null} - * @api public - */ -Db.prototype.dropIndex = function(collectionName, indexName, options, callback) { - var args = Array.prototype.slice.call(arguments, 2); - callback = args.pop(); - options = args.length ? args.shift() || {} : {}; - - // Delete index command - var cmd = {'deleteIndexes':collectionName, 'index':indexName}; - - // Execute command - this.command(cmd, options, function(err, result) { - if(callback == null) return; - if(err) return callback(err, null); - callback(null, result); - }); -}; - -/** - * Reindex all indexes on the collection - * Warning: reIndex is a blocking operation (indexes are rebuilt in the foreground) and will be slow for large collections. - * - * @param {String} collectionName the name of the collection. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from reIndex or null if an error occurred. - * @api public -**/ -Db.prototype.reIndex = function(collectionName, options, callback) { - if(typeof options == 'function') { - callback = options; - options = {}; - } - - // Reindex - var cmd = {'reIndex':collectionName}; - - // Execute the command - this.command(cmd, options, function(err, result) { - if(callback == null) return; - if(err) return callback(err, null); - callback(null, result.ok ? true : false); - }); -}; - -/** - * Retrieves this collections index info. - * - * Options - * - **full** {Boolean, default:false}, returns the full raw index information. - * - **readPreference** {String}, the preferred read preference ((Server.PRIMARY, Server.PRIMARY_PREFERRED, Server.SECONDARY, Server.SECONDARY_PREFERRED, Server.NEAREST). - * - * @param {String} collectionName the name of the collection. - * @param {Object} [options] additional options during update. - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from indexInformation or null if an error occurred. - * @return {null} - * @api public - */ -Db.prototype.indexInformation = function(name, options, callback) { - if(typeof callback === 'undefined') { - if(typeof options === 'undefined') { - callback = name; - name = null; - } else { - callback = options; - } - options = {}; - } - - // Throw is no name provided - if(name == null) throw new Error("A collection name must be provided as first argument"); - - // If we specified full information - var full = options['full'] == null ? false : options['full']; - var self = this; - - // Process all the results from the index command and collection - var processResults = function(indexes) { - // Contains all the information - var info = {}; - // Process all the indexes - for(var i = 0; i < indexes.length; i++) { - var index = indexes[i]; - // Let's unpack the object - info[index.name] = []; - for(var name in index.key) { - info[index.name].push([name, index.key[name]]); - } - } - - return info; - } - - // Fallback to pre 2.8 getting the index information - var fallbackListIndexes = function() { - // Build selector for the indexes - var selector = name != null ? {ns: (self.databaseName + "." + name)} : {}; - - // Get read preference if we set one - var readPreference = ReadPreference.PRIMARY; - - // Iterate through all the fields of the index - var collection = self.collection(DbCommand.SYSTEM_INDEX_COLLECTION); - // Perform the find for the collection - collection.find(selector).setReadPreference(readPreference).toArray(function(err, indexes) { - if(err != null) return callback(err, null); - // if full defined just return all the indexes directly - if(full) return callback(null, indexes); - // Return all the indexes - callback(null, processResults(indexes)); - }); - } - - // Attempt to execute the listIndexes command - self.command({listIndexes: name}, function(err, result) { - if(err) return fallbackListIndexes(); - // if full defined just return all the indexes directly - if(full) return callback(null, result.indexes); - // Return all the indexes - callback(null, processResults(result.indexes)); - }); -}; - -/** - * Drop a database. - * - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from dropDatabase or null if an error occurred. - * @return {null} - * @api public - */ -Db.prototype.dropDatabase = function(options, callback) { - if(typeof options == 'function') { - callback = options; - options = {}; - } - - // Reindex - var cmd = {'dropDatabase':1}; - - // Execute the command - this.command(cmd, options, function(err, result) { - if(callback == null) return; - if(err) return callback(err, null); - callback(null, result.ok ? true : false); - }); -} - -/** - * Get all the db statistics. - * - * Options - * - **scale** {Number}, divide the returned sizes by scale value. - * - **readPreference** {String}, the preferred read preference ((Server.PRIMARY, Server.PRIMARY_PREFERRED, Server.SECONDARY, Server.SECONDARY_PREFERRED, Server.NEAREST). - * - * @param {Objects} [options] options for the stats command - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the results from stats or null if an error occurred. - * @return {null} - * @api public - */ -Db.prototype.stats = function stats(options, callback) { - var args = Array.prototype.slice.call(arguments, 0); - callback = args.pop(); - // Fetch all commands - options = args.length ? args.shift() || {} : {}; - - // Build command object - var commandObject = { - dbStats:true - }; - - // Check if we have the scale value - if(options['scale'] != null) commandObject['scale'] = options['scale']; - - // Execute the command - this.command(commandObject, options, callback); -} - -/** - * @ignore - */ -var bindToCurrentDomain = function(callback) { - var domain = process.domain; - if(domain == null || callback == null) { - return callback; - } else { - return domain.bind(callback); - } -} - -/** - * @ignore - */ -var __executeQueryCommand = function(self, db_command, options, callback) { - // Options unpacking - var readPreference = options.readPreference != null ? options.readPreference : 'primary'; - var onAll = options['onAll'] != null ? options['onAll'] : false; - var specifiedConnection = options['connection'] != null ? options['connection'] : null; - var raw = typeof options.raw == 'boolean' ? options.raw : false; - - // Correct readPreference preference to default primary if set to false, null or primary - if(!(typeof readPreference == 'object') && readPreference._type == 'ReadPreference') { - readPreference = (readPreference == null || readPreference == 'primary' || readPreference == false) ? ReadPreference.PRIMARY : readPreference; - if(!ReadPreference.isValid(readPreference)) return callback(new Error("Illegal readPreference mode specified, " + JSON.stringify(readPreference))); - } else if(typeof readPreference == 'object' && readPreference._type == 'ReadPreference') { - if(!readPreference.isValid()) return callback(new Error("Illegal readPreference mode specified, " + JSON.stringify(readPreference))); - } - - // If we have a read preference set and we are a mongos pass the read preference on to the mongos instance, - if(self.serverConfig.isMongos() && readPreference != null && readPreference != 'primary') { - db_command.setMongosReadPreference(readPreference); - } - - // If we got a callback object - if(typeof callback === 'function' && !onAll) { - callback = bindToCurrentDomain(callback); - // Override connection if we passed in a specific connection - var connection = specifiedConnection != null ? specifiedConnection : null; - - if(connection instanceof Error) return callback(connection, null); - - // Fetch either a reader or writer dependent on the specified readPreference option if no connection - // was passed in - if(connection == null) { - connection = self.serverConfig.checkoutReader(readPreference); - } - - if(connection == null) { - return callback(new Error("no open connections")); - } else if(connection instanceof Error || connection['message'] != null) { - return callback(connection); - } - - // Exhaust Option - var exhaust = options.exhaust || false; - - // Register the handler in the data structure - self.serverConfig._registerHandler(db_command, raw, connection, exhaust, callback); - - // Write the message out and handle any errors if there are any - connection.write(db_command, function(err) { - if(err != null) { - // Call the handler with an error - if(Array.isArray(db_command)) - self.serverConfig._callHandler(db_command[0].getRequestId(), null, err); - else - self.serverConfig._callHandler(db_command.getRequestId(), null, err); - } - }); - } else if(typeof callback === 'function' && onAll) { - callback = bindToCurrentDomain(callback); - var connections = self.serverConfig.allRawConnections(); - var numberOfEntries = connections.length; - // Go through all the connections - for(var i = 0; i < connections.length; i++) { - // Fetch a connection - var connection = connections[i]; - - // Ensure we have a valid connection - if(connection == null) { - return callback(new Error("no open connections")); - } else if(connection instanceof Error) { - return callback(connection); - } - - // Register the handler in the data structure - self.serverConfig._registerHandler(db_command, raw, connection, callback); - - // Write the message out - connection.write(db_command, function(err) { - // Adjust the number of entries we need to process - numberOfEntries = numberOfEntries - 1; - // Remove listener - if(err != null) { - // Clean up listener and return error - self.serverConfig._removeHandler(db_command.getRequestId()); - } - - // No more entries to process callback with the error - if(numberOfEntries <= 0) { - callback(err); - } - }); - - // Update the db_command request id - db_command.updateRequestId(); - } - } else { - // Fetch either a reader or writer dependent on the specified read option - var connection = self.serverConfig.checkoutReader(readPreference); - // Override connection if needed - connection = specifiedConnection != null ? specifiedConnection : connection; - // Ensure we have a valid connection - if(connection == null || connection instanceof Error || connection['message'] != null) return null; - // Write the message out - connection.write(db_command, function(err) { - if(err != null) { - // Emit the error - self.emit("error", err); - } - }); - } -}; - -/** - * Execute db query command (not safe) - * @ignore - * @api private - */ -Db.prototype._executeQueryCommand = function(db_command, options, callback) { - var self = this; - - // Unpack the parameters - if(typeof options === 'function') { - callback = options; - options = {}; - } - callback = bindToCurrentDomain(callback); - - // fast fail option used for HA, no retry - var failFast = options['failFast'] != null - ? options['failFast'] - : false; - - // Check if the user force closed the command - if(this._applicationClosed) { - var err = new Error("db closed by application"); - if('function' == typeof callback) { - return callback(err, null); - } else { - throw err; - } - } - - if(this.serverConfig.isDestroyed()) - return callback(new Error("Connection was destroyed by application")); - - // Specific connection - var connection = options.connection; - // Check if the connection is actually live - if(connection - && (!connection.isConnected || !connection.isConnected())) connection = null; - - // Get the configuration - var config = this.serverConfig; - var readPreference = options.readPreference; - // Allow for the usage of the readPreference model - if(readPreference == null) { - readPreference = options.readPreference; - } - - if(!connection && !config.canRead(readPreference) && !config.canWrite() && config.isAutoReconnect()) { - - if(readPreference == ReadPreference.PRIMARY - || readPreference == ReadPreference.PRIMARY_PREFERRED - || (readPreference != null && typeof readPreference == 'object' && readPreference.mode) - || readPreference == null) { - - // Save the command - self.serverConfig._commandsStore.read_from_writer( - { type: 'query' - , db_command: db_command - , options: options - , callback: callback - , db: self - , executeQueryCommand: __executeQueryCommand - , executeInsertCommand: __executeInsertCommand - } - ); - } else { - self.serverConfig._commandsStore.read( - { type: 'query' - , db_command: db_command - , options: options - , callback: callback - , db: self - , executeQueryCommand: __executeQueryCommand - , executeInsertCommand: __executeInsertCommand - } - ); - } - - // If we have blown through the number of items let's - if(!self.serverConfig._commandsStore.validateBufferLimit(self.bufferMaxEntries)) { - self.close(); - } - } else if(!connection && !config.canRead(readPreference) && !config.canWrite() && !config.isAutoReconnect()) { - return callback(new Error("no open connections"), null); - } else { - if(typeof callback == 'function') { - __executeQueryCommand(self, db_command, options, function (err, result, conn) { - callback(err, result, conn); - }); - } else { - __executeQueryCommand(self, db_command, options); - } - } -}; - -/** - * @ignore - */ -var __executeInsertCommand = function(self, db_command, options, callback) { - // Always checkout a writer for this kind of operations - var connection = self.serverConfig.checkoutWriter(); - // Get safe mode - var safe = options['safe'] != null ? options['safe'] : false; - var specifiedConnection = options['connection'] != null ? options['connection'] : null; - // Override connection if needed - connection = specifiedConnection != null ? specifiedConnection : connection; - - // Validate if we can use this server 2.6 wire protocol - if(connection && !connection.isCompatible()) { - return callback(utils.toError("driver is incompatible with this server version"), null); - } - - // Ensure we have a valid connection - if(typeof callback === 'function') { - callback = bindToCurrentDomain(callback); - // Ensure we have a valid connection - if(connection == null) { - return callback(new Error("no open connections")); - } else if(connection instanceof Error) { - return callback(connection); - } - - var errorOptions = _getWriteConcern(self, options); - if(errorOptions.w > 0 || errorOptions.w == 'majority' || errorOptions.j || errorOptions.journal || errorOptions.fsync) { - // db command is now an array of commands (original command + lastError) - db_command = [db_command, DbCommand.createGetLastErrorCommand(errorOptions, self)]; - // Register the handler in the data structure - self.serverConfig._registerHandler(db_command[1], false, connection, callback); - } - } - - // If we have no callback and there is no connection - if(connection == null) return null; - if(connection instanceof Error && typeof callback == 'function') return callback(connection, null); - if(connection instanceof Error) return null; - if(connection == null && typeof callback == 'function') return callback(new Error("no primary server found"), null); - - // Write the message out - connection.write(db_command, function(err) { - // Return the callback if it's not a safe operation and the callback is defined - if(typeof callback === 'function' && (safe == null || safe == false)) { - // Perform the callback - callback(err, null); - } else if(typeof callback === 'function') { - // Call the handler with an error - self.serverConfig._callHandler(db_command[1].getRequestId(), null, err); - } else if(typeof callback == 'function' && safe && safe.w == -1) { - // Call the handler with no error - self.serverConfig._callHandler(db_command[1].getRequestId(), null, null); - } else if(!safe || safe.w == -1) { - self.emit("error", err); - } - }); -}; - -/** - * Execute an insert Command - * @ignore - * @api private - */ -Db.prototype._executeInsertCommand = function(db_command, options, callback) { - var self = this; - - // Unpack the parameters - if(callback == null && typeof options === 'function') { - callback = options; - options = {}; - } - callback = bindToCurrentDomain(callback); - // Ensure options are not null - options = options == null ? {} : options; - - // Check if the user force closed the command - if(this._applicationClosed) { - if(typeof callback == 'function') { - return callback(new Error("db closed by application"), null); - } else { - throw new Error("db closed by application"); - } - } - - if(this.serverConfig.isDestroyed()) return callback(new Error("Connection was destroyed by application")); - - // Specific connection - var connection = options.connection; - // Check if the connection is actually live - if(connection - && (!connection.isConnected || !connection.isConnected())) connection = null; - - // Get config - var config = self.serverConfig; - // Check if we are connected - if(!connection && !config.canWrite() && config.isAutoReconnect()) { - self.serverConfig._commandsStore.write( - { type:'insert' - , 'db_command':db_command - , 'options':options - , 'callback':callback - , db: self - , executeQueryCommand: __executeQueryCommand - , executeInsertCommand: __executeInsertCommand - } - ); - - // If we have blown through the number of items let's - if(!self.serverConfig._commandsStore.validateBufferLimit(self.bufferMaxEntries)) { - self.close(); - } - } else if(!connection && !config.canWrite() && !config.isAutoReconnect()) { - return callback(new Error("no open connections"), null); - } else { - __executeInsertCommand(self, db_command, options, callback); - } -}; - -/** - * Update command is the same - * @ignore - * @api private - */ -Db.prototype._executeUpdateCommand = Db.prototype._executeInsertCommand; -/** - * Remove command is the same - * @ignore - * @api private - */ -Db.prototype._executeRemoveCommand = Db.prototype._executeInsertCommand; - -/** - * Wrap a Mongo error document into an Error instance. - * Deprecated. Use utils.toError instead. - * - * @ignore - * @api private - * @deprecated - */ -Db.prototype.wrap = utils.toError; - -/** - * Default URL - * - * @classconstant DEFAULT_URL - **/ -Db.DEFAULT_URL = 'mongodb://localhost:27017/default'; - -/** - * Connect to MongoDB using a url as documented at - * - * docs.mongodb.org/manual/reference/connection-string/ - * - * Options - * - **uri_decode_auth** {Boolean, default:false} uri decode the user name and password for authentication - * - **db** {Object, default: null} a hash off options to set on the db object, see **Db constructor** - * - **server** {Object, default: null} a hash off options to set on the server objects, see **Server** constructor** - * - **replSet** {Object, default: null} a hash off options to set on the replSet object, see **ReplSet** constructor** - * - **mongos** {Object, default: null} a hash off options to set on the mongos object, see **Mongos** constructor** - * - * @param {String} url connection url for MongoDB. - * @param {Object} [options] optional options for insert command - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occurred, or null otherwise. While the second parameter will contain the db instance or null if an error occurred. - * @return {null} - * @api public - */ -Db.connect = function(url, options, callback) { - // Ensure correct mapping of the callback - if(typeof options == 'function') { - callback = options; - options = {}; - } - - // Ensure same behavior as previous version w:0 - if(url.indexOf("safe") == -1 - && url.indexOf("w") == -1 - && url.indexOf("journal") == -1 && url.indexOf("j") == -1 - && url.indexOf("fsync") == -1) options.w = 1; - - // Avoid circular require problem - var MongoClient = require('./mongo_client.js').MongoClient; - // Attempt to connect - MongoClient.connect.call(MongoClient, url, options, callback); -}; - -/** - * State of the db connection - * @ignore - */ -Object.defineProperty(Db.prototype, "state", { enumerable: true - , get: function () { - return this.serverConfig._serverState; - } -}); - -/** - * @ignore - */ -var _hasWriteConcern = function(errorOptions) { - return errorOptions == true - || errorOptions.w > 0 - || errorOptions.w == 'majority' - || errorOptions.j == true - || errorOptions.journal == true - || errorOptions.fsync == true -}; - -/** - * @ignore - */ -var _setWriteConcernHash = function(options) { - var finalOptions = {}; - if(options.w != null) finalOptions.w = options.w; - if(options.journal == true) finalOptions.j = options.journal; - if(options.j == true) finalOptions.j = options.j; - if(options.fsync == true) finalOptions.fsync = options.fsync; - if(options.wtimeout != null) finalOptions.wtimeout = options.wtimeout; - return finalOptions; -}; - -/** - * @ignore - */ -var _getWriteConcern = function(self, options) { - // Final options - var finalOptions = {w:1}; - // Local options verification - if(options.w != null || typeof options.j == 'boolean' || typeof options.journal == 'boolean' || typeof options.fsync == 'boolean') { - finalOptions = _setWriteConcernHash(options); - } else if(options.safe != null && typeof options.safe == 'object') { - finalOptions = _setWriteConcernHash(options.safe); - } else if(typeof options.safe == "boolean") { - finalOptions = {w: (options.safe ? 1 : 0)}; - } else if(self.options.w != null || typeof self.options.j == 'boolean' || typeof self.options.journal == 'boolean' || typeof self.options.fsync == 'boolean') { - finalOptions = _setWriteConcernHash(self.options); - } else if(self.safe.w != null || typeof self.safe.j == 'boolean' || typeof self.safe.journal == 'boolean' || typeof self.safe.fsync == 'boolean') { - finalOptions = _setWriteConcernHash(self.safe); - } else if(typeof self.safe == "boolean") { - finalOptions = {w: (self.safe ? 1 : 0)}; - } - - // Ensure we don't have an invalid combination of write concerns - if(finalOptions.w < 1 - && (finalOptions.journal == true || finalOptions.j == true || finalOptions.fsync == true)) throw new Error("No acknowledgement using w < 1 cannot be combined with journal:true or fsync:true"); - - // Return the options - return finalOptions; -} - -/** - * Legacy support - * - * @ignore - * @api private - */ -exports.connect = Db.connect; -exports.Db = Db; - -/** - * Remove all listeners to the db instance. - * @ignore - * @api private - */ -Db.prototype.removeAllEventListeners = function() { - this.removeAllListeners("close"); - this.removeAllListeners("error"); - this.removeAllListeners("timeout"); - this.removeAllListeners("parseError"); - this.removeAllListeners("poolReady"); - this.removeAllListeners("message"); -}; diff --git a/node_modules/mongodb/lib/mongodb/gridfs/chunk.js b/node_modules/mongodb/lib/mongodb/gridfs/chunk.js deleted file mode 100644 index 8cddafe..0000000 --- a/node_modules/mongodb/lib/mongodb/gridfs/chunk.js +++ /dev/null @@ -1,232 +0,0 @@ -var Binary = require('bson').Binary, - ObjectID = require('bson').ObjectID; - -/** - * Class for representing a single chunk in GridFS. - * - * @class - * - * @param file {GridStore} The {@link GridStore} object holding this chunk. - * @param mongoObject {object} The mongo object representation of this chunk. - * - * @throws Error when the type of data field for {@link mongoObject} is not - * supported. Currently supported types for data field are instances of - * {@link String}, {@link Array}, {@link Binary} and {@link Binary} - * from the bson module - * - * @see Chunk#buildMongoObject - */ -var Chunk = exports.Chunk = function(file, mongoObject, writeConcern) { - if(!(this instanceof Chunk)) return new Chunk(file, mongoObject); - - this.file = file; - var self = this; - var mongoObjectFinal = mongoObject == null ? {} : mongoObject; - this.writeConcern = writeConcern || {w:1}; - this.objectId = mongoObjectFinal._id == null ? new ObjectID() : mongoObjectFinal._id; - this.chunkNumber = mongoObjectFinal.n == null ? 0 : mongoObjectFinal.n; - this.data = new Binary(); - - if(mongoObjectFinal.data == null) { - } else if(typeof mongoObjectFinal.data == "string") { - var buffer = new Buffer(mongoObjectFinal.data.length); - buffer.write(mongoObjectFinal.data, 'binary', 0); - this.data = new Binary(buffer); - } else if(Array.isArray(mongoObjectFinal.data)) { - var buffer = new Buffer(mongoObjectFinal.data.length); - buffer.write(mongoObjectFinal.data.join(''), 'binary', 0); - this.data = new Binary(buffer); - } else if(mongoObjectFinal.data instanceof Binary || mongoObjectFinal.data._bsontype === 'Binary' || Object.prototype.toString.call(mongoObjectFinal.data) == "[object Binary]") { - this.data = mongoObjectFinal.data; - } else if(Buffer.isBuffer(mongoObjectFinal.data)) { - } else { - throw Error("Illegal chunk format"); - } - - // Update position - this.internalPosition = 0; -}; - -/** - * Writes a data to this object and advance the read/write head. - * - * @param data {string} the data to write - * @param callback {function(*, GridStore)} This will be called after executing - * this method. The first parameter will contain null and the second one - * will contain a reference to this object. - */ -Chunk.prototype.write = function(data, callback) { - this.data.write(data, this.internalPosition); - this.internalPosition = this.data.length(); - if(callback != null) return callback(null, this); - return this; -}; - -/** - * Reads data and advances the read/write head. - * - * @param length {number} The length of data to read. - * - * @return {string} The data read if the given length will not exceed the end of - * the chunk. Returns an empty String otherwise. - */ -Chunk.prototype.read = function(length) { - // Default to full read if no index defined - length = length == null || length == 0 ? this.length() : length; - - if(this.length() - this.internalPosition + 1 >= length) { - var data = this.data.read(this.internalPosition, length); - this.internalPosition = this.internalPosition + length; - return data; - } else { - return ''; - } -}; - -Chunk.prototype.readSlice = function(length) { - if ((this.length() - this.internalPosition) >= length) { - var data = null; - if (this.data.buffer != null) { //Pure BSON - data = this.data.buffer.slice(this.internalPosition, this.internalPosition + length); - } else { //Native BSON - data = new Buffer(length); - length = this.data.readInto(data, this.internalPosition); - } - this.internalPosition = this.internalPosition + length; - return data; - } else { - return null; - } -}; - -/** - * Checks if the read/write head is at the end. - * - * @return {boolean} Whether the read/write head has reached the end of this - * chunk. - */ -Chunk.prototype.eof = function() { - return this.internalPosition == this.length() ? true : false; -}; - -/** - * Reads one character from the data of this chunk and advances the read/write - * head. - * - * @return {string} a single character data read if the the read/write head is - * not at the end of the chunk. Returns an empty String otherwise. - */ -Chunk.prototype.getc = function() { - return this.read(1); -}; - -/** - * Clears the contents of the data in this chunk and resets the read/write head - * to the initial position. - */ -Chunk.prototype.rewind = function() { - this.internalPosition = 0; - this.data = new Binary(); -}; - -/** - * Saves this chunk to the database. Also overwrites existing entries having the - * same id as this chunk. - * - * @param callback {function(*, GridStore)} This will be called after executing - * this method. The first parameter will contain null and the second one - * will contain a reference to this object. - */ -Chunk.prototype.save = function(options, callback) { - var self = this; - if(typeof options == 'function') { - callback = options; - options = {}; - } - - self.file.chunkCollection(function(err, collection) { - if(err) return callback(err); - - // Merge the options - var writeOptions = {}; - for(var name in options) writeOptions[name] = options[name]; - for(var name in self.writeConcern) writeOptions[name] = self.writeConcern[name]; - - // collection.remove({'_id':self.objectId}, self.writeConcern, function(err, result) { - collection.remove({'_id':self.objectId}, writeOptions, function(err, result) { - if(err) return callback(err); - - if(self.data.length() > 0) { - self.buildMongoObject(function(mongoObject) { - var options = {forceServerObjectId:true}; - for(var name in self.writeConcern) { - options[name] = self.writeConcern[name]; - } - - collection.insert(mongoObject, writeOptions, function(err, collection) { - callback(err, self); - }); - }); - } else { - callback(null, self); - } - }); - }); -}; - -/** - * Creates a mongoDB object representation of this chunk. - * - * @param callback {function(Object)} This will be called after executing this - * method. The object will be passed to the first parameter and will have - * the structure: - * - *

- *        {
- *          '_id' : , // {number} id for this chunk
- *          'files_id' : , // {number} foreign key to the file collection
- *          'n' : , // {number} chunk number
- *          'data' : , // {bson#Binary} the chunk data itself
- *        }
- *        
- * - * @see MongoDB GridFS Chunk Object Structure - */ -Chunk.prototype.buildMongoObject = function(callback) { - var mongoObject = { - 'files_id': this.file.fileId, - 'n': this.chunkNumber, - 'data': this.data}; - // If we are saving using a specific ObjectId - if(this.objectId != null) mongoObject._id = this.objectId; - - callback(mongoObject); -}; - -/** - * @return {number} the length of the data - */ -Chunk.prototype.length = function() { - return this.data.length(); -}; - -/** - * The position of the read/write head - * @name position - * @lends Chunk# - * @field - */ -Object.defineProperty(Chunk.prototype, "position", { enumerable: true - , get: function () { - return this.internalPosition; - } - , set: function(value) { - this.internalPosition = value; - } -}); - -/** - * The default chunk size - * @constant - */ -Chunk.DEFAULT_CHUNK_SIZE = 1024 * 255; diff --git a/node_modules/mongodb/lib/mongodb/gridfs/grid.js b/node_modules/mongodb/lib/mongodb/gridfs/grid.js deleted file mode 100644 index 00db0ef..0000000 --- a/node_modules/mongodb/lib/mongodb/gridfs/grid.js +++ /dev/null @@ -1,104 +0,0 @@ -var GridStore = require('./gridstore').GridStore, - ObjectID = require('bson').ObjectID; - -/** - * A class representation of a simple Grid interface. - * - * @class Represents the Grid. - * @param {Db} db A database instance to interact with. - * @param {String} [fsName] optional different root collection for GridFS. - * @return {Grid} - */ -function Grid(db, fsName) { - - if(!(this instanceof Grid)) return new Grid(db, fsName); - - this.db = db; - this.fsName = fsName == null ? GridStore.DEFAULT_ROOT_COLLECTION : fsName; -} - -/** - * Puts binary data to the grid - * - * Options - * - **_id** {Any}, unique id for this file - * - **filename** {String}, name for this file. - * - **root** {String}, root collection to use. Defaults to **{GridStore.DEFAULT_ROOT_COLLECTION}**. - * - **content_type** {String}, mime type of the file. Defaults to **{GridStore.DEFAULT_CONTENT_TYPE}**. - * - **chunk_size** {Number}, size for the chunk. Defaults to **{Chunk.DEFAULT_CHUNK_SIZE}**. - * - **metadata** {Object}, arbitrary data the user wants to store. - * - * @param {Buffer} data buffer with Binary Data. - * @param {Object} [options] the options for the files. - * @param {Function} callback this will be called after this method is executed. The first parameter will contain an Error object if an error occured or null otherwise. The second parameter will contain a reference to this object. - * @return {null} - * @api public - */ -Grid.prototype.put = function(data, options, callback) { - var self = this; - var args = Array.prototype.slice.call(arguments, 1); - callback = args.pop(); - options = args.length ? args.shift() : {}; - // If root is not defined add our default one - options['root'] = options['root'] == null ? this.fsName : options['root']; - - // Return if we don't have a buffer object as data - if(!(Buffer.isBuffer(data))) return callback(new Error("Data object must be a buffer object"), null); - // Get filename if we are using it - var filename = options['filename'] || null; - // Get id if we are using it - var id = options['_id'] || null; - // Create gridstore - var gridStore = new GridStore(this.db, id, filename, "w", options); - gridStore.open(function(err, gridStore) { - if(err) return callback(err, null); - - gridStore.write(data, function(err, result) { - if(err) return callback(err, null); - - gridStore.close(function(err, result) { - if(err) return callback(err, null); - callback(null, result); - }) - }) - }) -} - -/** - * Get binary data to the grid - * - * @param {Any} id for file. - * @param {Function} callback this will be called after this method is executed. The first parameter will contain an Error object if an error occured or null otherwise. The second parameter will contain a reference to this object. - * @return {null} - * @api public - */ -Grid.prototype.get = function(id, callback) { - // Create gridstore - var gridStore = new GridStore(this.db, id, null, "r", {root:this.fsName}); - gridStore.open(function(err, gridStore) { - if(err) return callback(err, null); - - // Return the data - gridStore.read(function(err, data) { - return callback(err, data) - }); - }) -} - -/** - * Delete file from grid - * - * @param {Any} id for file. - * @param {Function} callback this will be called after this method is executed. The first parameter will contain an Error object if an error occured or null otherwise. The second parameter will contain a reference to this object. - * @return {null} - * @api public - */ -Grid.prototype.delete = function(id, callback) { - // Create gridstore - GridStore.unlink(this.db, id, {root:this.fsName}, function(err, result) { - if(err) return callback(err, false); - return callback(null, true); - }); -} - -exports.Grid = Grid; diff --git a/node_modules/mongodb/lib/mongodb/gridfs/gridstore.js b/node_modules/mongodb/lib/mongodb/gridfs/gridstore.js deleted file mode 100644 index c6b9894..0000000 --- a/node_modules/mongodb/lib/mongodb/gridfs/gridstore.js +++ /dev/null @@ -1,1570 +0,0 @@ -/** - * @fileOverview GridFS is a tool for MongoDB to store files to the database. - * Because of the restrictions of the object size the database can hold, a - * facility to split a file into several chunks is needed. The {@link GridStore} - * class offers a simplified api to interact with files while managing the - * chunks of split files behind the scenes. More information about GridFS can be - * found here. - */ -var Chunk = require('./chunk').Chunk, - DbCommand = require('../commands/db_command').DbCommand, - ObjectID = require('bson').ObjectID, - Buffer = require('buffer').Buffer, - fs = require('fs'), - timers = require('timers'), - util = require('util'), - inherits = util.inherits, - ReadStream = require('./readstream').ReadStream, - Stream = require('stream'); - -// Set processor, setImmediate if 0.10 otherwise nextTick -var processor = require('../utils').processor(); - -var REFERENCE_BY_FILENAME = 0, - REFERENCE_BY_ID = 1; - -/** - * A class representation of a file stored in GridFS. - * - * Modes - * - **"r"** - read only. This is the default mode. - * - **"w"** - write in truncate mode. Existing data will be overwriten. - * - **w+"** - write in edit mode (append is not guaranteed for concurrent operations) - * - * Options - * - **root** {String}, root collection to use. Defaults to **{GridStore.DEFAULT_ROOT_COLLECTION}**. - * - **content_type** {String}, mime type of the file. Defaults to **{GridStore.DEFAULT_CONTENT_TYPE}**. - * - **chunk_size** {Number}, size for the chunk. Defaults to **{Chunk.DEFAULT_CHUNK_SIZE}**. - * - **metadata** {Object}, arbitrary data the user wants to store. - * - **readPreference** {String}, the prefered read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). - * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write - * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) - * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal - * - **j**, (Boolean, default:false) write waits for journal sync before returning - * - * @class Represents the GridStore. - * @param {Db} db A database instance to interact with. - * @param {Any} [id] optional unique id for this file - * @param {String} [filename] optional filename for this file, no unique constrain on the field - * @param {String} mode set the mode for this file. - * @param {Object} options optional properties to specify. - * @return {GridStore} - */ -var GridStore = function GridStore(db, id, filename, mode, options) { - if(!(this instanceof GridStore)) return new GridStore(db, id, filename, mode, options); - - var self = this; - this.db = db; - - // Call stream constructor - if(typeof Stream == 'function') { - Stream.call(this); - } - - // Handle options - if(typeof options === 'undefined') options = {}; - // Handle mode - if(typeof mode === 'undefined') { - mode = filename; - filename = undefined; - } else if(typeof mode == 'object') { - options = mode; - mode = filename; - filename = undefined; - } - - if(id instanceof ObjectID) { - this.referenceBy = REFERENCE_BY_ID; - this.fileId = id; - this.filename = filename; - } else if(typeof filename == 'undefined') { - this.referenceBy = REFERENCE_BY_FILENAME; - this.filename = id; - if (mode.indexOf('w') != null) { - this.fileId = new ObjectID(); - } - } else { - this.referenceBy = REFERENCE_BY_ID; - this.fileId = id; - this.filename = filename; - } - - // Set up the rest - this.mode = mode == null ? "r" : mode; - this.options = options || {}; - - // Set the root if overridden - this.root = this.options['root'] == null ? exports.GridStore.DEFAULT_ROOT_COLLECTION : this.options['root']; - this.position = 0; - this.readPreference = this.options.readPreference || 'primary'; - this.writeConcern = _getWriteConcern(db, this.options); - - // Set default chunk size - this.internalChunkSize = this.options['chunkSize'] == null ? Chunk.DEFAULT_CHUNK_SIZE : this.options['chunkSize']; -} - -/** - * Code for the streaming capabilities of the gridstore object - * Most code from Aaron heckmanns project https://github.com/aheckmann/gridfs-stream - * Modified to work on the gridstore object itself - * @ignore - */ -if(typeof Stream == 'function') { - GridStore.prototype = { __proto__: Stream.prototype } -} else { - // Node 0.4.X compatibility code - GridStore.prototype = { __proto__: Stream.Stream.prototype } -} - -// Move pipe to _pipe -GridStore.prototype._pipe = GridStore.prototype.pipe; - -/** - * Opens the file from the database and initialize this object. Also creates a - * new one if file does not exist. - * - * @param {Function} callback this will be called after executing this method. The first parameter will contain an **{Error}** object and the second parameter will be null if an error occured. Otherwise, the first parameter will be null and the second will contain the reference to this object. - * @return {null} - * @api public - */ -GridStore.prototype.open = function(callback) { - if( this.mode != "w" && this.mode != "w+" && this.mode != "r"){ - callback(new Error("Illegal mode " + this.mode), null); - return; - } - - var self = this; - - // Get the write concern - var writeConcern = _getWriteConcern(this.db, this.options); - - // If we are writing we need to ensure we have the right indexes for md5's - if((self.mode == "w" || self.mode == "w+")) { - // Get files collection - var collection = self.collection(); - // Put index on filename - collection.ensureIndex([['filename', 1]], writeConcern, function(err, index) { - // if(err) return callback(err); - - // Get chunk collection - var chunkCollection = self.chunkCollection(); - // Ensure index on chunk collection - chunkCollection.ensureIndex([['files_id', 1], ['n', 1]], writeConcern, function(err, index) { - // if(err) return callback(err); - _open(self, writeConcern, callback); - }); - }); - } else { - // Open the gridstore - _open(self, writeConcern, callback); - } -}; - -/** - * Hidding the _open function - * @ignore - * @api private - */ -var _open = function(self, options, callback) { - var collection = self.collection(); - // Create the query - var query = self.referenceBy == REFERENCE_BY_ID ? {_id:self.fileId} : {filename:self.filename}; - query = null == self.fileId && self.filename == null ? null : query; - options.readPreference = self.readPreference; - - // Fetch the chunks - if(query != null) { - collection.findOne(query, options, function(err, doc) { - if(err) return error(err); - - // Check if the collection for the files exists otherwise prepare the new one - if(doc != null) { - self.fileId = doc._id; - // Prefer a new filename over the existing one if this is a write - self.filename = ((self.mode == 'r') || (self.filename == undefined)) ? doc.filename : self.filename; - self.contentType = doc.contentType; - self.internalChunkSize = doc.chunkSize; - self.uploadDate = doc.uploadDate; - self.aliases = doc.aliases; - self.length = doc.length; - self.metadata = doc.metadata; - self.internalMd5 = doc.md5; - } else if (self.mode != 'r') { - self.fileId = self.fileId == null ? new ObjectID() : self.fileId; - self.contentType = exports.GridStore.DEFAULT_CONTENT_TYPE; - self.internalChunkSize = self.internalChunkSize == null ? Chunk.DEFAULT_CHUNK_SIZE : self.internalChunkSize; - self.length = 0; - } else { - self.length = 0; - var txtId = self.fileId instanceof ObjectID ? self.fileId.toHexString() : self.fileId; - return error(new Error((self.referenceBy == REFERENCE_BY_ID ? txtId : self.filename) + " does not exist", self)); - } - - // Process the mode of the object - if(self.mode == "r") { - nthChunk(self, 0, options, function(err, chunk) { - if(err) return error(err); - self.currentChunk = chunk; - self.position = 0; - callback(null, self); - }); - } else if(self.mode == "w") { - // Delete any existing chunks - deleteChunks(self, options, function(err, result) { - if(err) return error(err); - self.currentChunk = new Chunk(self, {'n':0}, self.writeConcern); - self.contentType = self.options['content_type'] == null ? self.contentType : self.options['content_type']; - self.internalChunkSize = self.options['chunk_size'] == null ? self.internalChunkSize : self.options['chunk_size']; - self.metadata = self.options['metadata'] == null ? self.metadata : self.options['metadata']; - self.aliases = self.options['aliases'] == null ? self.aliases : self.options['aliases']; - self.position = 0; - callback(null, self); - }); - } else if(self.mode == "w+") { - nthChunk(self, lastChunkNumber(self), options, function(err, chunk) { - if(err) return error(err); - // Set the current chunk - self.currentChunk = chunk == null ? new Chunk(self, {'n':0}, self.writeConcern) : chunk; - self.currentChunk.position = self.currentChunk.data.length(); - self.metadata = self.options['metadata'] == null ? self.metadata : self.options['metadata']; - self.aliases = self.options['aliases'] == null ? self.aliases : self.options['aliases']; - self.position = self.length; - callback(null, self); - }); - } - }); - } else { - // Write only mode - self.fileId = null == self.fileId ? new ObjectID() : self.fileId; - self.contentType = exports.GridStore.DEFAULT_CONTENT_TYPE; - self.internalChunkSize = self.internalChunkSize == null ? Chunk.DEFAULT_CHUNK_SIZE : self.internalChunkSize; - self.length = 0; - - var collection2 = self.chunkCollection(); - // No file exists set up write mode - if(self.mode == "w") { - // Delete any existing chunks - deleteChunks(self, options, function(err, result) { - if(err) return error(err); - self.currentChunk = new Chunk(self, {'n':0}, self.writeConcern); - self.contentType = self.options['content_type'] == null ? self.contentType : self.options['content_type']; - self.internalChunkSize = self.options['chunk_size'] == null ? self.internalChunkSize : self.options['chunk_size']; - self.metadata = self.options['metadata'] == null ? self.metadata : self.options['metadata']; - self.aliases = self.options['aliases'] == null ? self.aliases : self.options['aliases']; - self.position = 0; - callback(null, self); - }); - } else if(self.mode == "w+") { - nthChunk(self, lastChunkNumber(self), options, function(err, chunk) { - if(err) return error(err); - // Set the current chunk - self.currentChunk = chunk == null ? new Chunk(self, {'n':0}, self.writeConcern) : chunk; - self.currentChunk.position = self.currentChunk.data.length(); - self.metadata = self.options['metadata'] == null ? self.metadata : self.options['metadata']; - self.aliases = self.options['aliases'] == null ? self.aliases : self.options['aliases']; - self.position = self.length; - callback(null, self); - }); - } - } - - // only pass error to callback once - function error (err) { - if(error.err) return; - callback(error.err = err); - } -}; - -/** - * Stores a file from the file system to the GridFS database. - * - * @param {String|Buffer|FileHandle} file the file to store. - * @param {Function} callback this will be called after this method is executed. The first parameter will be null and the the second will contain the reference to this object. - * @return {null} - * @api public - */ -GridStore.prototype.writeFile = function (file, callback) { - var self = this; - if (typeof file === 'string') { - fs.open(file, 'r', function (err, fd) { - if(err) return callback(err); - self.writeFile(fd, callback); - }); - return; - } - - self.open(function (err, self) { - if(err) return callback(err, self); - - fs.fstat(file, function (err, stats) { - if(err) return callback(err, self); - - var offset = 0; - var index = 0; - var numberOfChunksLeft = Math.min(stats.size / self.chunkSize); - - // Write a chunk - var writeChunk = function() { - fs.read(file, self.chunkSize, offset, 'binary', function(err, data, bytesRead) { - if(err) return callback(err, self); - - offset = offset + bytesRead; - - // Create a new chunk for the data - var chunk = new Chunk(self, {n:index++}, self.writeConcern); - chunk.write(data, function(err, chunk) { - if(err) return callback(err, self); - - chunk.save({}, function(err, result) { - if(err) return callback(err, self); - - self.position = self.position + data.length; - - // Point to current chunk - self.currentChunk = chunk; - - if(offset >= stats.size) { - fs.close(file); - self.close(function(err, result) { - if(err) return callback(err, self); - return callback(null, self); - }); - } else { - return processor(writeChunk); - } - }); - }); - }); - } - - // Process the first write - processor(writeChunk); - }); - }); -}; - -/** - * Writes some data. This method will work properly only if initialized with mode - * "w" or "w+". - * - * @param string {string} The data to write. - * @param close {boolean=false} opt_argument Closes this file after writing if - * true. - * @param callback {function(*, GridStore)} This will be called after executing - * this method. The first parameter will contain null and the second one - * will contain a reference to this object. - * - * @ignore - * @api private - */ -var writeBuffer = function(self, buffer, close, callback) { - if(typeof close === "function") { callback = close; close = null; } - var finalClose = typeof close == 'boolean' ? close : false; - - if(self.mode[0] != "w") { - callback(new Error((self.referenceBy == REFERENCE_BY_ID ? self.toHexString() : self.filename) + " not opened for writing"), null); - } else { - if(self.currentChunk.position + buffer.length >= self.chunkSize) { - // Write out the current Chunk and then keep writing until we have less data left than a chunkSize left - // to a new chunk (recursively) - var previousChunkNumber = self.currentChunk.chunkNumber; - var leftOverDataSize = self.chunkSize - self.currentChunk.position; - var firstChunkData = buffer.slice(0, leftOverDataSize); - var leftOverData = buffer.slice(leftOverDataSize); - // A list of chunks to write out - var chunksToWrite = [self.currentChunk.write(firstChunkData)]; - // If we have more data left than the chunk size let's keep writing new chunks - while(leftOverData.length >= self.chunkSize) { - // Create a new chunk and write to it - var newChunk = new Chunk(self, {'n': (previousChunkNumber + 1)}, self.writeConcern); - var firstChunkData = leftOverData.slice(0, self.chunkSize); - leftOverData = leftOverData.slice(self.chunkSize); - // Update chunk number - previousChunkNumber = previousChunkNumber + 1; - // Write data - newChunk.write(firstChunkData); - // Push chunk to save list - chunksToWrite.push(newChunk); - } - - // Set current chunk with remaining data - self.currentChunk = new Chunk(self, {'n': (previousChunkNumber + 1)}, self.writeConcern); - // If we have left over data write it - if(leftOverData.length > 0) self.currentChunk.write(leftOverData); - - // Update the position for the gridstore - self.position = self.position + buffer.length; - // Total number of chunks to write - var numberOfChunksToWrite = chunksToWrite.length; - - for(var i = 0; i < chunksToWrite.length; i++) { - chunksToWrite[i].save({}, function(err, result) { - if(err) return callback(err); - - numberOfChunksToWrite = numberOfChunksToWrite - 1; - - if(numberOfChunksToWrite <= 0) { - // We care closing the file before returning - if(finalClose) { - return self.close(function(err, result) { - callback(err, self); - }); - } - - // Return normally - return callback(null, self); - } - }); - } - } else { - // Update the position for the gridstore - self.position = self.position + buffer.length; - // We have less data than the chunk size just write it and callback - self.currentChunk.write(buffer); - // We care closing the file before returning - if(finalClose) { - return self.close(function(err, result) { - callback(err, self); - }); - } - // Return normally - return callback(null, self); - } - } -}; - -/** - * Creates a mongoDB object representation of this object. - * - * @param callback {function(object)} This will be called after executing this - * method. The object will be passed to the first parameter and will have - * the structure: - * - *

- *        {
- *          '_id' : , // {number} id for this file
- *          'filename' : , // {string} name for this file
- *          'contentType' : , // {string} mime type for this file
- *          'length' : , // {number} size of this file?
- *          'chunksize' : , // {number} chunk size used by this file
- *          'uploadDate' : , // {Date}
- *          'aliases' : , // {array of string}
- *          'metadata' : , // {string}
- *        }
- *        
- * - * @ignore - * @api private - */ -var buildMongoObject = function(self, callback) { - // Calcuate the length - var mongoObject = { - '_id': self.fileId, - 'filename': self.filename, - 'contentType': self.contentType, - 'length': self.position ? self.position : 0, - 'chunkSize': self.chunkSize, - 'uploadDate': self.uploadDate, - 'aliases': self.aliases, - 'metadata': self.metadata - }; - - var md5Command = {filemd5:self.fileId, root:self.root}; - self.db.command(md5Command, function(err, results) { - if(err) return callback(err); - - mongoObject.md5 = results.md5; - callback(null, mongoObject); - }); -}; - -/** - * Saves this file to the database. This will overwrite the old entry if it - * already exists. This will work properly only if mode was initialized to - * "w" or "w+". - * - * @param {Function} callback this will be called after executing this method. Passes an **{Error}** object to the first parameter and null to the second if an error occured. Otherwise, passes null to the first and a reference to this object to the second. - * @return {null} - * @api public - */ -GridStore.prototype.close = function(callback) { - var self = this; - - if(self.mode[0] == "w") { - // Set up options - var options = self.writeConcern; - - if(self.currentChunk != null && self.currentChunk.position > 0) { - self.currentChunk.save({}, function(err, chunk) { - if(err && typeof callback == 'function') return callback(err); - - self.collection(function(err, files) { - if(err && typeof callback == 'function') return callback(err); - - // Build the mongo object - if(self.uploadDate != null) { - files.remove({'_id':self.fileId}, self.writeConcern, function(err, collection) { - if(err && typeof callback == 'function') return callback(err); - - buildMongoObject(self, function(err, mongoObject) { - if(err) { - if(typeof callback == 'function') return callback(err); else throw err; - } - - files.save(mongoObject, options, function(err) { - if(typeof callback == 'function') - callback(err, mongoObject); - }); - }); - }); - } else { - self.uploadDate = new Date(); - buildMongoObject(self, function(err, mongoObject) { - if(err) { - if(typeof callback == 'function') return callback(err); else throw err; - } - - files.save(mongoObject, options, function(err) { - if(typeof callback == 'function') - callback(err, mongoObject); - }); - }); - } - }); - }); - } else { - self.collection(function(err, files) { - if(err && typeof callback == 'function') return callback(err); - - self.uploadDate = new Date(); - buildMongoObject(self, function(err, mongoObject) { - if(err) { - if(typeof callback == 'function') return callback(err); else throw err; - } - - files.save(mongoObject, options, function(err) { - if(typeof callback == 'function') - callback(err, mongoObject); - }); - }); - }); - } - } else if(self.mode[0] == "r") { - if(typeof callback == 'function') - callback(null, null); - } else { - if(typeof callback == 'function') - callback(new Error("Illegal mode " + self.mode), null); - } -}; - -/** - * Gets the nth chunk of this file. - * - * @param chunkNumber {number} The nth chunk to retrieve. - * @param callback {function(*, Chunk|object)} This will be called after - * executing this method. null will be passed to the first parameter while - * a new {@link Chunk} instance will be passed to the second parameter if - * the chunk was found or an empty object {} if not. - * - * @ignore - * @api private - */ -var nthChunk = function(self, chunkNumber, options, callback) { - if(typeof options == 'function') { - callback = options; - options = {}; - } - - options = options || self.writeConcern; - options.readPreference = self.readPreference; - // Get the nth chunk - self.chunkCollection().findOne({'files_id':self.fileId, 'n':chunkNumber}, options, function(err, chunk) { - if(err) return callback(err); - - var finalChunk = chunk == null ? {} : chunk; - callback(null, new Chunk(self, finalChunk, self.writeConcern)); - }); -}; - -/** - * - * @ignore - * @api private - */ -GridStore.prototype._nthChunk = function(chunkNumber, callback) { - nthChunk(this, chunkNumber, callback); -} - -/** - * @return {Number} The last chunk number of this file. - * - * @ignore - * @api private - */ -var lastChunkNumber = function(self) { - return Math.floor((self.length ? self.length - 1 : 0)/self.chunkSize); -}; - -/** - * Retrieve this file's chunks collection. - * - * @param {Function} callback this will be called after executing this method. An exception object will be passed to the first parameter when an error occured or null otherwise. A new **{Collection}** object will be passed to the second parameter if no error occured. - * @return {null} - * @api public - */ -GridStore.prototype.chunkCollection = function(callback) { - if(typeof callback == 'function') - return this.db.collection((this.root + ".chunks"), callback); - return this.db.collection((this.root + ".chunks")); -}; - -/** - * Deletes all the chunks of this file in the database. - * - * @param callback {function(*, boolean)} This will be called after this method - * executes. Passes null to the first and true to the second argument. - * - * @ignore - * @api private - */ -var deleteChunks = function(self, options, callback) { - if(typeof options == 'function') { - callback = options; - options = {}; - } - - options = options || self.writeConcern; - - if(self.fileId != null) { - self.chunkCollection().remove({'files_id':self.fileId}, options, function(err, result) { - if(err) return callback(err, false); - callback(null, true); - }); - } else { - callback(null, true); - } -}; - -/** - * Deletes all the chunks of this file in the database. - * - * @param {Function} callback this will be called after this method executes. Passes null to the first and true to the second argument. - * @return {null} - * @api public - */ -GridStore.prototype.unlink = function(callback) { - var self = this; - deleteChunks(this, function(err) { - if(err!==null) { - err.message = "at deleteChunks: " + err.message; - return callback(err); - } - - self.collection(function(err, collection) { - if(err!==null) { - err.message = "at collection: " + err.message; - return callback(err); - } - - collection.remove({'_id':self.fileId}, self.writeConcern, function(err) { - callback(err, self); - }); - }); - }); -}; - -/** - * Retrieves the file collection associated with this object. - * - * @param {Function} callback this will be called after executing this method. An exception object will be passed to the first parameter when an error occured or null otherwise. A new **{Collection}** object will be passed to the second parameter if no error occured. - * @return {null} - * @api public - */ -GridStore.prototype.collection = function(callback) { - if(typeof callback == 'function') - this.db.collection(this.root + ".files", callback); - return this.db.collection(this.root + ".files"); -}; - -/** - * Reads the data of this file. - * - * @param {String} [separator] the character to be recognized as the newline separator. - * @param {Function} callback This will be called after this method is executed. The first parameter will be null and the second parameter will contain an array of strings representing the entire data, each element representing a line including the separator character. - * @return {null} - * @api public - */ -GridStore.prototype.readlines = function(separator, callback) { - var args = Array.prototype.slice.call(arguments, 0); - callback = args.pop(); - separator = args.length ? args.shift() : "\n"; - - this.read(function(err, data) { - if(err) return callback(err); - - var items = data.toString().split(separator); - items = items.length > 0 ? items.splice(0, items.length - 1) : []; - for(var i = 0; i < items.length; i++) { - items[i] = items[i] + separator; - } - - callback(null, items); - }); -}; - -/** - * Deletes all the chunks of this file in the database if mode was set to "w" or - * "w+" and resets the read/write head to the initial position. - * - * @param {Function} callback this will be called after executing this method. The first parameter will contain null and the second one will contain a reference to this object. - * @return {null} - * @api public - */ -GridStore.prototype.rewind = function(callback) { - var self = this; - - if(this.currentChunk.chunkNumber != 0) { - if(this.mode[0] == "w") { - deleteChunks(self, function(err, gridStore) { - if(err) return callback(err); - self.currentChunk = new Chunk(self, {'n': 0}, self.writeConcern); - self.position = 0; - callback(null, self); - }); - } else { - self.currentChunk(0, function(err, chunk) { - if(err) return callback(err); - self.currentChunk = chunk; - self.currentChunk.rewind(); - self.position = 0; - callback(null, self); - }); - } - } else { - self.currentChunk.rewind(); - self.position = 0; - callback(null, self); - } -}; - -/** - * Retrieves the contents of this file and advances the read/write head. Works with Buffers only. - * - * There are 3 signatures for this method: - * - * (callback) - * (length, callback) - * (length, buffer, callback) - * - * @param {Number} [length] the number of characters to read. Reads all the characters from the read/write head to the EOF if not specified. - * @param {String|Buffer} [buffer] a string to hold temporary data. This is used for storing the string data read so far when recursively calling this method. - * @param {Function} callback this will be called after this method is executed. null will be passed to the first parameter and a string containing the contents of the buffer concatenated with the contents read from this file will be passed to the second. - * @return {null} - * @api public - */ -GridStore.prototype.read = function(length, buffer, callback) { - var self = this; - - var args = Array.prototype.slice.call(arguments, 0); - callback = args.pop(); - length = args.length ? args.shift() : null; - buffer = args.length ? args.shift() : null; - - // The data is a c-terminated string and thus the length - 1 - var finalLength = length == null ? self.length - self.position : length; - var finalBuffer = buffer == null ? new Buffer(finalLength) : buffer; - // Add a index to buffer to keep track of writing position or apply current index - finalBuffer._index = buffer != null && buffer._index != null ? buffer._index : 0; - - if((self.currentChunk.length() - self.currentChunk.position + finalBuffer._index) >= finalLength) { - var slice = self.currentChunk.readSlice(finalLength - finalBuffer._index); - // Copy content to final buffer - slice.copy(finalBuffer, finalBuffer._index); - // Update internal position - self.position = self.position + finalBuffer.length; - // Check if we don't have a file at all - if(finalLength == 0 && finalBuffer.length == 0) return callback(new Error("File does not exist"), null); - // Else return data - callback(null, finalBuffer); - } else { - var slice = self.currentChunk.readSlice(self.currentChunk.length() - self.currentChunk.position); - // Copy content to final buffer - slice.copy(finalBuffer, finalBuffer._index); - // Update index position - finalBuffer._index += slice.length; - - // Load next chunk and read more - nthChunk(self, self.currentChunk.chunkNumber + 1, function(err, chunk) { - if(err) return callback(err); - - if(chunk.length() > 0) { - self.currentChunk = chunk; - self.read(length, finalBuffer, callback); - } else { - if (finalBuffer._index > 0) { - callback(null, finalBuffer) - } else { - callback(new Error("no chunks found for file, possibly corrupt"), null); - } - } - }); - } -} - -/** - * Retrieves the position of the read/write head of this file. - * - * @param {Function} callback This gets called after this method terminates. null is passed to the first parameter and the position is passed to the second. - * @return {null} - * @api public - */ -GridStore.prototype.tell = function(callback) { - callback(null, this.position); -}; - -/** - * Moves the read/write head to a new location. - * - * There are 3 signatures for this method - * - * Seek Location Modes - * - **GridStore.IO_SEEK_SET**, **(default)** set the position from the start of the file. - * - **GridStore.IO_SEEK_CUR**, set the position from the current position in the file. - * - **GridStore.IO_SEEK_END**, set the position from the end of the file. - * - * @param {Number} [position] the position to seek to - * @param {Number} [seekLocation] seek mode. Use one of the Seek Location modes. - * @param {Function} callback this will be called after executing this method. The first parameter will contain null and the second one will contain a reference to this object. - * @return {null} - * @api public - */ -GridStore.prototype.seek = function(position, seekLocation, callback) { - var self = this; - - var args = Array.prototype.slice.call(arguments, 1); - callback = args.pop(); - seekLocation = args.length ? args.shift() : null; - - var seekLocationFinal = seekLocation == null ? exports.GridStore.IO_SEEK_SET : seekLocation; - var finalPosition = position; - var targetPosition = 0; - - // Calculate the position - if(seekLocationFinal == exports.GridStore.IO_SEEK_CUR) { - targetPosition = self.position + finalPosition; - } else if(seekLocationFinal == exports.GridStore.IO_SEEK_END) { - targetPosition = self.length + finalPosition; - } else { - targetPosition = finalPosition; - } - - // Get the chunk - var newChunkNumber = Math.floor(targetPosition/self.chunkSize); - if(newChunkNumber != self.currentChunk.chunkNumber) { - var seekChunk = function() { - nthChunk(self, newChunkNumber, function(err, chunk) { - self.currentChunk = chunk; - self.position = targetPosition; - self.currentChunk.position = (self.position % self.chunkSize); - callback(err, self); - }); - }; - - if(self.mode[0] == 'w') { - self.currentChunk.save({}, function(err) { - if(err) return callback(err); - seekChunk(); - }); - } else { - seekChunk(); - } - } else { - self.position = targetPosition; - self.currentChunk.position = (self.position % self.chunkSize); - callback(null, self); - } -}; - -/** - * Verify if the file is at EOF. - * - * @return {Boolean} true if the read/write head is at the end of this file. - * @api public - */ -GridStore.prototype.eof = function() { - return this.position == this.length ? true : false; -}; - -/** - * Retrieves a single character from this file. - * - * @param {Function} callback this gets called after this method is executed. Passes null to the first parameter and the character read to the second or null to the second if the read/write head is at the end of the file. - * @return {null} - * @api public - */ -GridStore.prototype.getc = function(callback) { - var self = this; - - if(self.eof()) { - callback(null, null); - } else if(self.currentChunk.eof()) { - nthChunk(self, self.currentChunk.chunkNumber + 1, function(err, chunk) { - self.currentChunk = chunk; - self.position = self.position + 1; - callback(err, self.currentChunk.getc()); - }); - } else { - self.position = self.position + 1; - callback(null, self.currentChunk.getc()); - } -}; - -/** - * Writes a string to the file with a newline character appended at the end if - * the given string does not have one. - * - * @param {String} string the string to write. - * @param {Function} callback this will be called after executing this method. The first parameter will contain null and the second one will contain a reference to this object. - * @return {null} - * @api public - */ -GridStore.prototype.puts = function(string, callback) { - var finalString = string.match(/\n$/) == null ? string + "\n" : string; - this.write(finalString, callback); -}; - -/** - * Returns read stream based on this GridStore file - * - * Events - * - **data** {function(item) {}} the data event triggers when a document is ready. - * - **end** {function() {}} the end event triggers when there is no more documents available. - * - **close** {function() {}} the close event triggers when the stream is closed. - * - **error** {function(err) {}} the error event triggers if an error happens. - * - * @param {Boolean} autoclose if true current GridStore will be closed when EOF and 'close' event will be fired - * @return {null} - * @api public - */ -GridStore.prototype.stream = function(autoclose) { - return new ReadStream(autoclose, this); -}; - -/** -* The collection to be used for holding the files and chunks collection. -* -* @classconstant DEFAULT_ROOT_COLLECTION -**/ -GridStore.DEFAULT_ROOT_COLLECTION = 'fs'; - -/** -* Default file mime type -* -* @classconstant DEFAULT_CONTENT_TYPE -**/ -GridStore.DEFAULT_CONTENT_TYPE = 'binary/octet-stream'; - -/** -* Seek mode where the given length is absolute. -* -* @classconstant IO_SEEK_SET -**/ -GridStore.IO_SEEK_SET = 0; - -/** -* Seek mode where the given length is an offset to the current read/write head. -* -* @classconstant IO_SEEK_CUR -**/ -GridStore.IO_SEEK_CUR = 1; - -/** -* Seek mode where the given length is an offset to the end of the file. -* -* @classconstant IO_SEEK_END -**/ -GridStore.IO_SEEK_END = 2; - -/** - * Checks if a file exists in the database. - * - * Options - * - **readPreference** {String}, the prefered read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). - * - * @param {Db} db the database to query. - * @param {String} name the name of the file to look for. - * @param {String} [rootCollection] the root collection that holds the files and chunks collection. Defaults to **{GridStore.DEFAULT_ROOT_COLLECTION}**. - * @param {Function} callback this will be called after this method executes. Passes null to the first and passes true to the second if the file exists and false otherwise. - * @return {null} - * @api public - */ -GridStore.exist = function(db, fileIdObject, rootCollection, options, callback) { - var args = Array.prototype.slice.call(arguments, 2); - callback = args.pop(); - rootCollection = args.length ? args.shift() : null; - options = args.length ? args.shift() : {}; - - // Establish read preference - var readPreference = options.readPreference || 'primary'; - // Fetch collection - var rootCollectionFinal = rootCollection != null ? rootCollection : GridStore.DEFAULT_ROOT_COLLECTION; - db.collection(rootCollectionFinal + ".files", function(err, collection) { - if(err) return callback(err); - - // Build query - var query = (typeof fileIdObject == 'string' || Object.prototype.toString.call(fileIdObject) == '[object RegExp]' ) - ? {'filename':fileIdObject} - : {'_id':fileIdObject}; // Attempt to locate file - - collection.findOne(query, {readPreference:readPreference}, function(err, item) { - if(err) return callback(err); - - callback(null, item == null ? false : true); - }); - }); -}; - -/** - * Gets the list of files stored in the GridFS. - * - * @param {Db} db the database to query. - * @param {String} [rootCollection] the root collection that holds the files and chunks collection. Defaults to **{GridStore.DEFAULT_ROOT_COLLECTION}**. - * @param {Function} callback this will be called after this method executes. Passes null to the first and passes an array of strings containing the names of the files. - * @return {null} - * @api public - */ -GridStore.list = function(db, rootCollection, options, callback) { - var args = Array.prototype.slice.call(arguments, 1); - callback = args.pop(); - rootCollection = args.length ? args.shift() : null; - options = args.length ? args.shift() : {}; - - // Ensure we have correct values - if(rootCollection != null && typeof rootCollection == 'object') { - options = rootCollection; - rootCollection = null; - } - - // Establish read preference - var readPreference = options.readPreference || 'primary'; - // Check if we are returning by id not filename - var byId = options['id'] != null ? options['id'] : false; - // Fetch item - var rootCollectionFinal = rootCollection != null ? rootCollection : GridStore.DEFAULT_ROOT_COLLECTION; - var items = []; - db.collection((rootCollectionFinal + ".files"), function(err, collection) { - if(err) return callback(err); - - collection.find({}, {readPreference:readPreference}, function(err, cursor) { - if(err) return callback(err); - - cursor.each(function(err, item) { - if(item != null) { - items.push(byId ? item._id : item.filename); - } else { - callback(err, items); - } - }); - }); - }); -}; - -/** - * Reads the contents of a file. - * - * This method has the following signatures - * - * (db, name, callback) - * (db, name, length, callback) - * (db, name, length, offset, callback) - * (db, name, length, offset, options, callback) - * - * @param {Db} db the database to query. - * @param {String} name the name of the file. - * @param {Number} [length] the size of data to read. - * @param {Number} [offset] the offset from the head of the file of which to start reading from. - * @param {Object} [options] the options for the file. - * @param {Function} callback this will be called after this method executes. A string with an error message will be passed to the first parameter when the length and offset combination exceeds the length of the file while an Error object will be passed if other forms of error occured, otherwise, a string is passed. The second parameter will contain the data read if successful or null if an error occured. - * @return {null} - * @api public - */ -GridStore.read = function(db, name, length, offset, options, callback) { - var args = Array.prototype.slice.call(arguments, 2); - callback = args.pop(); - length = args.length ? args.shift() : null; - offset = args.length ? args.shift() : null; - options = args.length ? args.shift() : null; - - new GridStore(db, name, "r", options).open(function(err, gridStore) { - if(err) return callback(err); - // Make sure we are not reading out of bounds - if(offset && offset >= gridStore.length) return callback("offset larger than size of file", null); - if(length && length > gridStore.length) return callback("length is larger than the size of the file", null); - if(offset && length && (offset + length) > gridStore.length) return callback("offset and length is larger than the size of the file", null); - - if(offset != null) { - gridStore.seek(offset, function(err, gridStore) { - if(err) return callback(err); - gridStore.read(length, callback); - }); - } else { - gridStore.read(length, callback); - } - }); -}; - -/** - * Reads the data of this file. - * - * @param {Db} db the database to query. - * @param {String} name the name of the file. - * @param {String} [separator] the character to be recognized as the newline separator. - * @param {Object} [options] file options. - * @param {Function} callback this will be called after this method is executed. The first parameter will be null and the second parameter will contain an array of strings representing the entire data, each element representing a line including the separator character. - * @return {null} - * @api public - */ -GridStore.readlines = function(db, name, separator, options, callback) { - var args = Array.prototype.slice.call(arguments, 2); - callback = args.pop(); - separator = args.length ? args.shift() : null; - options = args.length ? args.shift() : null; - - var finalSeperator = separator == null ? "\n" : separator; - new GridStore(db, name, "r", options).open(function(err, gridStore) { - if(err) return callback(err); - gridStore.readlines(finalSeperator, callback); - }); -}; - -/** - * Deletes the chunks and metadata information of a file from GridFS. - * - * @param {Db} db the database to interact with. - * @param {String|Array} names the name/names of the files to delete. - * @param {Object} [options] the options for the files. - * @callback {Function} this will be called after this method is executed. The first parameter will contain an Error object if an error occured or null otherwise. The second parameter will contain a reference to this object. - * @return {null} - * @api public - */ -GridStore.unlink = function(db, names, options, callback) { - var self = this; - var args = Array.prototype.slice.call(arguments, 2); - callback = args.pop(); - options = args.length ? args.shift() : {}; - - // Get the write concern - var writeConcern = _getWriteConcern(db, options); - - // List of names - if(names.constructor == Array) { - var tc = 0; - for(var i = 0; i < names.length; i++) { - ++tc; - GridStore.unlink(db, names[i], options, function(result) { - if(--tc == 0) { - callback(null, self); - } - }); - } - } else { - new GridStore(db, names, "w", options).open(function(err, gridStore) { - if(err) return callback(err); - deleteChunks(gridStore, function(err, result) { - if(err) return callback(err); - gridStore.collection(function(err, collection) { - if(err) return callback(err); - collection.remove({'_id':gridStore.fileId}, writeConcern, function(err, result) { - callback(err, self); - }); - }); - }); - }); - } -}; - -/** - * Returns the current chunksize of the file. - * - * @field chunkSize - * @type {Number} - * @getter - * @setter - * @property return number of bytes in the current chunkSize. - */ -Object.defineProperty(GridStore.prototype, "chunkSize", { enumerable: true - , get: function () { - return this.internalChunkSize; - } - , set: function(value) { - if(!(this.mode[0] == "w" && this.position == 0 && this.uploadDate == null)) { - this.internalChunkSize = this.internalChunkSize; - } else { - this.internalChunkSize = value; - } - } -}); - -/** - * The md5 checksum for this file. - * - * @field md5 - * @type {Number} - * @getter - * @setter - * @property return this files md5 checksum. - */ -Object.defineProperty(GridStore.prototype, "md5", { enumerable: true - , get: function () { - return this.internalMd5; - } -}); - -/** - * GridStore Streaming methods - * Handles the correct return of the writeable stream status - * @ignore - */ -Object.defineProperty(GridStore.prototype, "writable", { enumerable: true - , get: function () { - if(this._writeable == null) { - this._writeable = this.mode != null && this.mode.indexOf("w") != -1; - } - // Return the _writeable - return this._writeable; - } - , set: function(value) { - this._writeable = value; - } -}); - -/** - * Handles the correct return of the readable stream status - * @ignore - */ -Object.defineProperty(GridStore.prototype, "readable", { enumerable: true - , get: function () { - if(this._readable == null) { - this._readable = this.mode != null && this.mode.indexOf("r") != -1; - } - return this._readable; - } - , set: function(value) { - this._readable = value; - } -}); - -GridStore.prototype.paused; - -/** - * Handles the correct setting of encoding for the stream - * @ignore - */ -GridStore.prototype.setEncoding = fs.ReadStream.prototype.setEncoding; - -/** - * Handles the end events - * @ignore - */ -GridStore.prototype.end = function end(data) { - var self = this; - // allow queued data to write before closing - if(!this.writable) return; - this.writable = false; - - if(data) { - this._q.push(data); - } - - this.on('drain', function () { - self.close(function (err) { - if (err) return _error(self, err); - self.emit('close'); - }); - }); - - _flush(self); -} - -/** - * Handles the normal writes to gridstore - * @ignore - */ -var _writeNormal = function(self, data, close, callback) { - // If we have a buffer write it using the writeBuffer method - if(Buffer.isBuffer(data)) { - return writeBuffer(self, data, close, callback); - } else { - return writeBuffer(self, new Buffer(data, 'binary'), close, callback); - } -} - -/** - * Writes some data. This method will work properly only if initialized with mode "w" or "w+". - * - * @param {String|Buffer} data the data to write. - * @param {Boolean} [close] closes this file after writing if set to true. - * @param {Function} callback this will be called after executing this method. The first parameter will contain null and the second one will contain a reference to this object. - * @return {null} - * @api public - */ -GridStore.prototype.write = function write(data, close, callback) { - // If it's a normal write delegate the call - if(typeof close == 'function' || typeof callback == 'function') { - return _writeNormal(this, data, close, callback); - } - - // Otherwise it's a stream write - var self = this; - if (!this.writable) { - throw new Error('GridWriteStream is not writable'); - } - - // queue data until we open. - if(!this._opened) { - // Set up a queue to save data until gridstore object is ready - this._q = []; - _openStream(self); - this._q.push(data); - return false; - } - - // Push data to queue - this._q.push(data); - _flush(this); - // Return write successful - return true; -} - -/** - * Handles the destroy part of a stream - * @ignore - */ -GridStore.prototype.destroy = function destroy() { - // close and do not emit any more events. queued data is not sent. - if(!this.writable) return; - this.readable = false; - if(this.writable) { - this.writable = false; - this._q.length = 0; - this.emit('close'); - } -} - -/** - * Handles the destroySoon part of a stream - * @ignore - */ -GridStore.prototype.destroySoon = function destroySoon() { - // as soon as write queue is drained, destroy. - // may call destroy immediately if no data is queued. - if(!this._q.length) { - return this.destroy(); - } - this._destroying = true; -} - -/** - * Handles the pipe part of the stream - * @ignore - */ -GridStore.prototype.pipe = function(destination, options) { - var self = this; - // Open the gridstore - this.open(function(err, result) { - if(err) _errorRead(self, err); - if(!self.readable) return; - // Set up the pipe - self._pipe(destination, options); - // Emit the stream is open - self.emit('open'); - // Read from the stream - _read(self); - }); - return destination; -} - -/** - * Internal module methods - * @ignore - */ -var _read = function _read(self) { - if (!self.readable || self.paused || self.reading) { - return; - } - - self.reading = true; - var stream = self._stream = self.stream(); - stream.paused = self.paused; - - stream.on('data', function (data) { - if (self._decoder) { - var str = self._decoder.write(data); - if (str.length) self.emit('data', str); - } else { - self.emit('data', data); - } - }); - - stream.on('end', function (data) { - self.emit('end', data); - }); - - stream.on('error', function (data) { - _errorRead(self, data); - }); - - stream.on('close', function (data) { - self.emit('close', data); - }); - - self.pause = function () { - // native doesn't always pause. - // bypass its pause() method to hack it - self.paused = stream.paused = true; - } - - self.resume = function () { - if(!self.paused) return; - - self.paused = false; - stream.resume(); - self.readable = stream.readable; - } - - self.destroy = function () { - self.readable = false; - stream.destroy(); - } -} - -/** - * pause - * @ignore - */ -GridStore.prototype.pause = function pause () { - // Overridden when the GridStore opens. - this.paused = true; -} - -/** - * resume - * @ignore - */ -GridStore.prototype.resume = function resume () { - // Overridden when the GridStore opens. - this.paused = false; -} - -/** - * Internal module methods - * @ignore - */ -var _flush = function _flush(self, _force) { - if (!self._opened) return; - if (!_force && self._flushing) return; - self._flushing = true; - - // write the entire q to gridfs - if (!self._q.length) { - self._flushing = false; - self.emit('drain'); - - if(self._destroying) { - self.destroy(); - } - return; - } - - self.write(self._q.shift(), function (err, store) { - if (err) return _error(self, err); - self.emit('progress', store.position); - _flush(self, true); - }); -} - -var _openStream = function _openStream (self) { - if(self._opening == true) return; - self._opening = true; - - // Open the store - self.open(function (err, gridstore) { - if (err) return _error(self, err); - self._opened = true; - self.emit('open'); - _flush(self); - }); -} - -var _error = function _error(self, err) { - self.destroy(); - self.emit('error', err); -} - -var _errorRead = function _errorRead (self, err) { - self.readable = false; - self.emit('error', err); -} - -/** - * @ignore - */ -var _hasWriteConcern = function(errorOptions) { - return errorOptions == true - || errorOptions.w > 0 - || errorOptions.w == 'majority' - || errorOptions.j == true - || errorOptions.journal == true - || errorOptions.fsync == true -} - -/** - * @ignore - */ -var _setWriteConcernHash = function(options) { - var finalOptions = {}; - if(options.w != null) finalOptions.w = options.w; - if(options.journal == true) finalOptions.j = options.journal; - if(options.j == true) finalOptions.j = options.j; - if(options.fsync == true) finalOptions.fsync = options.fsync; - if(options.wtimeout != null) finalOptions.wtimeout = options.wtimeout; - return finalOptions; -} - -/** - * @ignore - */ -var _getWriteConcern = function(self, options) { - // Final options - var finalOptions = {w:1}; - options = options || {}; - - // Local options verification - if(options.w != null || typeof options.j == 'boolean' || typeof options.journal == 'boolean' || typeof options.fsync == 'boolean') { - finalOptions = _setWriteConcernHash(options); - } else if(options.safe != null && typeof options.safe == 'object') { - finalOptions = _setWriteConcernHash(options.safe); - } else if(typeof options.safe == "boolean") { - finalOptions = {w: (options.safe ? 1 : 0)}; - } else if(self.options.w != null || typeof self.options.j == 'boolean' || typeof self.options.journal == 'boolean' || typeof self.options.fsync == 'boolean') { - finalOptions = _setWriteConcernHash(self.options); - } else if(self.safe.w != null || typeof self.safe.j == 'boolean' || typeof self.safe.journal == 'boolean' || typeof self.safe.fsync == 'boolean') { - finalOptions = _setWriteConcernHash(self.safe); - } else if(typeof self.safe == "boolean") { - finalOptions = {w: (self.safe ? 1 : 0)}; - } - - // Ensure we don't have an invalid combination of write concerns - if(finalOptions.w < 1 - && (finalOptions.journal == true || finalOptions.j == true || finalOptions.fsync == true)) throw new Error("No acknowledgement using w < 1 cannot be combined with journal:true or fsync:true"); - - // Return the options - return finalOptions; -} - -/** - * @ignore - * @api private - */ -exports.GridStore = GridStore; diff --git a/node_modules/mongodb/lib/mongodb/gridfs/readstream.js b/node_modules/mongodb/lib/mongodb/gridfs/readstream.js deleted file mode 100644 index 4a4f7ee..0000000 --- a/node_modules/mongodb/lib/mongodb/gridfs/readstream.js +++ /dev/null @@ -1,206 +0,0 @@ -var Stream = require('stream').Stream, - timers = require('timers'), - util = require('util'); - -// Set processor, setImmediate if 0.10 otherwise nextTick -var processor = require('../utils').processor(); - -/** - * ReadStream - * - * Returns a stream interface for the **file**. - * - * Events - * - **data** {function(item) {}} the data event triggers when a document is ready. - * - **end** {function() {}} the end event triggers when there is no more documents available. - * - **close** {function() {}} the close event triggers when the stream is closed. - * - **error** {function(err) {}} the error event triggers if an error happens. - * - * @class Represents a GridFS File Stream. - * @param {Boolean} autoclose automatically close file when the stream reaches the end. - * @param {GridStore} cursor a cursor object that the stream wraps. - * @return {ReadStream} - */ -function ReadStream(autoclose, gstore) { - if (!(this instanceof ReadStream)) return new ReadStream(autoclose, gstore); - Stream.call(this); - - this.autoclose = !!autoclose; - this.gstore = gstore; - - this.finalLength = gstore.length - gstore.position; - this.completedLength = 0; - this.currentChunkNumber = gstore.currentChunk.chunkNumber; - - this.paused = false; - this.readable = true; - this.pendingChunk = null; - this.executing = false; - this.destroyed = false; - - // Calculate the number of chunks - this.numberOfChunks = Math.ceil(gstore.length/gstore.chunkSize); - - // This seek start position inside the current chunk - this.seekStartPosition = gstore.position - (this.currentChunkNumber * gstore.chunkSize); - - var self = this; - processor(function() { - self._execute(); - }); -}; - -/** - * Inherit from Stream - * @ignore - * @api private - */ -ReadStream.prototype.__proto__ = Stream.prototype; - -/** - * Flag stating whether or not this stream is readable. - */ -ReadStream.prototype.readable; - -/** - * Flag stating whether or not this stream is paused. - */ -ReadStream.prototype.paused; - -/** - * @ignore - * @api private - */ -ReadStream.prototype._execute = function() { - if(this.paused === true || this.readable === false) { - return; - } - - var gstore = this.gstore; - var self = this; - // Set that we are executing - this.executing = true; - - var last = false; - var toRead = 0; - - if(gstore.currentChunk.chunkNumber >= (this.numberOfChunks - 1)) { - self.executing = false; - last = true; - } - - // Data setup - var data = null; - - // Read a slice (with seek set if none) - if(this.seekStartPosition > 0 && (gstore.currentChunk.length() - this.seekStartPosition) > 0) { - data = gstore.currentChunk.readSlice(gstore.currentChunk.length() - this.seekStartPosition); - this.seekStartPosition = 0; - } else { - data = gstore.currentChunk.readSlice(gstore.currentChunk.length()); - } - - var processNext = function() { - if(last === true) { - self.readable = false; - self.emit("end"); - - if(self.autoclose === true) { - if(gstore.mode[0] == "w") { - gstore.close(function(err, doc) { - if (err) { - self.emit("error", err); - return; - } - self.readable = false; - self.destroyed = true; - self.emit("close", doc); - }); - } else { - self.readable = false; - self.destroyed = true; - self.emit("close"); - } - } - } else { - gstore._nthChunk(gstore.currentChunk.chunkNumber + 1, function(err, chunk) { - if(err) { - self.readable = false; - if(self.listeners("error").length > 0) - self.emit("error", err); - self.executing = false; - return; - } - - self.pendingChunk = chunk; - if(self.paused === true) { - self.executing = false; - return; - } - - gstore.currentChunk = self.pendingChunk; - self._execute(); - }); - } - } - - // Return the data - if(data != null && gstore.currentChunk.chunkNumber == self.currentChunkNumber) { - self.currentChunkNumber = self.currentChunkNumber + 1; - self.completedLength += data.length; - self.pendingChunk = null; - // Send the data - process.nextTick(function() { - self.emit("data", data); - processNext(); - }) - } else { - processNext(); - } -}; - -/** - * Pauses this stream, then no farther events will be fired. - * - * @ignore - * @api public - */ -ReadStream.prototype.pause = function() { - if(!this.executing) { - this.paused = true; - } -}; - -/** - * Destroys the stream, then no farther events will be fired. - * - * @ignore - * @api public - */ -ReadStream.prototype.destroy = function() { - if(this.destroyed) return; - this.destroyed = true; - this.readable = false; - // Emit close event - this.emit("close"); -}; - -/** - * Resumes this stream. - * - * @ignore - * @api public - */ -ReadStream.prototype.resume = function() { - if(this.paused === false || !this.readable) { - return; - } - - this.paused = false; - var self = this; - processor(function() { - self._execute(); - }); -}; - -exports.ReadStream = ReadStream; diff --git a/node_modules/mongodb/lib/mongodb/index.js b/node_modules/mongodb/lib/mongodb/index.js deleted file mode 100644 index 05a4cde..0000000 --- a/node_modules/mongodb/lib/mongodb/index.js +++ /dev/null @@ -1,62 +0,0 @@ -try { - exports.BSONPure = require('bson').BSONPure; - exports.BSONNative = require('bson').BSONNative; -} catch(err) { - // do nothing -} - -// export the driver version -exports.version = require('../../package').version; - -[ 'commands/base_command' - , 'admin' - , 'collection' - , 'connection/read_preference' - , 'connection/connection' - , 'connection/server' - , 'connection/mongos' - , 'connection/repl_set/repl_set' - , 'mongo_client' - , 'cursor' - , 'db' - , 'mongo_client' - , 'gridfs/grid' - , 'gridfs/chunk' - , 'gridfs/gridstore'].forEach(function (path) { - var module = require('./' + path); - for (var i in module) { - exports[i] = module[i]; - } -}); - -// backwards compat -exports.ReplSetServers = exports.ReplSet; -// Add BSON Classes -exports.Binary = require('bson').Binary; -exports.Code = require('bson').Code; -exports.DBRef = require('bson').DBRef; -exports.Double = require('bson').Double; -exports.Long = require('bson').Long; -exports.MinKey = require('bson').MinKey; -exports.MaxKey = require('bson').MaxKey; -exports.ObjectID = require('bson').ObjectID; -exports.Symbol = require('bson').Symbol; -exports.Timestamp = require('bson').Timestamp; -// Add BSON Parser -exports.BSON = require('bson').BSONPure.BSON; - -// Set up the connect function -var connect = exports.Db.connect; - -// Add the pure and native backward compatible functions -exports.pure = exports.native = function() { - return connect; -} - -// Map all values to the exports value -for(var name in exports) { - connect[name] = exports[name]; -} - -// Set our exports to be the connect function -module.exports = connect; diff --git a/node_modules/mongodb/lib/mongodb/mongo_client.js b/node_modules/mongodb/lib/mongodb/mongo_client.js deleted file mode 100644 index 04a0fc2..0000000 --- a/node_modules/mongodb/lib/mongodb/mongo_client.js +++ /dev/null @@ -1,482 +0,0 @@ -var Db = require('./db').Db - , Server = require('./connection/server').Server - , Mongos = require('./connection/mongos').Mongos - , ReplSet = require('./connection/repl_set/repl_set').ReplSet - , ReadPreference = require('./connection/read_preference').ReadPreference - , inherits = require('util').inherits - , EventEmitter = require('events').EventEmitter - , parse = require('./connection/url_parser').parse; - -/** - * Create a new MongoClient instance. - * - * Options - * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write - * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option) - * - **fsync**, (Boolean, default:false) write waits for fsync before returning, from MongoDB 2.6 on, fsync cannot be combined with journal - * - **j**, (Boolean, default:false) write waits for journal sync before returning - * - **readPreference** {String}, the prefered read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). - * - **native_parser** {Boolean, default:false}, use c++ bson parser. - * - **forceServerObjectId** {Boolean, default:false}, force server to create _id fields instead of client. - * - **pkFactory** {Object}, object overriding the basic ObjectID primary key generation. - * - **serializeFunctions** {Boolean, default:false}, serialize functions. - * - **raw** {Boolean, default:false}, peform operations using raw bson buffers. - * - **recordQueryStats** {Boolean, default:false}, record query statistics during execution. - * - **retryMiliSeconds** {Number, default:5000}, number of miliseconds between retries. - * - **numberOfRetries** {Number, default:5}, number of retries off connection. - * - **bufferMaxEntries** {Boolean, default: -1}, sets a cap on how many operations the driver will buffer up before giving up on getting a working connection, default is -1 which is unlimited - * - * @class Represents a MongoClient - * @param {Object} serverConfig server config object. - * @param {Object} [options] additional options for the collection. - */ -function MongoClient(serverConfig, options) { - if(serverConfig != null) { - options = options ? options : {}; - // If no write concern is set set the default to w:1 - if('w' in options === false) { - options.w = 1; - } - - // The internal db instance we are wrapping - this._db = new Db('test', serverConfig, options); - } -} - -/** - * @ignore - */ -inherits(MongoClient, EventEmitter); - -/** - * Connect to MongoDB using a url as documented at - * - * docs.mongodb.org/manual/reference/connection-string/ - * - * Options - * - **uri_decode_auth** {Boolean, default:false} uri decode the user name and password for authentication - * - **db** {Object, default: null} a hash off options to set on the db object, see **Db constructor** - * - **server** {Object, default: null} a hash off options to set on the server objects, see **Server** constructor** - * - **replSet** {Object, default: null} a hash off options to set on the replSet object, see **ReplSet** constructor** - * - **mongos** {Object, default: null} a hash off options to set on the mongos object, see **Mongos** constructor** - * - * @param {String} url connection url for MongoDB. - * @param {Object} [options] optional options for insert command - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the initialized db object or null if an error occured. - * @return {null} - * @api public - */ -MongoClient.prototype.connect = function(url, options, callback) { - var self = this; - - if(typeof options == 'function') { - callback = options; - options = {}; - } - - MongoClient.connect(url, options, function(err, db) { - if(err) return callback(err, db); - // Store internal db instance reference - self._db = db; - // Emit open and perform callback - self.emit("open", err, db); - callback(err, db); - }); -} - -/** - * Initialize the database connection. - * - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the connected mongoclient or null if an error occured. - * @return {null} - * @api public - */ -MongoClient.prototype.open = function(callback) { - // Self reference - var self = this; - // Open the db - this._db.open(function(err, db) { - if(err) return callback(err, null); - // Emit open event - self.emit("open", err, db); - // Callback - callback(null, self); - }) -} - -/** - * Close the current db connection, including all the child db instances. Emits close event and calls optional callback. - * - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the close method or null if an error occured. - * @return {null} - * @api public - */ -MongoClient.prototype.close = function(callback) { - this._db.close(callback); -} - -/** - * Create a new Db instance sharing the current socket connections. - * - * @param {String} dbName the name of the database we want to use. - * @return {Db} a db instance using the new database. - * @api public - */ -MongoClient.prototype.db = function(dbName) { - return this._db.db(dbName); -} - -/** - * Connect to MongoDB using a url as documented at - * - * docs.mongodb.org/manual/reference/connection-string/ - * - * Options - * - **uri_decode_auth** {Boolean, default:false} uri decode the user name and password for authentication - * - **db** {Object, default: null} a hash off options to set on the db object, see **Db constructor** - * - **server** {Object, default: null} a hash off options to set on the server objects, see **Server** constructor** - * - **replSet** {Object, default: null} a hash off options to set on the replSet object, see **ReplSet** constructor** - * - **mongos** {Object, default: null} a hash off options to set on the mongos object, see **Mongos** constructor** - * - * @param {String} url connection url for MongoDB. - * @param {Object} [options] optional options for insert command - * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the initialized db object or null if an error occured. - * @return {null} - * @api public - */ -MongoClient.connect = function(url, options, callback) { - var args = Array.prototype.slice.call(arguments, 1); - callback = typeof args[args.length - 1] == 'function' ? args.pop() : null; - options = args.length ? args.shift() : null; - options = options || {}; - - // Set default empty server options - var serverOptions = options.server || {}; - var mongosOptions = options.mongos || {}; - var replSetServersOptions = options.replSet || options.replSetServers || {}; - var dbOptions = options.db || {}; - - // If callback is null throw an exception - if(callback == null) - throw new Error("no callback function provided"); - - // Parse the string - var object = parse(url, options); - - // Merge in any options for db in options object - if(dbOptions) { - for(var name in dbOptions) object.db_options[name] = dbOptions[name]; - } - - // Added the url to the options - object.db_options.url = url; - - // Merge in any options for server in options object - if(serverOptions) { - for(var name in serverOptions) object.server_options[name] = serverOptions[name]; - } - - // Merge in any replicaset server options - if(replSetServersOptions) { - for(var name in replSetServersOptions) object.rs_options[name] = replSetServersOptions[name]; - } - - // Merge in any replicaset server options - if(mongosOptions) { - for(var name in mongosOptions) object.mongos_options[name] = mongosOptions[name]; - } - - // We need to ensure that the list of servers are only either direct members or mongos - // they cannot be a mix of monogs and mongod's - var totalNumberOfServers = object.servers.length; - var totalNumberOfMongosServers = 0; - var totalNumberOfMongodServers = 0; - var serverConfig = null; - var errorServers = {}; - - // Failure modes - if(object.servers.length == 0) throw new Error("connection string must contain at least one seed host"); - - // If we have no db setting for the native parser try to set the c++ one first - object.db_options.native_parser = _setNativeParser(object.db_options); - // If no auto_reconnect is set, set it to true as default for single servers - if(typeof object.server_options.auto_reconnect != 'boolean') { - object.server_options.auto_reconnect = true; - } - - // Establish the correct socketTimeout - var connectTimeoutMS = 30000; - var socketTimeoutMS = 0; - - // We have a server connection timeout setting - if(object.server_options && object.server_options.socketOptions && object.server_options.socketOptions.connectTimeoutMS) { - connectTimeoutMS = object.server_options.socketOptions.connectTimeoutMS; - } - - // We have a rs options set for connection timeout, override any server ones - if(object.rs_options && object.rs_options.socketOptions && object.rs_options.socketOptions.connectTimeoutMS) { - connectTimeoutMS = object.rs_options.socketOptions.connectTimeoutMS; - } - - // If we have no socket settings set the default values - if(object.rs_options.socketOptions.connectTimeoutMS == null) { - object.rs_options.socketOptions.connectTimeoutMS = connectTimeoutMS; - } - - if(object.rs_options.socketOptions.socketTimeoutMS == null) { - object.rs_options.socketOptions.socketTimeoutMS = socketTimeoutMS; - } - - if(object.server_options.socketOptions.connectTimeoutMS == null) { - object.server_options.socketOptions.connectTimeoutMS = connectTimeoutMS; - } - - if(object.server_options.socketOptions.socketTimeoutMS == null) { - object.server_options.socketOptions.socketTimeoutMS = socketTimeoutMS; - } - - // If we have more than a server, it could be replicaset or mongos list - // need to verify that it's one or the other and fail if it's a mix - // Connect to all servers and run ismaster - for(var i = 0; i < object.servers.length; i++) { - // Set up socket options - var _server_options = { - poolSize:1 - , socketOptions: { - connectTimeoutMS: connectTimeoutMS - , socketTimeoutMS: socketTimeoutMS - } - , auto_reconnect:false}; - - // Ensure we have ssl setup for the servers - if(object.rs_options.ssl) { - _server_options.ssl = object.rs_options.ssl; - _server_options.sslValidate = object.rs_options.sslValidate; - _server_options.sslCA = object.rs_options.sslCA; - _server_options.sslCert = object.rs_options.sslCert; - _server_options.sslKey = object.rs_options.sslKey; - _server_options.sslPass = object.rs_options.sslPass; - } else if(object.server_options.ssl) { - _server_options.ssl = object.server_options.ssl; - _server_options.sslValidate = object.server_options.sslValidate; - _server_options.sslCA = object.server_options.sslCA; - _server_options.sslCert = object.server_options.sslCert; - _server_options.sslKey = object.server_options.sslKey; - _server_options.sslPass = object.server_options.sslPass; - } - - // Set up the Server object - var _server = object.servers[i].domain_socket - ? new Server(object.servers[i].domain_socket, _server_options) - : new Server(object.servers[i].host, object.servers[i].port, _server_options); - - var connectFunction = function(__server) { - // Attempt connect - new Db(object.dbName, __server, {w:1, native_parser:false}).open(function(err, db) { - // Update number of servers - totalNumberOfServers = totalNumberOfServers - 1; - // If no error do the correct checks - if(!err) { - // Close the connection - db.close(true); - var isMasterDoc = db.serverConfig.isMasterDoc; - // Check what type of server we have - if(isMasterDoc.setName) totalNumberOfMongodServers++; - if(isMasterDoc.msg && isMasterDoc.msg == "isdbgrid") totalNumberOfMongosServers++; - } else { - errorServers[__server.host + ":" + __server.port] = __server; - } - - if(totalNumberOfServers == 0) { - // If we have a mix of mongod and mongos, throw an error - if(totalNumberOfMongosServers > 0 && totalNumberOfMongodServers > 0) { - return process.nextTick(function() { - try { - callback(new Error("cannot combine a list of replicaset seeds and mongos seeds")); - } catch (err) { - if(db) db.close(); - throw err - } - }) - } - - if(totalNumberOfMongodServers == 0 && object.servers.length == 1) { - var obj = object.servers[0]; - serverConfig = obj.domain_socket ? - new Server(obj.domain_socket, object.server_options) - : new Server(obj.host, obj.port, object.server_options); - } else if(totalNumberOfMongodServers > 0 || totalNumberOfMongosServers > 0) { - var finalServers = object.servers - .filter(function(serverObj) { - return errorServers[serverObj.host + ":" + serverObj.port] == null; - }) - .map(function(serverObj) { - return new Server(serverObj.host, serverObj.port, object.server_options); - }); - // Clean out any error servers - errorServers = {}; - // Set up the final configuration - if(totalNumberOfMongodServers > 0) { - serverConfig = new ReplSet(finalServers, object.rs_options); - } else { - serverConfig = new Mongos(finalServers, object.mongos_options); - } - } - - if(serverConfig == null) { - return process.nextTick(function() { - try { - callback(new Error("Could not locate any valid servers in initial seed list")); - } catch (err) { - if(db) db.close(); - throw err - } - }); - } - // Ensure no firing off open event before we are ready - serverConfig.emitOpen = false; - // Set up all options etc and connect to the database - _finishConnecting(serverConfig, object, options, callback) - } - }); - } - - // Wrap the context of the call - connectFunction(_server); - } -} - -var _setNativeParser = function(db_options) { - if(typeof db_options.native_parser == 'boolean') return db_options.native_parser; - - try { - require('bson').BSONNative.BSON; - return true; - } catch(err) { - return false; - } -} - -var _finishConnecting = function(serverConfig, object, options, callback) { - // Safe settings - var safe = {}; - // Build the safe parameter if needed - if(object.db_options.journal) safe.j = object.db_options.journal; - if(object.db_options.w) safe.w = object.db_options.w; - if(object.db_options.fsync) safe.fsync = object.db_options.fsync; - if(object.db_options.wtimeoutMS) safe.wtimeout = object.db_options.wtimeoutMS; - - // If we have a read Preference set - if(object.db_options.read_preference) { - var readPreference = new ReadPreference(object.db_options.read_preference); - // If we have the tags set up - if(object.db_options.read_preference_tags) - readPreference = new ReadPreference(object.db_options.read_preference, object.db_options.read_preference_tags); - // Add the read preference - object.db_options.readPreference = readPreference; - } - - // No safe mode if no keys - if(Object.keys(safe).length == 0) safe = false; - - // Add the safe object - object.db_options.safe = safe; - - // Get the socketTimeoutMS - var socketTimeoutMS = object.server_options.socketOptions.socketTimeoutMS || 0; - var connectTimeoutMS = object.server_options.socketOptions.connectTimeoutMS || 30000; - - // If we have a replset, override with replicaset socket timeout option if available - if(serverConfig instanceof ReplSet) { - socketTimeoutMS = object.rs_options.socketOptions.socketTimeoutMS || socketTimeoutMS; - } - - // - // Set socketTimeout to same as connectionTimeout to ensure we don't block on connect and auth - // This is a workaround for pre 2.6 servers where auth can hang when indexes are build on secondaries - serverConfig.setSocketOptions({socketTimeoutMS: connectTimeoutMS, connectTimeoutMS: connectTimeoutMS}); - - // Set up the db options - var db = new Db(object.dbName, serverConfig, object.db_options); - // Open the db - db.open(function(err, db){ - if(err) { - return process.nextTick(function() { - try { - callback(err, null); - } catch (err) { - if(db) db.close(); - throw err - } - }); - } - - // - // Set socketTimeout to same as connectionTimeout to ensure we don't block on connect and auth - // This is a workaround for pre 2.6 servers where auth can hang when indexes are build on secondaries - serverConfig.setSocketOptions({socketTimeoutMS: connectTimeoutMS, connectTimeoutMS: connectTimeoutMS}); - - // Set the provided write concern or fall back to w:1 as default - if(db.options !== null && !db.options.safe && !db.options.journal - && !db.options.w && !db.options.fsync && typeof db.options.w != 'number' - && (db.options.safe == false && object.db_options.url.indexOf("safe=") == -1)) { - db.options.w = 1; - } - - if(err == null && object.auth){ - // What db to authenticate against - var authentication_db = db; - if(object.db_options && object.db_options.authSource) { - authentication_db = db.db(object.db_options.authSource); - } - - // Build options object - var options = {}; - if(object.db_options.authMechanism) options.authMechanism = object.db_options.authMechanism; - if(object.db_options.gssapiServiceName) options.gssapiServiceName = object.db_options.gssapiServiceName; - - // Authenticate - authentication_db.authenticate(object.auth.user, object.auth.password, options, function(err, success){ - // Reset the socket timeout - serverConfig.setSocketOptions({socketTimeoutMS: socketTimeoutMS, connectTimeoutMS: connectTimeoutMS}); - - // Handle the results - if(success){ - process.nextTick(function() { - try { - callback(null, db); - } catch (err) { - if(db) db.close(); - throw err - } - }); - } else { - if(db) db.close(); - process.nextTick(function() { - try { - callback(err ? err : new Error('Could not authenticate user ' + object.auth[0]), null); - } catch (err) { - if(db) db.close(); - throw err - } - }); - } - }); - } else { - // Reset the socket timeout - serverConfig.setSocketOptions({socketTimeoutMS: socketTimeoutMS, connectTimeoutMS: connectTimeoutMS}); - - // Return connection - process.nextTick(function() { - try { - callback(err, db); - } catch (err) { - if(db) db.close(); - throw err - } - }) - } - }); -} - -exports.MongoClient = MongoClient; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/responses/mongo_reply.js b/node_modules/mongodb/lib/mongodb/responses/mongo_reply.js deleted file mode 100644 index 21e8cec..0000000 --- a/node_modules/mongodb/lib/mongodb/responses/mongo_reply.js +++ /dev/null @@ -1,83 +0,0 @@ -var Long = require('bson').Long - , timers = require('timers'); - -// Set processor, setImmediate if 0.10 otherwise nextTick -var processor = require('../utils').processor(); - -/** - Reply message from mongo db -**/ -var MongoReply = exports.MongoReply = function() { - this.documents = []; - this.index = 0; -}; - -MongoReply.prototype.parseHeader = function(binary_reply, bson) { - // Unpack the standard header first - this.messageLength = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24; - this.index = this.index + 4; - // Fetch the request id for this reply - this.requestId = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24; - this.index = this.index + 4; - // Fetch the id of the request that triggered the response - this.responseTo = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24; - // Skip op-code field - this.index = this.index + 4 + 4; - // Unpack the reply message - this.responseFlag = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24; - this.index = this.index + 4; - // Unpack the cursor id (a 64 bit long integer) - var low_bits = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24; - this.index = this.index + 4; - var high_bits = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24; - this.index = this.index + 4; - this.cursorId = new Long(low_bits, high_bits); - // Unpack the starting from - this.startingFrom = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24; - this.index = this.index + 4; - // Unpack the number of objects returned - this.numberReturned = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24; - this.index = this.index + 4; -} - -MongoReply.prototype.parseBody = function(binary_reply, bson, raw, callback) { - raw = raw == null ? false : raw; - - try { - // Let's unpack all the bson documents, deserialize them and store them - for(var object_index = 0; object_index < this.numberReturned; object_index++) { - var _options = {promoteLongs: bson.promoteLongs}; - - // Read the size of the bson object - var bsonObjectSize = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24; - - // If we are storing the raw responses to pipe straight through - if(raw) { - // Deserialize the object and add to the documents array - this.documents.push(binary_reply.slice(this.index, this.index + bsonObjectSize)); - } else { - // Deserialize the object and add to the documents array - this.documents.push(bson.deserialize(binary_reply.slice(this.index, this.index + bsonObjectSize), _options)); - } - - // Adjust binary index to point to next block of binary bson data - this.index = this.index + bsonObjectSize; - } - - // No error return - callback(null); - } catch(err) { - return callback(err); - } -} - -MongoReply.prototype.is_error = function(){ - if(this.documents.length == 1) { - return this.documents[0].ok == 1 ? false : true; - } - return false; -}; - -MongoReply.prototype.error_message = function() { - return this.documents.length == 1 && this.documents[0].ok == 1 ? '' : this.documents[0].errmsg; -}; \ No newline at end of file diff --git a/node_modules/mongodb/lib/mongodb/scope.js b/node_modules/mongodb/lib/mongodb/scope.js deleted file mode 100644 index 19ca386..0000000 --- a/node_modules/mongodb/lib/mongodb/scope.js +++ /dev/null @@ -1,86 +0,0 @@ -var Cursor = require('./cursor').Cursor - , Readable = require('stream').Readable - , utils = require('./utils') - , inherits = require('util').inherits; - -var Scope = function(collection, _selector, _fields, _scope_options) { - var self = this; - - // Ensure we have at least an empty cursor options object - _scope_options = _scope_options || {}; - var _write_concern = _scope_options.write_concern || null; - - // Ensure default read preference - // if(!_scope_options.readPreference) _scope_options.readPreference = 'primary'; - - // Set up the cursor - var _cursor = new Cursor( - collection.db, collection, _selector - , _fields, _scope_options - ); - - // Write branch options - var writeOptions = { - insert: function(documents, callback) { - // Merge together options - var options = _write_concern || {}; - // Execute insert - collection.insert(documents, options, callback); - }, - - save: function(document, callback) { - // Merge together options - var save_options = _write_concern || {}; - // Execute save - collection.save(document, save_options, function(err, result) { - if(typeof result == 'number' && result == 1) { - return callback(null, document); - } - - return callback(null, document); - }); - }, - - find: function(selector) { - _selector = selector; - return writeOptions; - }, - - // - // Update is implicit multiple document update - update: function(operations, callback) { - // Merge together options - var update_options = _write_concern || {}; - - // Set up options, multi is default operation - update_options.multi = _scope_options.multi ? _scope_options.multi : true; - if(_scope_options.upsert) update_options.upsert = _scope_options.upsert; - - // Execute options - collection.update(_selector, operations, update_options, function(err, result, obj) { - callback(err, obj); - }); - }, - } - - // Set write concern - this.withWriteConcern = function(write_concern) { - // Save the current write concern to the Scope - _scope_options.write_concern = write_concern; - _write_concern = write_concern; - // Only allow legal options - return writeOptions; - } - - // Start find - this.find = function(selector, options) { - // Save the current selector - _selector = selector; - // Set the cursor - _cursor.selector = selector; - // Return only legal read options - return Cursor.cloneWithOptions(_cursor, _scope_options); - } -} - -exports.Scope = Scope; diff --git a/node_modules/mongodb/lib/mongodb/utils.js b/node_modules/mongodb/lib/mongodb/utils.js deleted file mode 100644 index f7da514..0000000 --- a/node_modules/mongodb/lib/mongodb/utils.js +++ /dev/null @@ -1,286 +0,0 @@ -var timers = require('timers'); - -/** - * Sort functions, Normalize and prepare sort parameters - */ -var formatSortValue = exports.formatSortValue = function(sortDirection) { - var value = ("" + sortDirection).toLowerCase(); - - switch (value) { - case 'ascending': - case 'asc': - case '1': - return 1; - case 'descending': - case 'desc': - case '-1': - return -1; - default: - throw new Error("Illegal sort clause, must be of the form " - + "[['field1', '(ascending|descending)'], " - + "['field2', '(ascending|descending)']]"); - } -}; - -var formattedOrderClause = exports.formattedOrderClause = function(sortValue) { - var orderBy = {}; - if(sortValue == null) return null; - if (Array.isArray(sortValue)) { - if(sortValue.length === 0) { - return null; - } - - for(var i = 0; i < sortValue.length; i++) { - if(sortValue[i].constructor == String) { - orderBy[sortValue[i]] = 1; - } else { - orderBy[sortValue[i][0]] = formatSortValue(sortValue[i][1]); - } - } - } else if(sortValue != null && typeof sortValue == 'object') { - orderBy = sortValue; - } else if (typeof sortValue == 'string') { - orderBy[sortValue] = 1; - } else { - throw new Error("Illegal sort clause, must be of the form " + - "[['field1', '(ascending|descending)'], ['field2', '(ascending|descending)']]"); - } - - return orderBy; -}; - -exports.encodeInt = function(value) { - var buffer = new Buffer(4); - buffer[3] = (value >> 24) & 0xff; - buffer[2] = (value >> 16) & 0xff; - buffer[1] = (value >> 8) & 0xff; - buffer[0] = value & 0xff; - return buffer; -} - -exports.encodeIntInPlace = function(value, buffer, index) { - buffer[index + 3] = (value >> 24) & 0xff; - buffer[index + 2] = (value >> 16) & 0xff; - buffer[index + 1] = (value >> 8) & 0xff; - buffer[index] = value & 0xff; -} - -exports.encodeCString = function(string) { - var buf = new Buffer(string, 'utf8'); - return [buf, new Buffer([0])]; -} - -exports.decodeUInt32 = function(array, index) { - return array[index] | array[index + 1] << 8 | array[index + 2] << 16 | array[index + 3] << 24; -} - -// Decode the int -exports.decodeUInt8 = function(array, index) { - return array[index]; -} - -/** - * Context insensitive type checks - */ - -var toString = Object.prototype.toString; - -var isObject = exports.isObject = function (arg) { - return '[object Object]' == toString.call(arg) -} - -exports.isArray = function (arg) { - return Array.isArray(arg) || - 'object' == typeof arg && '[object Array]' == toString.call(arg) -} - -exports.isDate = function (arg) { - return 'object' == typeof arg && '[object Date]' == toString.call(arg) -} - -exports.isRegExp = function (arg) { - return 'object' == typeof arg && '[object RegExp]' == toString.call(arg) -} - -/** - * Wrap a Mongo error document in an Error instance - * @ignore - * @api private - */ -var toError = function(error) { - if (error instanceof Error) return error; - - var msg = error.err || error.errmsg || error.errMessage || error; - var e = new Error(msg); - e.name = 'MongoError'; - - // Get all object keys - var keys = typeof error == 'object' - ? Object.keys(error) - : []; - - for(var i = 0; i < keys.length; i++) { - e[keys[i]] = error[keys[i]]; - } - - return e; -} -exports.toError = toError; - -/** - * Convert a single level object to an array - * @ignore - * @api private - */ -exports.objectToArray = function(object) { - var list = []; - - for(var name in object) { - list.push(object[name]) - } - - return list; -} - -/** - * Handle single command document return - * @ignore - * @api private - */ -exports.handleSingleCommandResultReturn = function(override_value_true, override_value_false, callback) { - return function(err, result, connection) { - if(callback == null) return; - if(err && typeof callback == 'function') return callback(err, null); - if(!result || !result.documents || result.documents.length == 0) - if(typeof callback == 'function') return callback(toError("command failed to return results"), null) - if(result && result.documents[0].ok == 1) { - if(override_value_true) return callback(null, override_value_true) - if(typeof callback == 'function') return callback(null, result.documents[0]); - } - - // Return the error from the document - if(typeof callback == 'function') return callback(toError(result.documents[0]), override_value_false); - } -} - -/** - * Return correct processor - * @ignore - * @api private - */ -exports.processor = function() { - // Set processor, setImmediate if 0.10 otherwise nextTick - process.maxTickDepth = Infinity; - // Only use nextTick - return process.nextTick; -} - -/** - * Allow setting the socketTimeoutMS on all connections - * to work around issues such as secondaries blocking due to compaction - * - * @ignore - * @api private - */ -exports.setSocketTimeoutProperty = function(self, options) { - Object.defineProperty(self, "socketTimeoutMS", { - enumerable: true - , get: function () { return options.socketTimeoutMS; } - , set: function (value) { - // Set the socket timeoutMS value - options.socketTimeoutMS = value; - - // Get all the connections - var connections = self.allRawConnections(); - for(var i = 0; i < connections.length; i++) { - connections[i].socketTimeoutMS = value; - } - } - }); -} - -/** - * Determine if the server supports write commands - * - * @ignore - * @api private - */ -exports.hasWriteCommands = function(connection) { - return connection != null && connection.serverCapabilities != null && connection.serverCapabilities.hasWriteCommands; -} - -/** - * Fetch server capabilities - * - * @ignore - * @api private - */ -exports.serverCapabilities = function(connection) { - return connection != null && connection.serverCapabilities != null && connection.serverCapabilities.hasWriteCommands; -} - -/** - * Create index name based on field spec - * - * @ignore - * @api private - */ -exports.parseIndexOptions = function(fieldOrSpec) { - var fieldHash = {}; - var indexes = []; - var keys; - - // Get all the fields accordingly - if('string' == typeof fieldOrSpec) { - // 'type' - indexes.push(fieldOrSpec + '_' + 1); - fieldHash[fieldOrSpec] = 1; - } else if(Array.isArray(fieldOrSpec)) { - fieldOrSpec.forEach(function(f) { - if('string' == typeof f) { - // [{location:'2d'}, 'type'] - indexes.push(f + '_' + 1); - fieldHash[f] = 1; - } else if(Array.isArray(f)) { - // [['location', '2d'],['type', 1]] - indexes.push(f[0] + '_' + (f[1] || 1)); - fieldHash[f[0]] = f[1] || 1; - } else if(isObject(f)) { - // [{location:'2d'}, {type:1}] - keys = Object.keys(f); - keys.forEach(function(k) { - indexes.push(k + '_' + f[k]); - fieldHash[k] = f[k]; - }); - } else { - // undefined (ignore) - } - }); - } else if(isObject(fieldOrSpec)) { - // {location:'2d', type:1} - keys = Object.keys(fieldOrSpec); - keys.forEach(function(key) { - indexes.push(key + '_' + fieldOrSpec[key]); - fieldHash[key] = fieldOrSpec[key]; - }); - } - - return { - name: indexes.join("_"), keys: keys, fieldHash: fieldHash - } -} - -exports.decorateCommand = function(command, options, exclude) { - for(var name in options) { - if(exclude[name] == null) command[name] = options[name]; - } - - return command; -} - -exports.shallowObjectCopy = function(object) { - var c = {}; - for(var n in object) c[n] = object[n]; - return c; -} - diff --git a/node_modules/mongodb/node_modules/bson/.travis.yml b/node_modules/mongodb/node_modules/bson/.travis.yml deleted file mode 100644 index 471ed72..0000000 --- a/node_modules/mongodb/node_modules/bson/.travis.yml +++ /dev/null @@ -1,4 +0,0 @@ -language: node_js -node_js: - - 0.10 # development version of 0.8, may be unstable - - 0.11 \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/bson/LICENSE b/node_modules/mongodb/node_modules/bson/LICENSE deleted file mode 100644 index 261eeb9..0000000 --- a/node_modules/mongodb/node_modules/bson/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/node_modules/mongodb/node_modules/bson/Makefile b/node_modules/mongodb/node_modules/bson/Makefile deleted file mode 100644 index 77ce4e0..0000000 --- a/node_modules/mongodb/node_modules/bson/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -NODE = node -NPM = npm -NODEUNIT = node_modules/nodeunit/bin/nodeunit - -all: clean node_gyp - -test: clean node_gyp - npm test - -node_gyp: clean - node-gyp configure build - -clean: - node-gyp clean - -browserify: - node_modules/.bin/onejs build browser_build/package.json browser_build/bson.js - -.PHONY: all diff --git a/node_modules/mongodb/node_modules/bson/README.md b/node_modules/mongodb/node_modules/bson/README.md deleted file mode 100644 index 1a6fc2b..0000000 --- a/node_modules/mongodb/node_modules/bson/README.md +++ /dev/null @@ -1,45 +0,0 @@ -Javascript + C++ BSON parser -============================ - -This BSON parser is primarily meant for usage with the `mongodb` node.js driver. However thanks to such wonderful tools at `onejs` we are able to package up a BSON parser that will work in the browser aswell. The current build is located in the `browser_build/bson.js` file. - -A simple example on how to use it - - - - - - - - - It's got two simple methods to use in your application. - - * BSON.serialize(object, checkKeys, asBuffer, serializeFunctions) - * @param {Object} object the Javascript object to serialize. - * @param {Boolean} checkKeys the serializer will check if keys are valid. - * @param {Boolean} asBuffer return the serialized object as a Buffer object **(ignore)**. - * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)** - * @return {TypedArray/Array} returns a TypedArray or Array depending on what your browser supports - - * BSON.deserialize(buffer, options, isArray) - * Options - * **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized. - * **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse. - * **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function. - * @param {TypedArray/Array} a TypedArray/Array containing the BSON data - * @param {Object} [options] additional options used for the deserialization. - * @param {Boolean} [isArray] ignore used for recursive parsing. - * @return {Object} returns the deserialized Javascript Object. diff --git a/node_modules/mongodb/node_modules/bson/binding.gyp b/node_modules/mongodb/node_modules/bson/binding.gyp deleted file mode 100644 index c4455e7..0000000 --- a/node_modules/mongodb/node_modules/bson/binding.gyp +++ /dev/null @@ -1,18 +0,0 @@ -{ - 'targets': [ - { - 'target_name': 'bson', - 'sources': [ 'ext/bson.cc' ], - 'cflags!': [ '-fno-exceptions' ], - 'cflags_cc!': [ '-fno-exceptions' ], - 'include_dirs': [ '0){ - id = pkg.modules[i].id; - - if(id==moduleId || id == moduleIndexId){ - module = pkg.modules[i]; - break; - } - } - - return module; -} - -function newRequire(callingModule){ - function require(uri){ - var module, pkg; - - if(/^\./.test(uri)){ - module = findModule(callingModule, uri); - } else if ( ties && ties.hasOwnProperty( uri ) ) { - return ties[uri]; - } else if ( aliases && aliases.hasOwnProperty( uri ) ) { - return require(aliases[uri]); - } else { - pkg = pkgmap[uri]; - - if(!pkg && nativeRequire){ - try { - pkg = nativeRequire(uri); - } catch (nativeRequireError) {} - - if(pkg) return pkg; - } - - if(!pkg){ - throw new Error('Cannot find module "'+uri+'" @[module: '+callingModule.id+' package: '+callingModule.pkg.name+']'); - } - - module = pkg.index; - } - - if(!module){ - throw new Error('Cannot find module "'+uri+'" @[module: '+callingModule.id+' package: '+callingModule.pkg.name+']'); - } - - module.parent = callingModule; - return module.call(); - }; - - - return require; -} - - -function module(parent, id, wrapper){ - var mod = { pkg: parent, id: id, wrapper: wrapper }, - cached = false; - - mod.exports = {}; - mod.require = newRequire(mod); - - mod.call = function(){ - if(cached) { - return mod.exports; - } - - cached = true; - - global.require = mod.require; - - mod.wrapper(mod, mod.exports, global, global.require); - return mod.exports; - }; - - if(parent.mainModuleId == mod.id){ - parent.index = mod; - parent.parents.length === 0 && ( main = mod.call ); - } - - parent.modules.push(mod); -} - -function pkg(/* [ parentId ...], wrapper */){ - var wrapper = arguments[ arguments.length - 1 ], - parents = Array.prototype.slice.call(arguments, 0, arguments.length - 1), - ctx = wrapper(parents); - - - pkgmap[ctx.name] = ctx; - - arguments.length == 1 && ( pkgmap.main = ctx ); - - return function(modules){ - var id; - for(id in modules){ - module(ctx, id, modules[id]); - } - }; -} - - -}(this)); - -bson.pkg(function(parents){ - - return { - 'name' : 'bson', - 'mainModuleId' : 'bson', - 'modules' : [], - 'parents' : parents - }; - -})({ 'binary': function(module, exports, global, require, undefined){ - /** - * Module dependencies. - */ -if(typeof window === 'undefined') { - var Buffer = require('buffer').Buffer; // TODO just use global Buffer -} - -// Binary default subtype -var BSON_BINARY_SUBTYPE_DEFAULT = 0; - -/** - * @ignore - * @api private - */ -var writeStringToArray = function(data) { - // Create a buffer - var buffer = typeof Uint8Array != 'undefined' ? new Uint8Array(new ArrayBuffer(data.length)) : new Array(data.length); - // Write the content to the buffer - for(var i = 0; i < data.length; i++) { - buffer[i] = data.charCodeAt(i); - } - // Write the string to the buffer - return buffer; -} - -/** - * Convert Array ot Uint8Array to Binary String - * - * @ignore - * @api private - */ -var convertArraytoUtf8BinaryString = function(byteArray, startIndex, endIndex) { - var result = ""; - for(var i = startIndex; i < endIndex; i++) { - result = result + String.fromCharCode(byteArray[i]); - } - return result; -}; - -/** - * A class representation of the BSON Binary type. - * - * Sub types - * - **BSON.BSON_BINARY_SUBTYPE_DEFAULT**, default BSON type. - * - **BSON.BSON_BINARY_SUBTYPE_FUNCTION**, BSON function type. - * - **BSON.BSON_BINARY_SUBTYPE_BYTE_ARRAY**, BSON byte array type. - * - **BSON.BSON_BINARY_SUBTYPE_UUID**, BSON uuid type. - * - **BSON.BSON_BINARY_SUBTYPE_MD5**, BSON md5 type. - * - **BSON.BSON_BINARY_SUBTYPE_USER_DEFINED**, BSON user defined type. - * - * @class Represents the Binary BSON type. - * @param {Buffer} buffer a buffer object containing the binary data. - * @param {Number} [subType] the option binary type. - * @return {Grid} - */ -function Binary(buffer, subType) { - if(!(this instanceof Binary)) return new Binary(buffer, subType); - - this._bsontype = 'Binary'; - - if(buffer instanceof Number) { - this.sub_type = buffer; - this.position = 0; - } else { - this.sub_type = subType == null ? BSON_BINARY_SUBTYPE_DEFAULT : subType; - this.position = 0; - } - - if(buffer != null && !(buffer instanceof Number)) { - // Only accept Buffer, Uint8Array or Arrays - if(typeof buffer == 'string') { - // Different ways of writing the length of the string for the different types - if(typeof Buffer != 'undefined') { - this.buffer = new Buffer(buffer); - } else if(typeof Uint8Array != 'undefined' || (Object.prototype.toString.call(buffer) == '[object Array]')) { - this.buffer = writeStringToArray(buffer); - } else { - throw new Error("only String, Buffer, Uint8Array or Array accepted"); - } - } else { - this.buffer = buffer; - } - this.position = buffer.length; - } else { - if(typeof Buffer != 'undefined') { - this.buffer = new Buffer(Binary.BUFFER_SIZE); - } else if(typeof Uint8Array != 'undefined'){ - this.buffer = new Uint8Array(new ArrayBuffer(Binary.BUFFER_SIZE)); - } else { - this.buffer = new Array(Binary.BUFFER_SIZE); - } - // Set position to start of buffer - this.position = 0; - } -}; - -/** - * Updates this binary with byte_value. - * - * @param {Character} byte_value a single byte we wish to write. - * @api public - */ -Binary.prototype.put = function put(byte_value) { - // If it's a string and a has more than one character throw an error - if(byte_value['length'] != null && typeof byte_value != 'number' && byte_value.length != 1) throw new Error("only accepts single character String, Uint8Array or Array"); - if(typeof byte_value != 'number' && byte_value < 0 || byte_value > 255) throw new Error("only accepts number in a valid unsigned byte range 0-255"); - - // Decode the byte value once - var decoded_byte = null; - if(typeof byte_value == 'string') { - decoded_byte = byte_value.charCodeAt(0); - } else if(byte_value['length'] != null) { - decoded_byte = byte_value[0]; - } else { - decoded_byte = byte_value; - } - - if(this.buffer.length > this.position) { - this.buffer[this.position++] = decoded_byte; - } else { - if(typeof Buffer != 'undefined' && Buffer.isBuffer(this.buffer)) { - // Create additional overflow buffer - var buffer = new Buffer(Binary.BUFFER_SIZE + this.buffer.length); - // Combine the two buffers together - this.buffer.copy(buffer, 0, 0, this.buffer.length); - this.buffer = buffer; - this.buffer[this.position++] = decoded_byte; - } else { - var buffer = null; - // Create a new buffer (typed or normal array) - if(Object.prototype.toString.call(this.buffer) == '[object Uint8Array]') { - buffer = new Uint8Array(new ArrayBuffer(Binary.BUFFER_SIZE + this.buffer.length)); - } else { - buffer = new Array(Binary.BUFFER_SIZE + this.buffer.length); - } - - // We need to copy all the content to the new array - for(var i = 0; i < this.buffer.length; i++) { - buffer[i] = this.buffer[i]; - } - - // Reassign the buffer - this.buffer = buffer; - // Write the byte - this.buffer[this.position++] = decoded_byte; - } - } -}; - -/** - * Writes a buffer or string to the binary. - * - * @param {Buffer|String} string a string or buffer to be written to the Binary BSON object. - * @param {Number} offset specify the binary of where to write the content. - * @api public - */ -Binary.prototype.write = function write(string, offset) { - offset = typeof offset == 'number' ? offset : this.position; - - // If the buffer is to small let's extend the buffer - if(this.buffer.length < offset + string.length) { - var buffer = null; - // If we are in node.js - if(typeof Buffer != 'undefined' && Buffer.isBuffer(this.buffer)) { - buffer = new Buffer(this.buffer.length + string.length); - this.buffer.copy(buffer, 0, 0, this.buffer.length); - } else if(Object.prototype.toString.call(this.buffer) == '[object Uint8Array]') { - // Create a new buffer - buffer = new Uint8Array(new ArrayBuffer(this.buffer.length + string.length)) - // Copy the content - for(var i = 0; i < this.position; i++) { - buffer[i] = this.buffer[i]; - } - } - - // Assign the new buffer - this.buffer = buffer; - } - - if(typeof Buffer != 'undefined' && Buffer.isBuffer(string) && Buffer.isBuffer(this.buffer)) { - string.copy(this.buffer, offset, 0, string.length); - this.position = (offset + string.length) > this.position ? (offset + string.length) : this.position; - // offset = string.length - } else if(typeof Buffer != 'undefined' && typeof string == 'string' && Buffer.isBuffer(this.buffer)) { - this.buffer.write(string, 'binary', offset); - this.position = (offset + string.length) > this.position ? (offset + string.length) : this.position; - // offset = string.length; - } else if(Object.prototype.toString.call(string) == '[object Uint8Array]' - || Object.prototype.toString.call(string) == '[object Array]' && typeof string != 'string') { - for(var i = 0; i < string.length; i++) { - this.buffer[offset++] = string[i]; - } - - this.position = offset > this.position ? offset : this.position; - } else if(typeof string == 'string') { - for(var i = 0; i < string.length; i++) { - this.buffer[offset++] = string.charCodeAt(i); - } - - this.position = offset > this.position ? offset : this.position; - } -}; - -/** - * Reads **length** bytes starting at **position**. - * - * @param {Number} position read from the given position in the Binary. - * @param {Number} length the number of bytes to read. - * @return {Buffer} - * @api public - */ -Binary.prototype.read = function read(position, length) { - length = length && length > 0 - ? length - : this.position; - - // Let's return the data based on the type we have - if(this.buffer['slice']) { - return this.buffer.slice(position, position + length); - } else { - // Create a buffer to keep the result - var buffer = typeof Uint8Array != 'undefined' ? new Uint8Array(new ArrayBuffer(length)) : new Array(length); - for(var i = 0; i < length; i++) { - buffer[i] = this.buffer[position++]; - } - } - // Return the buffer - return buffer; -}; - -/** - * Returns the value of this binary as a string. - * - * @return {String} - * @api public - */ -Binary.prototype.value = function value(asRaw) { - asRaw = asRaw == null ? false : asRaw; - - // If it's a node.js buffer object - if(typeof Buffer != 'undefined' && Buffer.isBuffer(this.buffer)) { - return asRaw ? this.buffer.slice(0, this.position) : this.buffer.toString('binary', 0, this.position); - } else { - if(asRaw) { - // we support the slice command use it - if(this.buffer['slice'] != null) { - return this.buffer.slice(0, this.position); - } else { - // Create a new buffer to copy content to - var newBuffer = Object.prototype.toString.call(this.buffer) == '[object Uint8Array]' ? new Uint8Array(new ArrayBuffer(this.position)) : new Array(this.position); - // Copy content - for(var i = 0; i < this.position; i++) { - newBuffer[i] = this.buffer[i]; - } - // Return the buffer - return newBuffer; - } - } else { - return convertArraytoUtf8BinaryString(this.buffer, 0, this.position); - } - } -}; - -/** - * Length. - * - * @return {Number} the length of the binary. - * @api public - */ -Binary.prototype.length = function length() { - return this.position; -}; - -/** - * @ignore - * @api private - */ -Binary.prototype.toJSON = function() { - return this.buffer != null ? this.buffer.toString('base64') : ''; -} - -/** - * @ignore - * @api private - */ -Binary.prototype.toString = function(format) { - return this.buffer != null ? this.buffer.slice(0, this.position).toString(format) : ''; -} - -Binary.BUFFER_SIZE = 256; - -/** - * Default BSON type - * - * @classconstant SUBTYPE_DEFAULT - **/ -Binary.SUBTYPE_DEFAULT = 0; -/** - * Function BSON type - * - * @classconstant SUBTYPE_DEFAULT - **/ -Binary.SUBTYPE_FUNCTION = 1; -/** - * Byte Array BSON type - * - * @classconstant SUBTYPE_DEFAULT - **/ -Binary.SUBTYPE_BYTE_ARRAY = 2; -/** - * OLD UUID BSON type - * - * @classconstant SUBTYPE_DEFAULT - **/ -Binary.SUBTYPE_UUID_OLD = 3; -/** - * UUID BSON type - * - * @classconstant SUBTYPE_DEFAULT - **/ -Binary.SUBTYPE_UUID = 4; -/** - * MD5 BSON type - * - * @classconstant SUBTYPE_DEFAULT - **/ -Binary.SUBTYPE_MD5 = 5; -/** - * User BSON type - * - * @classconstant SUBTYPE_DEFAULT - **/ -Binary.SUBTYPE_USER_DEFINED = 128; - -/** - * Expose. - */ -exports.Binary = Binary; - - -}, - - - -'binary_parser': function(module, exports, global, require, undefined){ - /** - * Binary Parser. - * Jonas Raoni Soares Silva - * http://jsfromhell.com/classes/binary-parser [v1.0] - */ -var chr = String.fromCharCode; - -var maxBits = []; -for (var i = 0; i < 64; i++) { - maxBits[i] = Math.pow(2, i); -} - -function BinaryParser (bigEndian, allowExceptions) { - if(!(this instanceof BinaryParser)) return new BinaryParser(bigEndian, allowExceptions); - - this.bigEndian = bigEndian; - this.allowExceptions = allowExceptions; -}; - -BinaryParser.warn = function warn (msg) { - if (this.allowExceptions) { - throw new Error(msg); - } - - return 1; -}; - -BinaryParser.decodeFloat = function decodeFloat (data, precisionBits, exponentBits) { - var b = new this.Buffer(this.bigEndian, data); - - b.checkBuffer(precisionBits + exponentBits + 1); - - var bias = maxBits[exponentBits - 1] - 1 - , signal = b.readBits(precisionBits + exponentBits, 1) - , exponent = b.readBits(precisionBits, exponentBits) - , significand = 0 - , divisor = 2 - , curByte = b.buffer.length + (-precisionBits >> 3) - 1; - - do { - for (var byteValue = b.buffer[ ++curByte ], startBit = precisionBits % 8 || 8, mask = 1 << startBit; mask >>= 1; ( byteValue & mask ) && ( significand += 1 / divisor ), divisor *= 2 ); - } while (precisionBits -= startBit); - - return exponent == ( bias << 1 ) + 1 ? significand ? NaN : signal ? -Infinity : +Infinity : ( 1 + signal * -2 ) * ( exponent || significand ? !exponent ? Math.pow( 2, -bias + 1 ) * significand : Math.pow( 2, exponent - bias ) * ( 1 + significand ) : 0 ); -}; - -BinaryParser.decodeInt = function decodeInt (data, bits, signed, forceBigEndian) { - var b = new this.Buffer(this.bigEndian || forceBigEndian, data) - , x = b.readBits(0, bits) - , max = maxBits[bits]; //max = Math.pow( 2, bits ); - - return signed && x >= max / 2 - ? x - max - : x; -}; - -BinaryParser.encodeFloat = function encodeFloat (data, precisionBits, exponentBits) { - var bias = maxBits[exponentBits - 1] - 1 - , minExp = -bias + 1 - , maxExp = bias - , minUnnormExp = minExp - precisionBits - , n = parseFloat(data) - , status = isNaN(n) || n == -Infinity || n == +Infinity ? n : 0 - , exp = 0 - , len = 2 * bias + 1 + precisionBits + 3 - , bin = new Array(len) - , signal = (n = status !== 0 ? 0 : n) < 0 - , intPart = Math.floor(n = Math.abs(n)) - , floatPart = n - intPart - , lastBit - , rounded - , result - , i - , j; - - for (i = len; i; bin[--i] = 0); - - for (i = bias + 2; intPart && i; bin[--i] = intPart % 2, intPart = Math.floor(intPart / 2)); - - for (i = bias + 1; floatPart > 0 && i; (bin[++i] = ((floatPart *= 2) >= 1) - 0 ) && --floatPart); - - for (i = -1; ++i < len && !bin[i];); - - if (bin[(lastBit = precisionBits - 1 + (i = (exp = bias + 1 - i) >= minExp && exp <= maxExp ? i + 1 : bias + 1 - (exp = minExp - 1))) + 1]) { - if (!(rounded = bin[lastBit])) { - for (j = lastBit + 2; !rounded && j < len; rounded = bin[j++]); - } - - for (j = lastBit + 1; rounded && --j >= 0; (bin[j] = !bin[j] - 0) && (rounded = 0)); - } - - for (i = i - 2 < 0 ? -1 : i - 3; ++i < len && !bin[i];); - - if ((exp = bias + 1 - i) >= minExp && exp <= maxExp) { - ++i; - } else if (exp < minExp) { - exp != bias + 1 - len && exp < minUnnormExp && this.warn("encodeFloat::float underflow"); - i = bias + 1 - (exp = minExp - 1); - } - - if (intPart || status !== 0) { - this.warn(intPart ? "encodeFloat::float overflow" : "encodeFloat::" + status); - exp = maxExp + 1; - i = bias + 2; - - if (status == -Infinity) { - signal = 1; - } else if (isNaN(status)) { - bin[i] = 1; - } - } - - for (n = Math.abs(exp + bias), j = exponentBits + 1, result = ""; --j; result = (n % 2) + result, n = n >>= 1); - - for (n = 0, j = 0, i = (result = (signal ? "1" : "0") + result + bin.slice(i, i + precisionBits).join("")).length, r = []; i; j = (j + 1) % 8) { - n += (1 << j) * result.charAt(--i); - if (j == 7) { - r[r.length] = String.fromCharCode(n); - n = 0; - } - } - - r[r.length] = n - ? String.fromCharCode(n) - : ""; - - return (this.bigEndian ? r.reverse() : r).join(""); -}; - -BinaryParser.encodeInt = function encodeInt (data, bits, signed, forceBigEndian) { - var max = maxBits[bits]; - - if (data >= max || data < -(max / 2)) { - this.warn("encodeInt::overflow"); - data = 0; - } - - if (data < 0) { - data += max; - } - - for (var r = []; data; r[r.length] = String.fromCharCode(data % 256), data = Math.floor(data / 256)); - - for (bits = -(-bits >> 3) - r.length; bits--; r[r.length] = "\0"); - - return ((this.bigEndian || forceBigEndian) ? r.reverse() : r).join(""); -}; - -BinaryParser.toSmall = function( data ){ return this.decodeInt( data, 8, true ); }; -BinaryParser.fromSmall = function( data ){ return this.encodeInt( data, 8, true ); }; -BinaryParser.toByte = function( data ){ return this.decodeInt( data, 8, false ); }; -BinaryParser.fromByte = function( data ){ return this.encodeInt( data, 8, false ); }; -BinaryParser.toShort = function( data ){ return this.decodeInt( data, 16, true ); }; -BinaryParser.fromShort = function( data ){ return this.encodeInt( data, 16, true ); }; -BinaryParser.toWord = function( data ){ return this.decodeInt( data, 16, false ); }; -BinaryParser.fromWord = function( data ){ return this.encodeInt( data, 16, false ); }; -BinaryParser.toInt = function( data ){ return this.decodeInt( data, 32, true ); }; -BinaryParser.fromInt = function( data ){ return this.encodeInt( data, 32, true ); }; -BinaryParser.toLong = function( data ){ return this.decodeInt( data, 64, true ); }; -BinaryParser.fromLong = function( data ){ return this.encodeInt( data, 64, true ); }; -BinaryParser.toDWord = function( data ){ return this.decodeInt( data, 32, false ); }; -BinaryParser.fromDWord = function( data ){ return this.encodeInt( data, 32, false ); }; -BinaryParser.toQWord = function( data ){ return this.decodeInt( data, 64, true ); }; -BinaryParser.fromQWord = function( data ){ return this.encodeInt( data, 64, true ); }; -BinaryParser.toFloat = function( data ){ return this.decodeFloat( data, 23, 8 ); }; -BinaryParser.fromFloat = function( data ){ return this.encodeFloat( data, 23, 8 ); }; -BinaryParser.toDouble = function( data ){ return this.decodeFloat( data, 52, 11 ); }; -BinaryParser.fromDouble = function( data ){ return this.encodeFloat( data, 52, 11 ); }; - -// Factor out the encode so it can be shared by add_header and push_int32 -BinaryParser.encode_int32 = function encode_int32 (number, asArray) { - var a, b, c, d, unsigned; - unsigned = (number < 0) ? (number + 0x100000000) : number; - a = Math.floor(unsigned / 0xffffff); - unsigned &= 0xffffff; - b = Math.floor(unsigned / 0xffff); - unsigned &= 0xffff; - c = Math.floor(unsigned / 0xff); - unsigned &= 0xff; - d = Math.floor(unsigned); - return asArray ? [chr(a), chr(b), chr(c), chr(d)] : chr(a) + chr(b) + chr(c) + chr(d); -}; - -BinaryParser.encode_int64 = function encode_int64 (number) { - var a, b, c, d, e, f, g, h, unsigned; - unsigned = (number < 0) ? (number + 0x10000000000000000) : number; - a = Math.floor(unsigned / 0xffffffffffffff); - unsigned &= 0xffffffffffffff; - b = Math.floor(unsigned / 0xffffffffffff); - unsigned &= 0xffffffffffff; - c = Math.floor(unsigned / 0xffffffffff); - unsigned &= 0xffffffffff; - d = Math.floor(unsigned / 0xffffffff); - unsigned &= 0xffffffff; - e = Math.floor(unsigned / 0xffffff); - unsigned &= 0xffffff; - f = Math.floor(unsigned / 0xffff); - unsigned &= 0xffff; - g = Math.floor(unsigned / 0xff); - unsigned &= 0xff; - h = Math.floor(unsigned); - return chr(a) + chr(b) + chr(c) + chr(d) + chr(e) + chr(f) + chr(g) + chr(h); -}; - -/** - * UTF8 methods - */ - -// Take a raw binary string and return a utf8 string -BinaryParser.decode_utf8 = function decode_utf8 (binaryStr) { - var len = binaryStr.length - , decoded = '' - , i = 0 - , c = 0 - , c1 = 0 - , c2 = 0 - , c3; - - while (i < len) { - c = binaryStr.charCodeAt(i); - if (c < 128) { - decoded += String.fromCharCode(c); - i++; - } else if ((c > 191) && (c < 224)) { - c2 = binaryStr.charCodeAt(i+1); - decoded += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); - i += 2; - } else { - c2 = binaryStr.charCodeAt(i+1); - c3 = binaryStr.charCodeAt(i+2); - decoded += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); - i += 3; - } - } - - return decoded; -}; - -// Encode a cstring -BinaryParser.encode_cstring = function encode_cstring (s) { - return unescape(encodeURIComponent(s)) + BinaryParser.fromByte(0); -}; - -// Take a utf8 string and return a binary string -BinaryParser.encode_utf8 = function encode_utf8 (s) { - var a = "" - , c; - - for (var n = 0, len = s.length; n < len; n++) { - c = s.charCodeAt(n); - - if (c < 128) { - a += String.fromCharCode(c); - } else if ((c > 127) && (c < 2048)) { - a += String.fromCharCode((c>>6) | 192) ; - a += String.fromCharCode((c&63) | 128); - } else { - a += String.fromCharCode((c>>12) | 224); - a += String.fromCharCode(((c>>6) & 63) | 128); - a += String.fromCharCode((c&63) | 128); - } - } - - return a; -}; - -BinaryParser.hprint = function hprint (s) { - var number; - - for (var i = 0, len = s.length; i < len; i++) { - if (s.charCodeAt(i) < 32) { - number = s.charCodeAt(i) <= 15 - ? "0" + s.charCodeAt(i).toString(16) - : s.charCodeAt(i).toString(16); - process.stdout.write(number + " ") - } else { - number = s.charCodeAt(i) <= 15 - ? "0" + s.charCodeAt(i).toString(16) - : s.charCodeAt(i).toString(16); - process.stdout.write(number + " ") - } - } - - process.stdout.write("\n\n"); -}; - -BinaryParser.ilprint = function hprint (s) { - var number; - - for (var i = 0, len = s.length; i < len; i++) { - if (s.charCodeAt(i) < 32) { - number = s.charCodeAt(i) <= 15 - ? "0" + s.charCodeAt(i).toString(10) - : s.charCodeAt(i).toString(10); - - require('util').debug(number+' : '); - } else { - number = s.charCodeAt(i) <= 15 - ? "0" + s.charCodeAt(i).toString(10) - : s.charCodeAt(i).toString(10); - require('util').debug(number+' : '+ s.charAt(i)); - } - } -}; - -BinaryParser.hlprint = function hprint (s) { - var number; - - for (var i = 0, len = s.length; i < len; i++) { - if (s.charCodeAt(i) < 32) { - number = s.charCodeAt(i) <= 15 - ? "0" + s.charCodeAt(i).toString(16) - : s.charCodeAt(i).toString(16); - require('util').debug(number+' : '); - } else { - number = s.charCodeAt(i) <= 15 - ? "0" + s.charCodeAt(i).toString(16) - : s.charCodeAt(i).toString(16); - require('util').debug(number+' : '+ s.charAt(i)); - } - } -}; - -/** - * BinaryParser buffer constructor. - */ -function BinaryParserBuffer (bigEndian, buffer) { - this.bigEndian = bigEndian || 0; - this.buffer = []; - this.setBuffer(buffer); -}; - -BinaryParserBuffer.prototype.setBuffer = function setBuffer (data) { - var l, i, b; - - if (data) { - i = l = data.length; - b = this.buffer = new Array(l); - for (; i; b[l - i] = data.charCodeAt(--i)); - this.bigEndian && b.reverse(); - } -}; - -BinaryParserBuffer.prototype.hasNeededBits = function hasNeededBits (neededBits) { - return this.buffer.length >= -(-neededBits >> 3); -}; - -BinaryParserBuffer.prototype.checkBuffer = function checkBuffer (neededBits) { - if (!this.hasNeededBits(neededBits)) { - throw new Error("checkBuffer::missing bytes"); - } -}; - -BinaryParserBuffer.prototype.readBits = function readBits (start, length) { - //shl fix: Henri Torgemane ~1996 (compressed by Jonas Raoni) - - function shl (a, b) { - for (; b--; a = ((a %= 0x7fffffff + 1) & 0x40000000) == 0x40000000 ? a * 2 : (a - 0x40000000) * 2 + 0x7fffffff + 1); - return a; - } - - if (start < 0 || length <= 0) { - return 0; - } - - this.checkBuffer(start + length); - - var offsetLeft - , offsetRight = start % 8 - , curByte = this.buffer.length - ( start >> 3 ) - 1 - , lastByte = this.buffer.length + ( -( start + length ) >> 3 ) - , diff = curByte - lastByte - , sum = ((this.buffer[ curByte ] >> offsetRight) & ((1 << (diff ? 8 - offsetRight : length)) - 1)) + (diff && (offsetLeft = (start + length) % 8) ? (this.buffer[lastByte++] & ((1 << offsetLeft) - 1)) << (diff-- << 3) - offsetRight : 0); - - for(; diff; sum += shl(this.buffer[lastByte++], (diff-- << 3) - offsetRight)); - - return sum; -}; - -/** - * Expose. - */ -BinaryParser.Buffer = BinaryParserBuffer; - -exports.BinaryParser = BinaryParser; - -}, - - - -'bson': function(module, exports, global, require, undefined){ - var Long = require('./long').Long - , Double = require('./double').Double - , Timestamp = require('./timestamp').Timestamp - , ObjectID = require('./objectid').ObjectID - , Symbol = require('./symbol').Symbol - , Code = require('./code').Code - , MinKey = require('./min_key').MinKey - , MaxKey = require('./max_key').MaxKey - , DBRef = require('./db_ref').DBRef - , Binary = require('./binary').Binary - , BinaryParser = require('./binary_parser').BinaryParser - , writeIEEE754 = require('./float_parser').writeIEEE754 - , readIEEE754 = require('./float_parser').readIEEE754 - -// To ensure that 0.4 of node works correctly -var isDate = function isDate(d) { - return typeof d === 'object' && Object.prototype.toString.call(d) === '[object Date]'; -} - -/** - * Create a new BSON instance - * - * @class Represents the BSON Parser - * @return {BSON} instance of BSON Parser. - */ -function BSON () {}; - -/** - * @ignore - * @api private - */ -// BSON MAX VALUES -BSON.BSON_INT32_MAX = 0x7FFFFFFF; -BSON.BSON_INT32_MIN = -0x80000000; - -BSON.BSON_INT64_MAX = Math.pow(2, 63) - 1; -BSON.BSON_INT64_MIN = -Math.pow(2, 63); - -// JS MAX PRECISE VALUES -BSON.JS_INT_MAX = 0x20000000000000; // Any integer up to 2^53 can be precisely represented by a double. -BSON.JS_INT_MIN = -0x20000000000000; // Any integer down to -2^53 can be precisely represented by a double. - -// Internal long versions -var JS_INT_MAX_LONG = Long.fromNumber(0x20000000000000); // Any integer up to 2^53 can be precisely represented by a double. -var JS_INT_MIN_LONG = Long.fromNumber(-0x20000000000000); // Any integer down to -2^53 can be precisely represented by a double. - -/** - * Number BSON Type - * - * @classconstant BSON_DATA_NUMBER - **/ -BSON.BSON_DATA_NUMBER = 1; -/** - * String BSON Type - * - * @classconstant BSON_DATA_STRING - **/ -BSON.BSON_DATA_STRING = 2; -/** - * Object BSON Type - * - * @classconstant BSON_DATA_OBJECT - **/ -BSON.BSON_DATA_OBJECT = 3; -/** - * Array BSON Type - * - * @classconstant BSON_DATA_ARRAY - **/ -BSON.BSON_DATA_ARRAY = 4; -/** - * Binary BSON Type - * - * @classconstant BSON_DATA_BINARY - **/ -BSON.BSON_DATA_BINARY = 5; -/** - * ObjectID BSON Type - * - * @classconstant BSON_DATA_OID - **/ -BSON.BSON_DATA_OID = 7; -/** - * Boolean BSON Type - * - * @classconstant BSON_DATA_BOOLEAN - **/ -BSON.BSON_DATA_BOOLEAN = 8; -/** - * Date BSON Type - * - * @classconstant BSON_DATA_DATE - **/ -BSON.BSON_DATA_DATE = 9; -/** - * null BSON Type - * - * @classconstant BSON_DATA_NULL - **/ -BSON.BSON_DATA_NULL = 10; -/** - * RegExp BSON Type - * - * @classconstant BSON_DATA_REGEXP - **/ -BSON.BSON_DATA_REGEXP = 11; -/** - * Code BSON Type - * - * @classconstant BSON_DATA_CODE - **/ -BSON.BSON_DATA_CODE = 13; -/** - * Symbol BSON Type - * - * @classconstant BSON_DATA_SYMBOL - **/ -BSON.BSON_DATA_SYMBOL = 14; -/** - * Code with Scope BSON Type - * - * @classconstant BSON_DATA_CODE_W_SCOPE - **/ -BSON.BSON_DATA_CODE_W_SCOPE = 15; -/** - * 32 bit Integer BSON Type - * - * @classconstant BSON_DATA_INT - **/ -BSON.BSON_DATA_INT = 16; -/** - * Timestamp BSON Type - * - * @classconstant BSON_DATA_TIMESTAMP - **/ -BSON.BSON_DATA_TIMESTAMP = 17; -/** - * Long BSON Type - * - * @classconstant BSON_DATA_LONG - **/ -BSON.BSON_DATA_LONG = 18; -/** - * MinKey BSON Type - * - * @classconstant BSON_DATA_MIN_KEY - **/ -BSON.BSON_DATA_MIN_KEY = 0xff; -/** - * MaxKey BSON Type - * - * @classconstant BSON_DATA_MAX_KEY - **/ -BSON.BSON_DATA_MAX_KEY = 0x7f; - -/** - * Binary Default Type - * - * @classconstant BSON_BINARY_SUBTYPE_DEFAULT - **/ -BSON.BSON_BINARY_SUBTYPE_DEFAULT = 0; -/** - * Binary Function Type - * - * @classconstant BSON_BINARY_SUBTYPE_FUNCTION - **/ -BSON.BSON_BINARY_SUBTYPE_FUNCTION = 1; -/** - * Binary Byte Array Type - * - * @classconstant BSON_BINARY_SUBTYPE_BYTE_ARRAY - **/ -BSON.BSON_BINARY_SUBTYPE_BYTE_ARRAY = 2; -/** - * Binary UUID Type - * - * @classconstant BSON_BINARY_SUBTYPE_UUID - **/ -BSON.BSON_BINARY_SUBTYPE_UUID = 3; -/** - * Binary MD5 Type - * - * @classconstant BSON_BINARY_SUBTYPE_MD5 - **/ -BSON.BSON_BINARY_SUBTYPE_MD5 = 4; -/** - * Binary User Defined Type - * - * @classconstant BSON_BINARY_SUBTYPE_USER_DEFINED - **/ -BSON.BSON_BINARY_SUBTYPE_USER_DEFINED = 128; - -/** - * Calculate the bson size for a passed in Javascript object. - * - * @param {Object} object the Javascript object to calculate the BSON byte size for. - * @param {Boolean} [serializeFunctions] serialize all functions in the object **(default:false)**. - * @return {Number} returns the number of bytes the BSON object will take up. - * @api public - */ -BSON.calculateObjectSize = function calculateObjectSize(object, serializeFunctions) { - var totalLength = (4 + 1); - - if(Array.isArray(object)) { - for(var i = 0; i < object.length; i++) { - totalLength += calculateElement(i.toString(), object[i], serializeFunctions) - } - } else { - // If we have toBSON defined, override the current object - if(object.toBSON) { - object = object.toBSON(); - } - - // Calculate size - for(var key in object) { - totalLength += calculateElement(key, object[key], serializeFunctions) - } - } - - return totalLength; -} - -/** - * @ignore - * @api private - */ -function calculateElement(name, value, serializeFunctions) { - var isBuffer = typeof Buffer !== 'undefined'; - - switch(typeof value) { - case 'string': - return 1 + (!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1 + 4 + (!isBuffer ? numberOfBytes(value) : Buffer.byteLength(value, 'utf8')) + 1; - case 'number': - if(Math.floor(value) === value && value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) { - if(value >= BSON.BSON_INT32_MIN && value <= BSON.BSON_INT32_MAX) { // 32 bit - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (4 + 1); - } else { - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (8 + 1); - } - } else { // 64 bit - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (8 + 1); - } - case 'undefined': - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (1); - case 'boolean': - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (1 + 1); - case 'object': - if(value == null || value instanceof MinKey || value instanceof MaxKey || value['_bsontype'] == 'MinKey' || value['_bsontype'] == 'MaxKey') { - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (1); - } else if(value instanceof ObjectID || value['_bsontype'] == 'ObjectID') { - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (12 + 1); - } else if(value instanceof Date || isDate(value)) { - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (8 + 1); - } else if(typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) { - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (1 + 4 + 1) + value.length; - } else if(value instanceof Long || value instanceof Double || value instanceof Timestamp - || value['_bsontype'] == 'Long' || value['_bsontype'] == 'Double' || value['_bsontype'] == 'Timestamp') { - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (8 + 1); - } else if(value instanceof Code || value['_bsontype'] == 'Code') { - // Calculate size depending on the availability of a scope - if(value.scope != null && Object.keys(value.scope).length > 0) { - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + 4 + 4 + (!isBuffer ? numberOfBytes(value.code.toString()) : Buffer.byteLength(value.code.toString(), 'utf8')) + 1 + BSON.calculateObjectSize(value.scope, serializeFunctions); - } else { - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + 4 + (!isBuffer ? numberOfBytes(value.code.toString()) : Buffer.byteLength(value.code.toString(), 'utf8')) + 1; - } - } else if(value instanceof Binary || value['_bsontype'] == 'Binary') { - // Check what kind of subtype we have - if(value.sub_type == Binary.SUBTYPE_BYTE_ARRAY) { - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (value.position + 1 + 4 + 1 + 4); - } else { - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (value.position + 1 + 4 + 1); - } - } else if(value instanceof Symbol || value['_bsontype'] == 'Symbol') { - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + ((!isBuffer ? numberOfBytes(value.value) : Buffer.byteLength(value.value, 'utf8')) + 4 + 1 + 1); - } else if(value instanceof DBRef || value['_bsontype'] == 'DBRef') { - // Set up correct object for serialization - var ordered_values = { - '$ref': value.namespace - , '$id' : value.oid - }; - - // Add db reference if it exists - if(null != value.db) { - ordered_values['$db'] = value.db; - } - - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + BSON.calculateObjectSize(ordered_values, serializeFunctions); - } else if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]') { - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + (!isBuffer ? numberOfBytes(value.source) : Buffer.byteLength(value.source, 'utf8')) + 1 - + (value.global ? 1 : 0) + (value.ignoreCase ? 1 : 0) + (value.multiline ? 1 : 0) + 1 - } else { - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + BSON.calculateObjectSize(value, serializeFunctions) + 1; - } - case 'function': - // WTF for 0.4.X where typeof /someregexp/ === 'function' - if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]' || String.call(value) == '[object RegExp]') { - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + (!isBuffer ? numberOfBytes(value.source) : Buffer.byteLength(value.source, 'utf8')) + 1 - + (value.global ? 1 : 0) + (value.ignoreCase ? 1 : 0) + (value.multiline ? 1 : 0) + 1 - } else { - if(serializeFunctions && value.scope != null && Object.keys(value.scope).length > 0) { - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + 4 + 4 + (!isBuffer ? numberOfBytes(value.toString()) : Buffer.byteLength(value.toString(), 'utf8')) + 1 + BSON.calculateObjectSize(value.scope, serializeFunctions); - } else if(serializeFunctions) { - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + 4 + (!isBuffer ? numberOfBytes(value.toString()) : Buffer.byteLength(value.toString(), 'utf8')) + 1; - } - } - } - - return 0; -} - -/** - * Serialize a Javascript object using a predefined Buffer and index into the buffer, useful when pre-allocating the space for serialization. - * - * @param {Object} object the Javascript object to serialize. - * @param {Boolean} checkKeys the serializer will check if keys are valid. - * @param {Buffer} buffer the Buffer you pre-allocated to store the serialized BSON object. - * @param {Number} index the index in the buffer where we wish to start serializing into. - * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**. - * @return {Number} returns the new write index in the Buffer. - * @api public - */ -BSON.serializeWithBufferAndIndex = function serializeWithBufferAndIndex(object, checkKeys, buffer, index, serializeFunctions) { - // Default setting false - serializeFunctions = serializeFunctions == null ? false : serializeFunctions; - // Write end information (length of the object) - var size = buffer.length; - // Write the size of the object - buffer[index++] = size & 0xff; - buffer[index++] = (size >> 8) & 0xff; - buffer[index++] = (size >> 16) & 0xff; - buffer[index++] = (size >> 24) & 0xff; - return serializeObject(object, checkKeys, buffer, index, serializeFunctions) - 1; -} - -/** - * @ignore - * @api private - */ -var serializeObject = function(object, checkKeys, buffer, index, serializeFunctions) { - // Process the object - if(Array.isArray(object)) { - for(var i = 0; i < object.length; i++) { - index = packElement(i.toString(), object[i], checkKeys, buffer, index, serializeFunctions); - } - } else { - // If we have toBSON defined, override the current object - if(object.toBSON) { - object = object.toBSON(); - } - - // Serialize the object - for(var key in object) { - // Check the key and throw error if it's illegal - if (key != '$db' && key != '$ref' && key != '$id') { - // dollars and dots ok - BSON.checkKey(key, !checkKeys); - } - - // Pack the element - index = packElement(key, object[key], checkKeys, buffer, index, serializeFunctions); - } - } - - // Write zero - buffer[index++] = 0; - return index; -} - -var stringToBytes = function(str) { - var ch, st, re = []; - for (var i = 0; i < str.length; i++ ) { - ch = str.charCodeAt(i); // get char - st = []; // set up "stack" - do { - st.push( ch & 0xFF ); // push byte to stack - ch = ch >> 8; // shift value down by 1 byte - } - while ( ch ); - // add stack contents to result - // done because chars have "wrong" endianness - re = re.concat( st.reverse() ); - } - // return an array of bytes - return re; -} - -var numberOfBytes = function(str) { - var ch, st, re = 0; - for (var i = 0; i < str.length; i++ ) { - ch = str.charCodeAt(i); // get char - st = []; // set up "stack" - do { - st.push( ch & 0xFF ); // push byte to stack - ch = ch >> 8; // shift value down by 1 byte - } - while ( ch ); - // add stack contents to result - // done because chars have "wrong" endianness - re = re + st.length; - } - // return an array of bytes - return re; -} - -/** - * @ignore - * @api private - */ -var writeToTypedArray = function(buffer, string, index) { - var bytes = stringToBytes(string); - for(var i = 0; i < bytes.length; i++) { - buffer[index + i] = bytes[i]; - } - return bytes.length; -} - -/** - * @ignore - * @api private - */ -var supportsBuffer = typeof Buffer != 'undefined'; - -/** - * @ignore - * @api private - */ -var packElement = function(name, value, checkKeys, buffer, index, serializeFunctions) { - var startIndex = index; - - switch(typeof value) { - case 'string': - // Encode String type - buffer[index++] = BSON.BSON_DATA_STRING; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - - // Calculate size - var size = supportsBuffer ? Buffer.byteLength(value) + 1 : numberOfBytes(value) + 1; - // Write the size of the string to buffer - buffer[index + 3] = (size >> 24) & 0xff; - buffer[index + 2] = (size >> 16) & 0xff; - buffer[index + 1] = (size >> 8) & 0xff; - buffer[index] = size & 0xff; - // Ajust the index - index = index + 4; - // Write the string - supportsBuffer ? buffer.write(value, index, 'utf8') : writeToTypedArray(buffer, value, index); - // Update index - index = index + size - 1; - // Write zero - buffer[index++] = 0; - // Return index - return index; - case 'number': - // We have an integer value - if(Math.floor(value) === value && value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) { - // If the value fits in 32 bits encode as int, if it fits in a double - // encode it as a double, otherwise long - if(value >= BSON.BSON_INT32_MIN && value <= BSON.BSON_INT32_MAX) { - // Set int type 32 bits or less - buffer[index++] = BSON.BSON_DATA_INT; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - // Write the int value - buffer[index++] = value & 0xff; - buffer[index++] = (value >> 8) & 0xff; - buffer[index++] = (value >> 16) & 0xff; - buffer[index++] = (value >> 24) & 0xff; - } else if(value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) { - // Encode as double - buffer[index++] = BSON.BSON_DATA_NUMBER; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - // Write float - writeIEEE754(buffer, value, index, 'little', 52, 8); - // Ajust index - index = index + 8; - } else { - // Set long type - buffer[index++] = BSON.BSON_DATA_LONG; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - var longVal = Long.fromNumber(value); - var lowBits = longVal.getLowBits(); - var highBits = longVal.getHighBits(); - // Encode low bits - buffer[index++] = lowBits & 0xff; - buffer[index++] = (lowBits >> 8) & 0xff; - buffer[index++] = (lowBits >> 16) & 0xff; - buffer[index++] = (lowBits >> 24) & 0xff; - // Encode high bits - buffer[index++] = highBits & 0xff; - buffer[index++] = (highBits >> 8) & 0xff; - buffer[index++] = (highBits >> 16) & 0xff; - buffer[index++] = (highBits >> 24) & 0xff; - } - } else { - // Encode as double - buffer[index++] = BSON.BSON_DATA_NUMBER; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - // Write float - writeIEEE754(buffer, value, index, 'little', 52, 8); - // Ajust index - index = index + 8; - } - - return index; - case 'undefined': - // Set long type - buffer[index++] = BSON.BSON_DATA_NULL; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - return index; - case 'boolean': - // Write the type - buffer[index++] = BSON.BSON_DATA_BOOLEAN; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - // Encode the boolean value - buffer[index++] = value ? 1 : 0; - return index; - case 'object': - if(value === null || value instanceof MinKey || value instanceof MaxKey - || value['_bsontype'] == 'MinKey' || value['_bsontype'] == 'MaxKey') { - // Write the type of either min or max key - if(value === null) { - buffer[index++] = BSON.BSON_DATA_NULL; - } else if(value instanceof MinKey) { - buffer[index++] = BSON.BSON_DATA_MIN_KEY; - } else { - buffer[index++] = BSON.BSON_DATA_MAX_KEY; - } - - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - return index; - } else if(value instanceof ObjectID || value['_bsontype'] == 'ObjectID') { - // Write the type - buffer[index++] = BSON.BSON_DATA_OID; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - - // Write objectid - supportsBuffer ? buffer.write(value.id, index, 'binary') : writeToTypedArray(buffer, value.id, index); - // Ajust index - index = index + 12; - return index; - } else if(value instanceof Date || isDate(value)) { - // Write the type - buffer[index++] = BSON.BSON_DATA_DATE; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - - // Write the date - var dateInMilis = Long.fromNumber(value.getTime()); - var lowBits = dateInMilis.getLowBits(); - var highBits = dateInMilis.getHighBits(); - // Encode low bits - buffer[index++] = lowBits & 0xff; - buffer[index++] = (lowBits >> 8) & 0xff; - buffer[index++] = (lowBits >> 16) & 0xff; - buffer[index++] = (lowBits >> 24) & 0xff; - // Encode high bits - buffer[index++] = highBits & 0xff; - buffer[index++] = (highBits >> 8) & 0xff; - buffer[index++] = (highBits >> 16) & 0xff; - buffer[index++] = (highBits >> 24) & 0xff; - return index; - } else if(typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) { - // Write the type - buffer[index++] = BSON.BSON_DATA_BINARY; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - // Get size of the buffer (current write point) - var size = value.length; - // Write the size of the string to buffer - buffer[index++] = size & 0xff; - buffer[index++] = (size >> 8) & 0xff; - buffer[index++] = (size >> 16) & 0xff; - buffer[index++] = (size >> 24) & 0xff; - // Write the default subtype - buffer[index++] = BSON.BSON_BINARY_SUBTYPE_DEFAULT; - // Copy the content form the binary field to the buffer - value.copy(buffer, index, 0, size); - // Adjust the index - index = index + size; - return index; - } else if(value instanceof Long || value instanceof Timestamp || value['_bsontype'] == 'Long' || value['_bsontype'] == 'Timestamp') { - // Write the type - buffer[index++] = value instanceof Long ? BSON.BSON_DATA_LONG : BSON.BSON_DATA_TIMESTAMP; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - // Write the date - var lowBits = value.getLowBits(); - var highBits = value.getHighBits(); - // Encode low bits - buffer[index++] = lowBits & 0xff; - buffer[index++] = (lowBits >> 8) & 0xff; - buffer[index++] = (lowBits >> 16) & 0xff; - buffer[index++] = (lowBits >> 24) & 0xff; - // Encode high bits - buffer[index++] = highBits & 0xff; - buffer[index++] = (highBits >> 8) & 0xff; - buffer[index++] = (highBits >> 16) & 0xff; - buffer[index++] = (highBits >> 24) & 0xff; - return index; - } else if(value instanceof Double || value['_bsontype'] == 'Double') { - // Encode as double - buffer[index++] = BSON.BSON_DATA_NUMBER; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - // Write float - writeIEEE754(buffer, value, index, 'little', 52, 8); - // Ajust index - index = index + 8; - return index; - } else if(value instanceof Code || value['_bsontype'] == 'Code') { - if(value.scope != null && Object.keys(value.scope).length > 0) { - // Write the type - buffer[index++] = BSON.BSON_DATA_CODE_W_SCOPE; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - // Calculate the scope size - var scopeSize = BSON.calculateObjectSize(value.scope, serializeFunctions); - // Function string - var functionString = value.code.toString(); - // Function Size - var codeSize = supportsBuffer ? Buffer.byteLength(functionString) + 1 : numberOfBytes(functionString) + 1; - - // Calculate full size of the object - var totalSize = 4 + codeSize + scopeSize + 4; - - // Write the total size of the object - buffer[index++] = totalSize & 0xff; - buffer[index++] = (totalSize >> 8) & 0xff; - buffer[index++] = (totalSize >> 16) & 0xff; - buffer[index++] = (totalSize >> 24) & 0xff; - - // Write the size of the string to buffer - buffer[index++] = codeSize & 0xff; - buffer[index++] = (codeSize >> 8) & 0xff; - buffer[index++] = (codeSize >> 16) & 0xff; - buffer[index++] = (codeSize >> 24) & 0xff; - - // Write the string - supportsBuffer ? buffer.write(functionString, index, 'utf8') : writeToTypedArray(buffer, functionString, index); - // Update index - index = index + codeSize - 1; - // Write zero - buffer[index++] = 0; - // Serialize the scope object - var scopeObjectBuffer = supportsBuffer ? new Buffer(scopeSize) : new Uint8Array(new ArrayBuffer(scopeSize)); - // Execute the serialization into a seperate buffer - serializeObject(value.scope, checkKeys, scopeObjectBuffer, 0, serializeFunctions); - - // Adjusted scope Size (removing the header) - var scopeDocSize = scopeSize; - // Write scope object size - buffer[index++] = scopeDocSize & 0xff; - buffer[index++] = (scopeDocSize >> 8) & 0xff; - buffer[index++] = (scopeDocSize >> 16) & 0xff; - buffer[index++] = (scopeDocSize >> 24) & 0xff; - - // Write the scopeObject into the buffer - supportsBuffer ? scopeObjectBuffer.copy(buffer, index, 0, scopeSize) : buffer.set(scopeObjectBuffer, index); - // Adjust index, removing the empty size of the doc (5 bytes 0000000005) - index = index + scopeDocSize - 5; - // Write trailing zero - buffer[index++] = 0; - return index - } else { - buffer[index++] = BSON.BSON_DATA_CODE; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - // Function string - var functionString = value.code.toString(); - // Function Size - var size = supportsBuffer ? Buffer.byteLength(functionString) + 1 : numberOfBytes(functionString) + 1; - // Write the size of the string to buffer - buffer[index++] = size & 0xff; - buffer[index++] = (size >> 8) & 0xff; - buffer[index++] = (size >> 16) & 0xff; - buffer[index++] = (size >> 24) & 0xff; - // Write the string - supportsBuffer ? buffer.write(functionString, index, 'utf8') : writeToTypedArray(buffer, functionString, index); - // Update index - index = index + size - 1; - // Write zero - buffer[index++] = 0; - return index; - } - } else if(value instanceof Binary || value['_bsontype'] == 'Binary') { - // Write the type - buffer[index++] = BSON.BSON_DATA_BINARY; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - // Extract the buffer - var data = value.value(true); - // Calculate size - var size = value.position; - // Write the size of the string to buffer - buffer[index++] = size & 0xff; - buffer[index++] = (size >> 8) & 0xff; - buffer[index++] = (size >> 16) & 0xff; - buffer[index++] = (size >> 24) & 0xff; - // Write the subtype to the buffer - buffer[index++] = value.sub_type; - - // If we have binary type 2 the 4 first bytes are the size - if(value.sub_type == Binary.SUBTYPE_BYTE_ARRAY) { - buffer[index++] = size & 0xff; - buffer[index++] = (size >> 8) & 0xff; - buffer[index++] = (size >> 16) & 0xff; - buffer[index++] = (size >> 24) & 0xff; - } - - // Write the data to the object - supportsBuffer ? data.copy(buffer, index, 0, value.position) : buffer.set(data, index); - // Ajust index - index = index + value.position; - return index; - } else if(value instanceof Symbol || value['_bsontype'] == 'Symbol') { - // Write the type - buffer[index++] = BSON.BSON_DATA_SYMBOL; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - // Calculate size - var size = supportsBuffer ? Buffer.byteLength(value.value) + 1 : numberOfBytes(value.value) + 1; - // Write the size of the string to buffer - buffer[index++] = size & 0xff; - buffer[index++] = (size >> 8) & 0xff; - buffer[index++] = (size >> 16) & 0xff; - buffer[index++] = (size >> 24) & 0xff; - // Write the string - buffer.write(value.value, index, 'utf8'); - // Update index - index = index + size - 1; - // Write zero - buffer[index++] = 0x00; - return index; - } else if(value instanceof DBRef || value['_bsontype'] == 'DBRef') { - // Write the type - buffer[index++] = BSON.BSON_DATA_OBJECT; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - // Set up correct object for serialization - var ordered_values = { - '$ref': value.namespace - , '$id' : value.oid - }; - - // Add db reference if it exists - if(null != value.db) { - ordered_values['$db'] = value.db; - } - - // Message size - var size = BSON.calculateObjectSize(ordered_values, serializeFunctions); - // Serialize the object - var endIndex = BSON.serializeWithBufferAndIndex(ordered_values, checkKeys, buffer, index, serializeFunctions); - // Write the size of the string to buffer - buffer[index++] = size & 0xff; - buffer[index++] = (size >> 8) & 0xff; - buffer[index++] = (size >> 16) & 0xff; - buffer[index++] = (size >> 24) & 0xff; - // Write zero for object - buffer[endIndex++] = 0x00; - // Return the end index - return endIndex; - } else if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]') { - // Write the type - buffer[index++] = BSON.BSON_DATA_REGEXP; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - - // Write the regular expression string - supportsBuffer ? buffer.write(value.source, index, 'utf8') : writeToTypedArray(buffer, value.source, index); - // Adjust the index - index = index + (supportsBuffer ? Buffer.byteLength(value.source) : numberOfBytes(value.source)); - // Write zero - buffer[index++] = 0x00; - // Write the parameters - if(value.global) buffer[index++] = 0x73; // s - if(value.ignoreCase) buffer[index++] = 0x69; // i - if(value.multiline) buffer[index++] = 0x6d; // m - // Add ending zero - buffer[index++] = 0x00; - return index; - } else { - // Write the type - buffer[index++] = Array.isArray(value) ? BSON.BSON_DATA_ARRAY : BSON.BSON_DATA_OBJECT; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Adjust the index - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - var endIndex = serializeObject(value, checkKeys, buffer, index + 4, serializeFunctions); - // Write size - var size = endIndex - index; - // Write the size of the string to buffer - buffer[index++] = size & 0xff; - buffer[index++] = (size >> 8) & 0xff; - buffer[index++] = (size >> 16) & 0xff; - buffer[index++] = (size >> 24) & 0xff; - return endIndex; - } - case 'function': - // WTF for 0.4.X where typeof /someregexp/ === 'function' - if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]' || String.call(value) == '[object RegExp]') { - // Write the type - buffer[index++] = BSON.BSON_DATA_REGEXP; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - - // Write the regular expression string - buffer.write(value.source, index, 'utf8'); - // Adjust the index - index = index + (supportsBuffer ? Buffer.byteLength(value.source) : numberOfBytes(value.source)); - // Write zero - buffer[index++] = 0x00; - // Write the parameters - if(value.global) buffer[index++] = 0x73; // s - if(value.ignoreCase) buffer[index++] = 0x69; // i - if(value.multiline) buffer[index++] = 0x6d; // m - // Add ending zero - buffer[index++] = 0x00; - return index; - } else { - if(serializeFunctions && value.scope != null && Object.keys(value.scope).length > 0) { - // Write the type - buffer[index++] = BSON.BSON_DATA_CODE_W_SCOPE; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - // Calculate the scope size - var scopeSize = BSON.calculateObjectSize(value.scope, serializeFunctions); - // Function string - var functionString = value.toString(); - // Function Size - var codeSize = supportsBuffer ? Buffer.byteLength(functionString) + 1 : numberOfBytes(functionString) + 1; - - // Calculate full size of the object - var totalSize = 4 + codeSize + scopeSize; - - // Write the total size of the object - buffer[index++] = totalSize & 0xff; - buffer[index++] = (totalSize >> 8) & 0xff; - buffer[index++] = (totalSize >> 16) & 0xff; - buffer[index++] = (totalSize >> 24) & 0xff; - - // Write the size of the string to buffer - buffer[index++] = codeSize & 0xff; - buffer[index++] = (codeSize >> 8) & 0xff; - buffer[index++] = (codeSize >> 16) & 0xff; - buffer[index++] = (codeSize >> 24) & 0xff; - - // Write the string - supportsBuffer ? buffer.write(functionString, index, 'utf8') : writeToTypedArray(buffer, functionString, index); - // Update index - index = index + codeSize - 1; - // Write zero - buffer[index++] = 0; - // Serialize the scope object - var scopeObjectBuffer = new Buffer(scopeSize); - // Execute the serialization into a seperate buffer - serializeObject(value.scope, checkKeys, scopeObjectBuffer, 0, serializeFunctions); - - // Adjusted scope Size (removing the header) - var scopeDocSize = scopeSize - 4; - // Write scope object size - buffer[index++] = scopeDocSize & 0xff; - buffer[index++] = (scopeDocSize >> 8) & 0xff; - buffer[index++] = (scopeDocSize >> 16) & 0xff; - buffer[index++] = (scopeDocSize >> 24) & 0xff; - - // Write the scopeObject into the buffer - scopeObjectBuffer.copy(buffer, index, 0, scopeSize); - - // Adjust index, removing the empty size of the doc (5 bytes 0000000005) - index = index + scopeDocSize - 5; - // Write trailing zero - buffer[index++] = 0; - return index - } else if(serializeFunctions) { - buffer[index++] = BSON.BSON_DATA_CODE; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - // Function string - var functionString = value.toString(); - // Function Size - var size = supportsBuffer ? Buffer.byteLength(functionString) + 1 : numberOfBytes(functionString) + 1; - // Write the size of the string to buffer - buffer[index++] = size & 0xff; - buffer[index++] = (size >> 8) & 0xff; - buffer[index++] = (size >> 16) & 0xff; - buffer[index++] = (size >> 24) & 0xff; - // Write the string - supportsBuffer ? buffer.write(functionString, index, 'utf8') : writeToTypedArray(buffer, functionString, index); - // Update index - index = index + size - 1; - // Write zero - buffer[index++] = 0; - return index; - } - } - } - - // If no value to serialize - return index; -} - -/** - * Serialize a Javascript object. - * - * @param {Object} object the Javascript object to serialize. - * @param {Boolean} checkKeys the serializer will check if keys are valid. - * @param {Boolean} asBuffer return the serialized object as a Buffer object **(ignore)**. - * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**. - * @return {Buffer} returns the Buffer object containing the serialized object. - * @api public - */ -BSON.serialize = function(object, checkKeys, asBuffer, serializeFunctions) { - // Throw error if we are trying serialize an illegal type - if(object == null || typeof object != 'object' || Array.isArray(object)) - throw new Error("Only javascript objects supported"); - - // Emoty target buffer - var buffer = null; - // Calculate the size of the object - var size = BSON.calculateObjectSize(object, serializeFunctions); - // Fetch the best available type for storing the binary data - if(buffer = typeof Buffer != 'undefined') { - buffer = new Buffer(size); - asBuffer = true; - } else if(typeof Uint8Array != 'undefined') { - buffer = new Uint8Array(new ArrayBuffer(size)); - } else { - buffer = new Array(size); - } - - // If asBuffer is false use typed arrays - BSON.serializeWithBufferAndIndex(object, checkKeys, buffer, 0, serializeFunctions); - return buffer; -} - -/** - * Contains the function cache if we have that enable to allow for avoiding the eval step on each deserialization, comparison is by md5 - * - * @ignore - * @api private - */ -var functionCache = BSON.functionCache = {}; - -/** - * Crc state variables shared by function - * - * @ignore - * @api private - */ -var table = [0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D]; - -/** - * CRC32 hash method, Fast and enough versitility for our usage - * - * @ignore - * @api private - */ -var crc32 = function(string, start, end) { - var crc = 0 - var x = 0; - var y = 0; - crc = crc ^ (-1); - - for(var i = start, iTop = end; i < iTop;i++) { - y = (crc ^ string[i]) & 0xFF; - x = table[y]; - crc = (crc >>> 8) ^ x; - } - - return crc ^ (-1); -} - -/** - * Deserialize stream data as BSON documents. - * - * Options - * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized. - * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse. - * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function. - * - **promoteLongs** {Boolean, default:true}, when deserializing a Long will fit it into a Number if it's smaller than 53 bits - * - * @param {Buffer} data the buffer containing the serialized set of BSON documents. - * @param {Number} startIndex the start index in the data Buffer where the deserialization is to start. - * @param {Number} numberOfDocuments number of documents to deserialize. - * @param {Array} documents an array where to store the deserialized documents. - * @param {Number} docStartIndex the index in the documents array from where to start inserting documents. - * @param {Object} [options] additional options used for the deserialization. - * @return {Number} returns the next index in the buffer after deserialization **x** numbers of documents. - * @api public - */ -BSON.deserializeStream = function(data, startIndex, numberOfDocuments, documents, docStartIndex, options) { - // if(numberOfDocuments !== documents.length) throw new Error("Number of expected results back is less than the number of documents"); - options = options != null ? options : {}; - var index = startIndex; - // Loop over all documents - for(var i = 0; i < numberOfDocuments; i++) { - // Find size of the document - var size = data[index] | data[index + 1] << 8 | data[index + 2] << 16 | data[index + 3] << 24; - // Update options with index - options['index'] = index; - // Parse the document at this point - documents[docStartIndex + i] = BSON.deserialize(data, options); - // Adjust index by the document size - index = index + size; - } - - // Return object containing end index of parsing and list of documents - return index; -} - -/** - * Ensure eval is isolated. - * - * @ignore - * @api private - */ -var isolateEvalWithHash = function(functionCache, hash, functionString, object) { - // Contains the value we are going to set - var value = null; - - // Check for cache hit, eval if missing and return cached function - if(functionCache[hash] == null) { - eval("value = " + functionString); - functionCache[hash] = value; - } - // Set the object - return functionCache[hash].bind(object); -} - -/** - * Ensure eval is isolated. - * - * @ignore - * @api private - */ -var isolateEval = function(functionString) { - // Contains the value we are going to set - var value = null; - // Eval the function - eval("value = " + functionString); - return value; -} - -/** - * Convert Uint8Array to String - * - * @ignore - * @api private - */ -var convertUint8ArrayToUtf8String = function(byteArray, startIndex, endIndex) { - return BinaryParser.decode_utf8(convertArraytoUtf8BinaryString(byteArray, startIndex, endIndex)); -} - -var convertArraytoUtf8BinaryString = function(byteArray, startIndex, endIndex) { - var result = ""; - for(var i = startIndex; i < endIndex; i++) { - result = result + String.fromCharCode(byteArray[i]); - } - - return result; -}; - -/** - * Deserialize data as BSON. - * - * Options - * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized. - * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse. - * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function. - * - **promoteLongs** {Boolean, default:true}, when deserializing a Long will fit it into a Number if it's smaller than 53 bits - * - * @param {Buffer} buffer the buffer containing the serialized set of BSON documents. - * @param {Object} [options] additional options used for the deserialization. - * @param {Boolean} [isArray] ignore used for recursive parsing. - * @return {Object} returns the deserialized Javascript Object. - * @api public - */ -BSON.deserialize = function(buffer, options, isArray) { - // Options - options = options == null ? {} : options; - var evalFunctions = options['evalFunctions'] == null ? false : options['evalFunctions']; - var cacheFunctions = options['cacheFunctions'] == null ? false : options['cacheFunctions']; - var cacheFunctionsCrc32 = options['cacheFunctionsCrc32'] == null ? false : options['cacheFunctionsCrc32']; - var promoteLongs = options['promoteLongs'] || true; - - // Validate that we have at least 4 bytes of buffer - if(buffer.length < 5) throw new Error("corrupt bson message < 5 bytes long"); - - // Set up index - var index = typeof options['index'] == 'number' ? options['index'] : 0; - // Reads in a C style string - var readCStyleString = function() { - // Get the start search index - var i = index; - // Locate the end of the c string - while(buffer[i] !== 0x00) { i++ } - // Grab utf8 encoded string - var string = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('utf8', index, i) : convertUint8ArrayToUtf8String(buffer, index, i); - // Update index position - index = i + 1; - // Return string - return string; - } - - // Create holding object - var object = isArray ? [] : {}; - - // Read the document size - var size = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; - - // Ensure buffer is valid size - if(size < 5 || size > buffer.length) throw new Error("corrupt bson message"); - - // While we have more left data left keep parsing - while(true) { - // Read the type - var elementType = buffer[index++]; - // If we get a zero it's the last byte, exit - if(elementType == 0) break; - // Read the name of the field - var name = readCStyleString(); - // Switch on the type - switch(elementType) { - case BSON.BSON_DATA_OID: - var string = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('binary', index, index + 12) : convertArraytoUtf8BinaryString(buffer, index, index + 12); - // Decode the oid - object[name] = new ObjectID(string); - // Update index - index = index + 12; - break; - case BSON.BSON_DATA_STRING: - // Read the content of the field - var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; - // Add string to object - object[name] = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('utf8', index, index + stringSize - 1) : convertUint8ArrayToUtf8String(buffer, index, index + stringSize - 1); - // Update parse index position - index = index + stringSize; - break; - case BSON.BSON_DATA_INT: - // Decode the 32bit value - object[name] = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; - break; - case BSON.BSON_DATA_NUMBER: - // Decode the double value - object[name] = readIEEE754(buffer, index, 'little', 52, 8); - // Update the index - index = index + 8; - break; - case BSON.BSON_DATA_DATE: - // Unpack the low and high bits - var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; - var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; - // Set date object - object[name] = new Date(new Long(lowBits, highBits).toNumber()); - break; - case BSON.BSON_DATA_BOOLEAN: - // Parse the boolean value - object[name] = buffer[index++] == 1; - break; - case BSON.BSON_DATA_NULL: - // Parse the boolean value - object[name] = null; - break; - case BSON.BSON_DATA_BINARY: - // Decode the size of the binary blob - var binarySize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; - // Decode the subtype - var subType = buffer[index++]; - // Decode as raw Buffer object if options specifies it - if(buffer['slice'] != null) { - // If we have subtype 2 skip the 4 bytes for the size - if(subType == Binary.SUBTYPE_BYTE_ARRAY) { - binarySize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; - } - // Slice the data - object[name] = new Binary(buffer.slice(index, index + binarySize), subType); - } else { - var _buffer = typeof Uint8Array != 'undefined' ? new Uint8Array(new ArrayBuffer(binarySize)) : new Array(binarySize); - // If we have subtype 2 skip the 4 bytes for the size - if(subType == Binary.SUBTYPE_BYTE_ARRAY) { - binarySize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; - } - // Copy the data - for(var i = 0; i < binarySize; i++) { - _buffer[i] = buffer[index + i]; - } - // Create the binary object - object[name] = new Binary(_buffer, subType); - } - // Update the index - index = index + binarySize; - break; - case BSON.BSON_DATA_ARRAY: - options['index'] = index; - // Decode the size of the array document - var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24; - // Set the array to the object - object[name] = BSON.deserialize(buffer, options, true); - // Adjust the index - index = index + objectSize; - break; - case BSON.BSON_DATA_OBJECT: - options['index'] = index; - // Decode the size of the object document - var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24; - // Set the array to the object - object[name] = BSON.deserialize(buffer, options, false); - // Adjust the index - index = index + objectSize; - break; - case BSON.BSON_DATA_REGEXP: - // Create the regexp - var source = readCStyleString(); - var regExpOptions = readCStyleString(); - // For each option add the corresponding one for javascript - var optionsArray = new Array(regExpOptions.length); - - // Parse options - for(var i = 0; i < regExpOptions.length; i++) { - switch(regExpOptions[i]) { - case 'm': - optionsArray[i] = 'm'; - break; - case 's': - optionsArray[i] = 'g'; - break; - case 'i': - optionsArray[i] = 'i'; - break; - } - } - - object[name] = new RegExp(source, optionsArray.join('')); - break; - case BSON.BSON_DATA_LONG: - // Unpack the low and high bits - var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; - var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; - // Create long object - var long = new Long(lowBits, highBits); - // Promote the long if possible - if(promoteLongs) { - object[name] = long.lessThanOrEqual(JS_INT_MAX_LONG) && long.greaterThanOrEqual(JS_INT_MIN_LONG) ? long.toNumber() : long; - } else { - object[name] = long; - } - break; - case BSON.BSON_DATA_SYMBOL: - // Read the content of the field - var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; - // Add string to object - object[name] = new Symbol(buffer.toString('utf8', index, index + stringSize - 1)); - // Update parse index position - index = index + stringSize; - break; - case BSON.BSON_DATA_TIMESTAMP: - // Unpack the low and high bits - var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; - var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; - // Set the object - object[name] = new Timestamp(lowBits, highBits); - break; - case BSON.BSON_DATA_MIN_KEY: - // Parse the object - object[name] = new MinKey(); - break; - case BSON.BSON_DATA_MAX_KEY: - // Parse the object - object[name] = new MaxKey(); - break; - case BSON.BSON_DATA_CODE: - // Read the content of the field - var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; - // Function string - var functionString = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('utf8', index, index + stringSize - 1) : convertUint8ArrayToUtf8String(buffer, index, index + stringSize - 1); - - // If we are evaluating the functions - if(evalFunctions) { - // Contains the value we are going to set - var value = null; - // If we have cache enabled let's look for the md5 of the function in the cache - if(cacheFunctions) { - var hash = cacheFunctionsCrc32 ? crc32(functionString) : functionString; - // Got to do this to avoid V8 deoptimizing the call due to finding eval - object[name] = isolateEvalWithHash(functionCache, hash, functionString, object); - } else { - // Set directly - object[name] = isolateEval(functionString); - } - } else { - object[name] = new Code(functionString, {}); - } - - // Update parse index position - index = index + stringSize; - break; - case BSON.BSON_DATA_CODE_W_SCOPE: - // Read the content of the field - var totalSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; - var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; - // Javascript function - var functionString = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('utf8', index, index + stringSize - 1) : convertUint8ArrayToUtf8String(buffer, index, index + stringSize - 1); - // Update parse index position - index = index + stringSize; - // Parse the element - options['index'] = index; - // Decode the size of the object document - var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24; - // Decode the scope object - var scopeObject = BSON.deserialize(buffer, options, false); - // Adjust the index - index = index + objectSize; - - // If we are evaluating the functions - if(evalFunctions) { - // Contains the value we are going to set - var value = null; - // If we have cache enabled let's look for the md5 of the function in the cache - if(cacheFunctions) { - var hash = cacheFunctionsCrc32 ? crc32(functionString) : functionString; - // Got to do this to avoid V8 deoptimizing the call due to finding eval - object[name] = isolateEvalWithHash(functionCache, hash, functionString, object); - } else { - // Set directly - object[name] = isolateEval(functionString); - } - - // Set the scope on the object - object[name].scope = scopeObject; - } else { - object[name] = new Code(functionString, scopeObject); - } - - // Add string to object - break; - } - } - - // Check if we have a db ref object - if(object['$id'] != null) object = new DBRef(object['$ref'], object['$id'], object['$db']); - - // Return the final objects - return object; -} - -/** - * Check if key name is valid. - * - * @ignore - * @api private - */ -BSON.checkKey = function checkKey (key, dollarsAndDotsOk) { - if (!key.length) return; - // Check if we have a legal key for the object - if (!!~key.indexOf("\x00")) { - // The BSON spec doesn't allow keys with null bytes because keys are - // null-terminated. - throw Error("key " + key + " must not contain null bytes"); - } - if (!dollarsAndDotsOk) { - if('$' == key[0]) { - throw Error("key " + key + " must not start with '$'"); - } else if (!!~key.indexOf('.')) { - throw Error("key " + key + " must not contain '.'"); - } - } -}; - -/** - * Deserialize data as BSON. - * - * Options - * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized. - * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse. - * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function. - * - * @param {Buffer} buffer the buffer containing the serialized set of BSON documents. - * @param {Object} [options] additional options used for the deserialization. - * @param {Boolean} [isArray] ignore used for recursive parsing. - * @return {Object} returns the deserialized Javascript Object. - * @api public - */ -BSON.prototype.deserialize = function(data, options) { - return BSON.deserialize(data, options); -} - -/** - * Deserialize stream data as BSON documents. - * - * Options - * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized. - * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse. - * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function. - * - * @param {Buffer} data the buffer containing the serialized set of BSON documents. - * @param {Number} startIndex the start index in the data Buffer where the deserialization is to start. - * @param {Number} numberOfDocuments number of documents to deserialize. - * @param {Array} documents an array where to store the deserialized documents. - * @param {Number} docStartIndex the index in the documents array from where to start inserting documents. - * @param {Object} [options] additional options used for the deserialization. - * @return {Number} returns the next index in the buffer after deserialization **x** numbers of documents. - * @api public - */ -BSON.prototype.deserializeStream = function(data, startIndex, numberOfDocuments, documents, docStartIndex, options) { - return BSON.deserializeStream(data, startIndex, numberOfDocuments, documents, docStartIndex, options); -} - -/** - * Serialize a Javascript object. - * - * @param {Object} object the Javascript object to serialize. - * @param {Boolean} checkKeys the serializer will check if keys are valid. - * @param {Boolean} asBuffer return the serialized object as a Buffer object **(ignore)**. - * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**. - * @return {Buffer} returns the Buffer object containing the serialized object. - * @api public - */ -BSON.prototype.serialize = function(object, checkKeys, asBuffer, serializeFunctions) { - return BSON.serialize(object, checkKeys, asBuffer, serializeFunctions); -} - -/** - * Calculate the bson size for a passed in Javascript object. - * - * @param {Object} object the Javascript object to calculate the BSON byte size for. - * @param {Boolean} [serializeFunctions] serialize all functions in the object **(default:false)**. - * @return {Number} returns the number of bytes the BSON object will take up. - * @api public - */ -BSON.prototype.calculateObjectSize = function(object, serializeFunctions) { - return BSON.calculateObjectSize(object, serializeFunctions); -} - -/** - * Serialize a Javascript object using a predefined Buffer and index into the buffer, useful when pre-allocating the space for serialization. - * - * @param {Object} object the Javascript object to serialize. - * @param {Boolean} checkKeys the serializer will check if keys are valid. - * @param {Buffer} buffer the Buffer you pre-allocated to store the serialized BSON object. - * @param {Number} index the index in the buffer where we wish to start serializing into. - * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**. - * @return {Number} returns the new write index in the Buffer. - * @api public - */ -BSON.prototype.serializeWithBufferAndIndex = function(object, checkKeys, buffer, startIndex, serializeFunctions) { - return BSON.serializeWithBufferAndIndex(object, checkKeys, buffer, startIndex, serializeFunctions); -} - -/** - * @ignore - * @api private - */ -exports.Code = Code; -exports.Symbol = Symbol; -exports.BSON = BSON; -exports.DBRef = DBRef; -exports.Binary = Binary; -exports.ObjectID = ObjectID; -exports.Long = Long; -exports.Timestamp = Timestamp; -exports.Double = Double; -exports.MinKey = MinKey; -exports.MaxKey = MaxKey; - -}, - - - -'code': function(module, exports, global, require, undefined){ - /** - * A class representation of the BSON Code type. - * - * @class Represents the BSON Code type. - * @param {String|Function} code a string or function. - * @param {Object} [scope] an optional scope for the function. - * @return {Code} - */ -function Code(code, scope) { - if(!(this instanceof Code)) return new Code(code, scope); - - this._bsontype = 'Code'; - this.code = code; - this.scope = scope == null ? {} : scope; -}; - -/** - * @ignore - * @api private - */ -Code.prototype.toJSON = function() { - return {scope:this.scope, code:this.code}; -} - -exports.Code = Code; -}, - - - -'db_ref': function(module, exports, global, require, undefined){ - /** - * A class representation of the BSON DBRef type. - * - * @class Represents the BSON DBRef type. - * @param {String} namespace the collection name. - * @param {ObjectID} oid the reference ObjectID. - * @param {String} [db] optional db name, if omitted the reference is local to the current db. - * @return {DBRef} - */ -function DBRef(namespace, oid, db) { - if(!(this instanceof DBRef)) return new DBRef(namespace, oid, db); - - this._bsontype = 'DBRef'; - this.namespace = namespace; - this.oid = oid; - this.db = db; -}; - -/** - * @ignore - * @api private - */ -DBRef.prototype.toJSON = function() { - return { - '$ref':this.namespace, - '$id':this.oid, - '$db':this.db == null ? '' : this.db - }; -} - -exports.DBRef = DBRef; -}, - - - -'double': function(module, exports, global, require, undefined){ - /** - * A class representation of the BSON Double type. - * - * @class Represents the BSON Double type. - * @param {Number} value the number we want to represent as a double. - * @return {Double} - */ -function Double(value) { - if(!(this instanceof Double)) return new Double(value); - - this._bsontype = 'Double'; - this.value = value; -} - -/** - * Access the number value. - * - * @return {Number} returns the wrapped double number. - * @api public - */ -Double.prototype.valueOf = function() { - return this.value; -}; - -/** - * @ignore - * @api private - */ -Double.prototype.toJSON = function() { - return this.value; -} - -exports.Double = Double; -}, - - - -'float_parser': function(module, exports, global, require, undefined){ - // Copyright (c) 2008, Fair Oaks Labs, Inc. -// All rights reserved. -// -// 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. -// -// * Neither the name of Fair Oaks Labs, Inc. nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 OWNER OR CONTRIBUTORS 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. -// -// -// Modifications to writeIEEE754 to support negative zeroes made by Brian White - -var readIEEE754 = function(buffer, offset, endian, mLen, nBytes) { - var e, m, - bBE = (endian === 'big'), - eLen = nBytes * 8 - mLen - 1, - eMax = (1 << eLen) - 1, - eBias = eMax >> 1, - nBits = -7, - i = bBE ? 0 : (nBytes - 1), - d = bBE ? 1 : -1, - s = buffer[offset + i]; - - i += d; - - e = s & ((1 << (-nBits)) - 1); - s >>= (-nBits); - nBits += eLen; - for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8); - - m = e & ((1 << (-nBits)) - 1); - e >>= (-nBits); - nBits += mLen; - for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8); - - if (e === 0) { - e = 1 - eBias; - } else if (e === eMax) { - return m ? NaN : ((s ? -1 : 1) * Infinity); - } else { - m = m + Math.pow(2, mLen); - e = e - eBias; - } - return (s ? -1 : 1) * m * Math.pow(2, e - mLen); -}; - -var writeIEEE754 = function(buffer, value, offset, endian, mLen, nBytes) { - var e, m, c, - bBE = (endian === 'big'), - eLen = nBytes * 8 - mLen - 1, - eMax = (1 << eLen) - 1, - eBias = eMax >> 1, - rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0), - i = bBE ? (nBytes-1) : 0, - d = bBE ? -1 : 1, - s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0; - - value = Math.abs(value); - - if (isNaN(value) || value === Infinity) { - m = isNaN(value) ? 1 : 0; - e = eMax; - } else { - e = Math.floor(Math.log(value) / Math.LN2); - if (value * (c = Math.pow(2, -e)) < 1) { - e--; - c *= 2; - } - if (e+eBias >= 1) { - value += rt / c; - } else { - value += rt * Math.pow(2, 1 - eBias); - } - if (value * c >= 2) { - e++; - c /= 2; - } - - if (e + eBias >= eMax) { - m = 0; - e = eMax; - } else if (e + eBias >= 1) { - m = (value * c - 1) * Math.pow(2, mLen); - e = e + eBias; - } else { - m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen); - e = 0; - } - } - - for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8); - - e = (e << mLen) | m; - eLen += mLen; - for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8); - - buffer[offset + i - d] |= s * 128; -}; - -exports.readIEEE754 = readIEEE754; -exports.writeIEEE754 = writeIEEE754; -}, - - - -'index': function(module, exports, global, require, undefined){ - try { - exports.BSONPure = require('./bson'); - exports.BSONNative = require('../../ext'); -} catch(err) { - // do nothing -} - -[ './binary_parser' - , './binary' - , './code' - , './db_ref' - , './double' - , './max_key' - , './min_key' - , './objectid' - , './symbol' - , './timestamp' - , './long'].forEach(function (path) { - var module = require('./' + path); - for (var i in module) { - exports[i] = module[i]; - } -}); - -// Exports all the classes for the NATIVE JS BSON Parser -exports.native = function() { - var classes = {}; - // Map all the classes - [ './binary_parser' - , './binary' - , './code' - , './db_ref' - , './double' - , './max_key' - , './min_key' - , './objectid' - , './symbol' - , './timestamp' - , './long' - , '../../ext' -].forEach(function (path) { - var module = require('./' + path); - for (var i in module) { - classes[i] = module[i]; - } - }); - // Return classes list - return classes; -} - -// Exports all the classes for the PURE JS BSON Parser -exports.pure = function() { - var classes = {}; - // Map all the classes - [ './binary_parser' - , './binary' - , './code' - , './db_ref' - , './double' - , './max_key' - , './min_key' - , './objectid' - , './symbol' - , './timestamp' - , './long' - , '././bson'].forEach(function (path) { - var module = require('./' + path); - for (var i in module) { - classes[i] = module[i]; - } - }); - // Return classes list - return classes; -} - -}, - - - -'long': function(module, exports, global, require, undefined){ - // Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Copyright 2009 Google Inc. All Rights Reserved - -/** - * Defines a Long class for representing a 64-bit two's-complement - * integer value, which faithfully simulates the behavior of a Java "Long". This - * implementation is derived from LongLib in GWT. - * - * Constructs a 64-bit two's-complement integer, given its low and high 32-bit - * values as *signed* integers. See the from* functions below for more - * convenient ways of constructing Longs. - * - * The internal representation of a Long is the two given signed, 32-bit values. - * We use 32-bit pieces because these are the size of integers on which - * Javascript performs bit-operations. For operations like addition and - * multiplication, we split each number into 16-bit pieces, which can easily be - * multiplied within Javascript's floating-point representation without overflow - * or change in sign. - * - * In the algorithms below, we frequently reduce the negative case to the - * positive case by negating the input(s) and then post-processing the result. - * Note that we must ALWAYS check specially whether those values are MIN_VALUE - * (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as - * a positive number, it overflows back into a negative). Not handling this - * case would often result in infinite recursion. - * - * @class Represents the BSON Long type. - * @param {Number} low the low (signed) 32 bits of the Long. - * @param {Number} high the high (signed) 32 bits of the Long. - */ -function Long(low, high) { - if(!(this instanceof Long)) return new Long(low, high); - - this._bsontype = 'Long'; - /** - * @type {number} - * @api private - */ - this.low_ = low | 0; // force into 32 signed bits. - - /** - * @type {number} - * @api private - */ - this.high_ = high | 0; // force into 32 signed bits. -}; - -/** - * Return the int value. - * - * @return {Number} the value, assuming it is a 32-bit integer. - * @api public - */ -Long.prototype.toInt = function() { - return this.low_; -}; - -/** - * Return the Number value. - * - * @return {Number} the closest floating-point representation to this value. - * @api public - */ -Long.prototype.toNumber = function() { - return this.high_ * Long.TWO_PWR_32_DBL_ + - this.getLowBitsUnsigned(); -}; - -/** - * Return the JSON value. - * - * @return {String} the JSON representation. - * @api public - */ -Long.prototype.toJSON = function() { - return this.toString(); -} - -/** - * Return the String value. - * - * @param {Number} [opt_radix] the radix in which the text should be written. - * @return {String} the textual representation of this value. - * @api public - */ -Long.prototype.toString = function(opt_radix) { - var radix = opt_radix || 10; - if (radix < 2 || 36 < radix) { - throw Error('radix out of range: ' + radix); - } - - if (this.isZero()) { - return '0'; - } - - if (this.isNegative()) { - if (this.equals(Long.MIN_VALUE)) { - // We need to change the Long value before it can be negated, so we remove - // the bottom-most digit in this base and then recurse to do the rest. - var radixLong = Long.fromNumber(radix); - var div = this.div(radixLong); - var rem = div.multiply(radixLong).subtract(this); - return div.toString(radix) + rem.toInt().toString(radix); - } else { - return '-' + this.negate().toString(radix); - } - } - - // Do several (6) digits each time through the loop, so as to - // minimize the calls to the very expensive emulated div. - var radixToPower = Long.fromNumber(Math.pow(radix, 6)); - - var rem = this; - var result = ''; - while (true) { - var remDiv = rem.div(radixToPower); - var intval = rem.subtract(remDiv.multiply(radixToPower)).toInt(); - var digits = intval.toString(radix); - - rem = remDiv; - if (rem.isZero()) { - return digits + result; - } else { - while (digits.length < 6) { - digits = '0' + digits; - } - result = '' + digits + result; - } - } -}; - -/** - * Return the high 32-bits value. - * - * @return {Number} the high 32-bits as a signed value. - * @api public - */ -Long.prototype.getHighBits = function() { - return this.high_; -}; - -/** - * Return the low 32-bits value. - * - * @return {Number} the low 32-bits as a signed value. - * @api public - */ -Long.prototype.getLowBits = function() { - return this.low_; -}; - -/** - * Return the low unsigned 32-bits value. - * - * @return {Number} the low 32-bits as an unsigned value. - * @api public - */ -Long.prototype.getLowBitsUnsigned = function() { - return (this.low_ >= 0) ? - this.low_ : Long.TWO_PWR_32_DBL_ + this.low_; -}; - -/** - * Returns the number of bits needed to represent the absolute value of this Long. - * - * @return {Number} Returns the number of bits needed to represent the absolute value of this Long. - * @api public - */ -Long.prototype.getNumBitsAbs = function() { - if (this.isNegative()) { - if (this.equals(Long.MIN_VALUE)) { - return 64; - } else { - return this.negate().getNumBitsAbs(); - } - } else { - var val = this.high_ != 0 ? this.high_ : this.low_; - for (var bit = 31; bit > 0; bit--) { - if ((val & (1 << bit)) != 0) { - break; - } - } - return this.high_ != 0 ? bit + 33 : bit + 1; - } -}; - -/** - * Return whether this value is zero. - * - * @return {Boolean} whether this value is zero. - * @api public - */ -Long.prototype.isZero = function() { - return this.high_ == 0 && this.low_ == 0; -}; - -/** - * Return whether this value is negative. - * - * @return {Boolean} whether this value is negative. - * @api public - */ -Long.prototype.isNegative = function() { - return this.high_ < 0; -}; - -/** - * Return whether this value is odd. - * - * @return {Boolean} whether this value is odd. - * @api public - */ -Long.prototype.isOdd = function() { - return (this.low_ & 1) == 1; -}; - -/** - * Return whether this Long equals the other - * - * @param {Long} other Long to compare against. - * @return {Boolean} whether this Long equals the other - * @api public - */ -Long.prototype.equals = function(other) { - return (this.high_ == other.high_) && (this.low_ == other.low_); -}; - -/** - * Return whether this Long does not equal the other. - * - * @param {Long} other Long to compare against. - * @return {Boolean} whether this Long does not equal the other. - * @api public - */ -Long.prototype.notEquals = function(other) { - return (this.high_ != other.high_) || (this.low_ != other.low_); -}; - -/** - * Return whether this Long is less than the other. - * - * @param {Long} other Long to compare against. - * @return {Boolean} whether this Long is less than the other. - * @api public - */ -Long.prototype.lessThan = function(other) { - return this.compare(other) < 0; -}; - -/** - * Return whether this Long is less than or equal to the other. - * - * @param {Long} other Long to compare against. - * @return {Boolean} whether this Long is less than or equal to the other. - * @api public - */ -Long.prototype.lessThanOrEqual = function(other) { - return this.compare(other) <= 0; -}; - -/** - * Return whether this Long is greater than the other. - * - * @param {Long} other Long to compare against. - * @return {Boolean} whether this Long is greater than the other. - * @api public - */ -Long.prototype.greaterThan = function(other) { - return this.compare(other) > 0; -}; - -/** - * Return whether this Long is greater than or equal to the other. - * - * @param {Long} other Long to compare against. - * @return {Boolean} whether this Long is greater than or equal to the other. - * @api public - */ -Long.prototype.greaterThanOrEqual = function(other) { - return this.compare(other) >= 0; -}; - -/** - * Compares this Long with the given one. - * - * @param {Long} other Long to compare against. - * @return {Boolean} 0 if they are the same, 1 if the this is greater, and -1 if the given one is greater. - * @api public - */ -Long.prototype.compare = function(other) { - if (this.equals(other)) { - return 0; - } - - var thisNeg = this.isNegative(); - var otherNeg = other.isNegative(); - if (thisNeg && !otherNeg) { - return -1; - } - if (!thisNeg && otherNeg) { - return 1; - } - - // at this point, the signs are the same, so subtraction will not overflow - if (this.subtract(other).isNegative()) { - return -1; - } else { - return 1; - } -}; - -/** - * The negation of this value. - * - * @return {Long} the negation of this value. - * @api public - */ -Long.prototype.negate = function() { - if (this.equals(Long.MIN_VALUE)) { - return Long.MIN_VALUE; - } else { - return this.not().add(Long.ONE); - } -}; - -/** - * Returns the sum of this and the given Long. - * - * @param {Long} other Long to add to this one. - * @return {Long} the sum of this and the given Long. - * @api public - */ -Long.prototype.add = function(other) { - // Divide each number into 4 chunks of 16 bits, and then sum the chunks. - - var a48 = this.high_ >>> 16; - var a32 = this.high_ & 0xFFFF; - var a16 = this.low_ >>> 16; - var a00 = this.low_ & 0xFFFF; - - var b48 = other.high_ >>> 16; - var b32 = other.high_ & 0xFFFF; - var b16 = other.low_ >>> 16; - var b00 = other.low_ & 0xFFFF; - - var c48 = 0, c32 = 0, c16 = 0, c00 = 0; - c00 += a00 + b00; - c16 += c00 >>> 16; - c00 &= 0xFFFF; - c16 += a16 + b16; - c32 += c16 >>> 16; - c16 &= 0xFFFF; - c32 += a32 + b32; - c48 += c32 >>> 16; - c32 &= 0xFFFF; - c48 += a48 + b48; - c48 &= 0xFFFF; - return Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32); -}; - -/** - * Returns the difference of this and the given Long. - * - * @param {Long} other Long to subtract from this. - * @return {Long} the difference of this and the given Long. - * @api public - */ -Long.prototype.subtract = function(other) { - return this.add(other.negate()); -}; - -/** - * Returns the product of this and the given Long. - * - * @param {Long} other Long to multiply with this. - * @return {Long} the product of this and the other. - * @api public - */ -Long.prototype.multiply = function(other) { - if (this.isZero()) { - return Long.ZERO; - } else if (other.isZero()) { - return Long.ZERO; - } - - if (this.equals(Long.MIN_VALUE)) { - return other.isOdd() ? Long.MIN_VALUE : Long.ZERO; - } else if (other.equals(Long.MIN_VALUE)) { - return this.isOdd() ? Long.MIN_VALUE : Long.ZERO; - } - - if (this.isNegative()) { - if (other.isNegative()) { - return this.negate().multiply(other.negate()); - } else { - return this.negate().multiply(other).negate(); - } - } else if (other.isNegative()) { - return this.multiply(other.negate()).negate(); - } - - // If both Longs are small, use float multiplication - if (this.lessThan(Long.TWO_PWR_24_) && - other.lessThan(Long.TWO_PWR_24_)) { - return Long.fromNumber(this.toNumber() * other.toNumber()); - } - - // Divide each Long into 4 chunks of 16 bits, and then add up 4x4 products. - // We can skip products that would overflow. - - var a48 = this.high_ >>> 16; - var a32 = this.high_ & 0xFFFF; - var a16 = this.low_ >>> 16; - var a00 = this.low_ & 0xFFFF; - - var b48 = other.high_ >>> 16; - var b32 = other.high_ & 0xFFFF; - var b16 = other.low_ >>> 16; - var b00 = other.low_ & 0xFFFF; - - var c48 = 0, c32 = 0, c16 = 0, c00 = 0; - c00 += a00 * b00; - c16 += c00 >>> 16; - c00 &= 0xFFFF; - c16 += a16 * b00; - c32 += c16 >>> 16; - c16 &= 0xFFFF; - c16 += a00 * b16; - c32 += c16 >>> 16; - c16 &= 0xFFFF; - c32 += a32 * b00; - c48 += c32 >>> 16; - c32 &= 0xFFFF; - c32 += a16 * b16; - c48 += c32 >>> 16; - c32 &= 0xFFFF; - c32 += a00 * b32; - c48 += c32 >>> 16; - c32 &= 0xFFFF; - c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48; - c48 &= 0xFFFF; - return Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32); -}; - -/** - * Returns this Long divided by the given one. - * - * @param {Long} other Long by which to divide. - * @return {Long} this Long divided by the given one. - * @api public - */ -Long.prototype.div = function(other) { - if (other.isZero()) { - throw Error('division by zero'); - } else if (this.isZero()) { - return Long.ZERO; - } - - if (this.equals(Long.MIN_VALUE)) { - if (other.equals(Long.ONE) || - other.equals(Long.NEG_ONE)) { - return Long.MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE - } else if (other.equals(Long.MIN_VALUE)) { - return Long.ONE; - } else { - // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|. - var halfThis = this.shiftRight(1); - var approx = halfThis.div(other).shiftLeft(1); - if (approx.equals(Long.ZERO)) { - return other.isNegative() ? Long.ONE : Long.NEG_ONE; - } else { - var rem = this.subtract(other.multiply(approx)); - var result = approx.add(rem.div(other)); - return result; - } - } - } else if (other.equals(Long.MIN_VALUE)) { - return Long.ZERO; - } - - if (this.isNegative()) { - if (other.isNegative()) { - return this.negate().div(other.negate()); - } else { - return this.negate().div(other).negate(); - } - } else if (other.isNegative()) { - return this.div(other.negate()).negate(); - } - - // Repeat the following until the remainder is less than other: find a - // floating-point that approximates remainder / other *from below*, add this - // into the result, and subtract it from the remainder. It is critical that - // the approximate value is less than or equal to the real value so that the - // remainder never becomes negative. - var res = Long.ZERO; - var rem = this; - while (rem.greaterThanOrEqual(other)) { - // Approximate the result of division. This may be a little greater or - // smaller than the actual value. - var approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber())); - - // We will tweak the approximate result by changing it in the 48-th digit or - // the smallest non-fractional digit, whichever is larger. - var log2 = Math.ceil(Math.log(approx) / Math.LN2); - var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48); - - // Decrease the approximation until it is smaller than the remainder. Note - // that if it is too large, the product overflows and is negative. - var approxRes = Long.fromNumber(approx); - var approxRem = approxRes.multiply(other); - while (approxRem.isNegative() || approxRem.greaterThan(rem)) { - approx -= delta; - approxRes = Long.fromNumber(approx); - approxRem = approxRes.multiply(other); - } - - // We know the answer can't be zero... and actually, zero would cause - // infinite recursion since we would make no progress. - if (approxRes.isZero()) { - approxRes = Long.ONE; - } - - res = res.add(approxRes); - rem = rem.subtract(approxRem); - } - return res; -}; - -/** - * Returns this Long modulo the given one. - * - * @param {Long} other Long by which to mod. - * @return {Long} this Long modulo the given one. - * @api public - */ -Long.prototype.modulo = function(other) { - return this.subtract(this.div(other).multiply(other)); -}; - -/** - * The bitwise-NOT of this value. - * - * @return {Long} the bitwise-NOT of this value. - * @api public - */ -Long.prototype.not = function() { - return Long.fromBits(~this.low_, ~this.high_); -}; - -/** - * Returns the bitwise-AND of this Long and the given one. - * - * @param {Long} other the Long with which to AND. - * @return {Long} the bitwise-AND of this and the other. - * @api public - */ -Long.prototype.and = function(other) { - return Long.fromBits(this.low_ & other.low_, this.high_ & other.high_); -}; - -/** - * Returns the bitwise-OR of this Long and the given one. - * - * @param {Long} other the Long with which to OR. - * @return {Long} the bitwise-OR of this and the other. - * @api public - */ -Long.prototype.or = function(other) { - return Long.fromBits(this.low_ | other.low_, this.high_ | other.high_); -}; - -/** - * Returns the bitwise-XOR of this Long and the given one. - * - * @param {Long} other the Long with which to XOR. - * @return {Long} the bitwise-XOR of this and the other. - * @api public - */ -Long.prototype.xor = function(other) { - return Long.fromBits(this.low_ ^ other.low_, this.high_ ^ other.high_); -}; - -/** - * Returns this Long with bits shifted to the left by the given amount. - * - * @param {Number} numBits the number of bits by which to shift. - * @return {Long} this shifted to the left by the given amount. - * @api public - */ -Long.prototype.shiftLeft = function(numBits) { - numBits &= 63; - if (numBits == 0) { - return this; - } else { - var low = this.low_; - if (numBits < 32) { - var high = this.high_; - return Long.fromBits( - low << numBits, - (high << numBits) | (low >>> (32 - numBits))); - } else { - return Long.fromBits(0, low << (numBits - 32)); - } - } -}; - -/** - * Returns this Long with bits shifted to the right by the given amount. - * - * @param {Number} numBits the number of bits by which to shift. - * @return {Long} this shifted to the right by the given amount. - * @api public - */ -Long.prototype.shiftRight = function(numBits) { - numBits &= 63; - if (numBits == 0) { - return this; - } else { - var high = this.high_; - if (numBits < 32) { - var low = this.low_; - return Long.fromBits( - (low >>> numBits) | (high << (32 - numBits)), - high >> numBits); - } else { - return Long.fromBits( - high >> (numBits - 32), - high >= 0 ? 0 : -1); - } - } -}; - -/** - * Returns this Long with bits shifted to the right by the given amount, with the new top bits matching the current sign bit. - * - * @param {Number} numBits the number of bits by which to shift. - * @return {Long} this shifted to the right by the given amount, with zeros placed into the new leading bits. - * @api public - */ -Long.prototype.shiftRightUnsigned = function(numBits) { - numBits &= 63; - if (numBits == 0) { - return this; - } else { - var high = this.high_; - if (numBits < 32) { - var low = this.low_; - return Long.fromBits( - (low >>> numBits) | (high << (32 - numBits)), - high >>> numBits); - } else if (numBits == 32) { - return Long.fromBits(high, 0); - } else { - return Long.fromBits(high >>> (numBits - 32), 0); - } - } -}; - -/** - * Returns a Long representing the given (32-bit) integer value. - * - * @param {Number} value the 32-bit integer in question. - * @return {Long} the corresponding Long value. - * @api public - */ -Long.fromInt = function(value) { - if (-128 <= value && value < 128) { - var cachedObj = Long.INT_CACHE_[value]; - if (cachedObj) { - return cachedObj; - } - } - - var obj = new Long(value | 0, value < 0 ? -1 : 0); - if (-128 <= value && value < 128) { - Long.INT_CACHE_[value] = obj; - } - return obj; -}; - -/** - * Returns a Long representing the given value, provided that it is a finite number. Otherwise, zero is returned. - * - * @param {Number} value the number in question. - * @return {Long} the corresponding Long value. - * @api public - */ -Long.fromNumber = function(value) { - if (isNaN(value) || !isFinite(value)) { - return Long.ZERO; - } else if (value <= -Long.TWO_PWR_63_DBL_) { - return Long.MIN_VALUE; - } else if (value + 1 >= Long.TWO_PWR_63_DBL_) { - return Long.MAX_VALUE; - } else if (value < 0) { - return Long.fromNumber(-value).negate(); - } else { - return new Long( - (value % Long.TWO_PWR_32_DBL_) | 0, - (value / Long.TWO_PWR_32_DBL_) | 0); - } -}; - -/** - * Returns a Long representing the 64-bit integer that comes by concatenating the given high and low bits. Each is assumed to use 32 bits. - * - * @param {Number} lowBits the low 32-bits. - * @param {Number} highBits the high 32-bits. - * @return {Long} the corresponding Long value. - * @api public - */ -Long.fromBits = function(lowBits, highBits) { - return new Long(lowBits, highBits); -}; - -/** - * Returns a Long representation of the given string, written using the given radix. - * - * @param {String} str the textual representation of the Long. - * @param {Number} opt_radix the radix in which the text is written. - * @return {Long} the corresponding Long value. - * @api public - */ -Long.fromString = function(str, opt_radix) { - if (str.length == 0) { - throw Error('number format error: empty string'); - } - - var radix = opt_radix || 10; - if (radix < 2 || 36 < radix) { - throw Error('radix out of range: ' + radix); - } - - if (str.charAt(0) == '-') { - return Long.fromString(str.substring(1), radix).negate(); - } else if (str.indexOf('-') >= 0) { - throw Error('number format error: interior "-" character: ' + str); - } - - // Do several (8) digits each time through the loop, so as to - // minimize the calls to the very expensive emulated div. - var radixToPower = Long.fromNumber(Math.pow(radix, 8)); - - var result = Long.ZERO; - for (var i = 0; i < str.length; i += 8) { - var size = Math.min(8, str.length - i); - var value = parseInt(str.substring(i, i + size), radix); - if (size < 8) { - var power = Long.fromNumber(Math.pow(radix, size)); - result = result.multiply(power).add(Long.fromNumber(value)); - } else { - result = result.multiply(radixToPower); - result = result.add(Long.fromNumber(value)); - } - } - return result; -}; - -// NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the -// from* methods on which they depend. - - -/** - * A cache of the Long representations of small integer values. - * @type {Object} - * @api private - */ -Long.INT_CACHE_ = {}; - -// NOTE: the compiler should inline these constant values below and then remove -// these variables, so there should be no runtime penalty for these. - -/** - * Number used repeated below in calculations. This must appear before the - * first call to any from* function below. - * @type {number} - * @api private - */ -Long.TWO_PWR_16_DBL_ = 1 << 16; - -/** - * @type {number} - * @api private - */ -Long.TWO_PWR_24_DBL_ = 1 << 24; - -/** - * @type {number} - * @api private - */ -Long.TWO_PWR_32_DBL_ = Long.TWO_PWR_16_DBL_ * Long.TWO_PWR_16_DBL_; - -/** - * @type {number} - * @api private - */ -Long.TWO_PWR_31_DBL_ = Long.TWO_PWR_32_DBL_ / 2; - -/** - * @type {number} - * @api private - */ -Long.TWO_PWR_48_DBL_ = Long.TWO_PWR_32_DBL_ * Long.TWO_PWR_16_DBL_; - -/** - * @type {number} - * @api private - */ -Long.TWO_PWR_64_DBL_ = Long.TWO_PWR_32_DBL_ * Long.TWO_PWR_32_DBL_; - -/** - * @type {number} - * @api private - */ -Long.TWO_PWR_63_DBL_ = Long.TWO_PWR_64_DBL_ / 2; - -/** @type {Long} */ -Long.ZERO = Long.fromInt(0); - -/** @type {Long} */ -Long.ONE = Long.fromInt(1); - -/** @type {Long} */ -Long.NEG_ONE = Long.fromInt(-1); - -/** @type {Long} */ -Long.MAX_VALUE = - Long.fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0); - -/** @type {Long} */ -Long.MIN_VALUE = Long.fromBits(0, 0x80000000 | 0); - -/** - * @type {Long} - * @api private - */ -Long.TWO_PWR_24_ = Long.fromInt(1 << 24); - -/** - * Expose. - */ -exports.Long = Long; -}, - - - -'max_key': function(module, exports, global, require, undefined){ - /** - * A class representation of the BSON MaxKey type. - * - * @class Represents the BSON MaxKey type. - * @return {MaxKey} - */ -function MaxKey() { - if(!(this instanceof MaxKey)) return new MaxKey(); - - this._bsontype = 'MaxKey'; -} - -exports.MaxKey = MaxKey; -}, - - - -'min_key': function(module, exports, global, require, undefined){ - /** - * A class representation of the BSON MinKey type. - * - * @class Represents the BSON MinKey type. - * @return {MinKey} - */ -function MinKey() { - if(!(this instanceof MinKey)) return new MinKey(); - - this._bsontype = 'MinKey'; -} - -exports.MinKey = MinKey; -}, - - - -'objectid': function(module, exports, global, require, undefined){ - /** - * Module dependencies. - */ -var BinaryParser = require('./binary_parser').BinaryParser; - -/** - * Machine id. - * - * Create a random 3-byte value (i.e. unique for this - * process). Other drivers use a md5 of the machine id here, but - * that would mean an asyc call to gethostname, so we don't bother. - */ -var MACHINE_ID = parseInt(Math.random() * 0xFFFFFF, 10); - -// Regular expression that checks for hex value -var checkForHexRegExp = new RegExp("^[0-9a-fA-F]{24}$"); - -/** -* Create a new ObjectID instance -* -* @class Represents the BSON ObjectID type -* @param {String|Number} id Can be a 24 byte hex string, 12 byte binary string or a Number. -* @return {Object} instance of ObjectID. -*/ -var ObjectID = function ObjectID(id, _hex) { - if(!(this instanceof ObjectID)) return new ObjectID(id, _hex); - - this._bsontype = 'ObjectID'; - var __id = null; - - // Throw an error if it's not a valid setup - if(id != null && 'number' != typeof id && (id.length != 12 && id.length != 24)) - throw new Error("Argument passed in must be a single String of 12 bytes or a string of 24 hex characters"); - - // Generate id based on the input - if(id == null || typeof id == 'number') { - // convert to 12 byte binary string - this.id = this.generate(id); - } else if(id != null && id.length === 12) { - // assume 12 byte string - this.id = id; - } else if(checkForHexRegExp.test(id)) { - return ObjectID.createFromHexString(id); - } else { - throw new Error("Value passed in is not a valid 24 character hex string"); - } - - if(ObjectID.cacheHexString) this.__id = this.toHexString(); -}; - -// Allow usage of ObjectId as well as ObjectID -var ObjectId = ObjectID; - -// Precomputed hex table enables speedy hex string conversion -var hexTable = []; -for (var i = 0; i < 256; i++) { - hexTable[i] = (i <= 15 ? '0' : '') + i.toString(16); -} - -/** -* Return the ObjectID id as a 24 byte hex string representation -* -* @return {String} return the 24 byte hex string representation. -* @api public -*/ -ObjectID.prototype.toHexString = function() { - if(ObjectID.cacheHexString && this.__id) return this.__id; - - var hexString = ''; - - for (var i = 0; i < this.id.length; i++) { - hexString += hexTable[this.id.charCodeAt(i)]; - } - - if(ObjectID.cacheHexString) this.__id = hexString; - return hexString; -}; - -/** -* Update the ObjectID index used in generating new ObjectID's on the driver -* -* @return {Number} returns next index value. -* @api private -*/ -ObjectID.prototype.get_inc = function() { - return ObjectID.index = (ObjectID.index + 1) % 0xFFFFFF; -}; - -/** -* Update the ObjectID index used in generating new ObjectID's on the driver -* -* @return {Number} returns next index value. -* @api private -*/ -ObjectID.prototype.getInc = function() { - return this.get_inc(); -}; - -/** -* Generate a 12 byte id string used in ObjectID's -* -* @param {Number} [time] optional parameter allowing to pass in a second based timestamp. -* @return {String} return the 12 byte id binary string. -* @api private -*/ -ObjectID.prototype.generate = function(time) { - if ('number' == typeof time) { - var time4Bytes = BinaryParser.encodeInt(time, 32, true, true); - /* for time-based ObjectID the bytes following the time will be zeroed */ - var machine3Bytes = BinaryParser.encodeInt(MACHINE_ID, 24, false); - var pid2Bytes = BinaryParser.fromShort(typeof process === 'undefined' ? Math.floor(Math.random() * 100000) : process.pid); - var index3Bytes = BinaryParser.encodeInt(this.get_inc(), 24, false, true); - } else { - var unixTime = parseInt(Date.now()/1000,10); - var time4Bytes = BinaryParser.encodeInt(unixTime, 32, true, true); - var machine3Bytes = BinaryParser.encodeInt(MACHINE_ID, 24, false); - var pid2Bytes = BinaryParser.fromShort(typeof process === 'undefined' ? Math.floor(Math.random() * 100000) : process.pid); - var index3Bytes = BinaryParser.encodeInt(this.get_inc(), 24, false, true); - } - - return time4Bytes + machine3Bytes + pid2Bytes + index3Bytes; -}; - -/** -* Converts the id into a 24 byte hex string for printing -* -* @return {String} return the 24 byte hex string representation. -* @api private -*/ -ObjectID.prototype.toString = function() { - return this.toHexString(); -}; - -/** -* Converts to a string representation of this Id. -* -* @return {String} return the 24 byte hex string representation. -* @api private -*/ -ObjectID.prototype.inspect = ObjectID.prototype.toString; - -/** -* Converts to its JSON representation. -* -* @return {String} return the 24 byte hex string representation. -* @api private -*/ -ObjectID.prototype.toJSON = function() { - return this.toHexString(); -}; - -/** -* Compares the equality of this ObjectID with `otherID`. -* -* @param {Object} otherID ObjectID instance to compare against. -* @return {Bool} the result of comparing two ObjectID's -* @api public -*/ -ObjectID.prototype.equals = function equals (otherID) { - var id = (otherID instanceof ObjectID || otherID.toHexString) - ? otherID.id - : ObjectID.createFromHexString(otherID).id; - - return this.id === id; -} - -/** -* Returns the generation date (accurate up to the second) that this ID was generated. -* -* @return {Date} the generation date -* @api public -*/ -ObjectID.prototype.getTimestamp = function() { - var timestamp = new Date(); - timestamp.setTime(Math.floor(BinaryParser.decodeInt(this.id.substring(0,4), 32, true, true)) * 1000); - return timestamp; -} - -/** -* @ignore -* @api private -*/ -ObjectID.index = parseInt(Math.random() * 0xFFFFFF, 10); - -ObjectID.createPk = function createPk () { - return new ObjectID(); -}; - -/** -* Creates an ObjectID from a second based number, with the rest of the ObjectID zeroed out. Used for comparisons or sorting the ObjectID. -* -* @param {Number} time an integer number representing a number of seconds. -* @return {ObjectID} return the created ObjectID -* @api public -*/ -ObjectID.createFromTime = function createFromTime (time) { - var id = BinaryParser.encodeInt(time, 32, true, true) + - BinaryParser.encodeInt(0, 64, true, true); - return new ObjectID(id); -}; - -/** -* Creates an ObjectID from a hex string representation of an ObjectID. -* -* @param {String} hexString create a ObjectID from a passed in 24 byte hexstring. -* @return {ObjectID} return the created ObjectID -* @api public -*/ -ObjectID.createFromHexString = function createFromHexString (hexString) { - // Throw an error if it's not a valid setup - if(typeof hexString === 'undefined' || hexString != null && hexString.length != 24) - throw new Error("Argument passed in must be a single String of 12 bytes or a string of 24 hex characters"); - - var len = hexString.length; - - if(len > 12*2) { - throw new Error('Id cannot be longer than 12 bytes'); - } - - var result = '' - , string - , number; - - for (var index = 0; index < len; index += 2) { - string = hexString.substr(index, 2); - number = parseInt(string, 16); - result += BinaryParser.fromByte(number); - } - - return new ObjectID(result, hexString); -}; - -/** -* @ignore -*/ -Object.defineProperty(ObjectID.prototype, "generationTime", { - enumerable: true - , get: function () { - return Math.floor(BinaryParser.decodeInt(this.id.substring(0,4), 32, true, true)); - } - , set: function (value) { - var value = BinaryParser.encodeInt(value, 32, true, true); - this.id = value + this.id.substr(4); - // delete this.__id; - this.toHexString(); - } -}); - -/** - * Expose. - */ -exports.ObjectID = ObjectID; -exports.ObjectId = ObjectID; - -}, - - - -'symbol': function(module, exports, global, require, undefined){ - /** - * A class representation of the BSON Symbol type. - * - * @class Represents the BSON Symbol type. - * @param {String} value the string representing the symbol. - * @return {Symbol} - */ -function Symbol(value) { - if(!(this instanceof Symbol)) return new Symbol(value); - this._bsontype = 'Symbol'; - this.value = value; -} - -/** - * Access the wrapped string value. - * - * @return {String} returns the wrapped string. - * @api public - */ -Symbol.prototype.valueOf = function() { - return this.value; -}; - -/** - * @ignore - * @api private - */ -Symbol.prototype.toString = function() { - return this.value; -} - -/** - * @ignore - * @api private - */ -Symbol.prototype.inspect = function() { - return this.value; -} - -/** - * @ignore - * @api private - */ -Symbol.prototype.toJSON = function() { - return this.value; -} - -exports.Symbol = Symbol; -}, - - - -'timestamp': function(module, exports, global, require, undefined){ - // Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Copyright 2009 Google Inc. All Rights Reserved - -/** - * Defines a Timestamp class for representing a 64-bit two's-complement - * integer value, which faithfully simulates the behavior of a Java "Timestamp". This - * implementation is derived from TimestampLib in GWT. - * - * Constructs a 64-bit two's-complement integer, given its low and high 32-bit - * values as *signed* integers. See the from* functions below for more - * convenient ways of constructing Timestamps. - * - * The internal representation of a Timestamp is the two given signed, 32-bit values. - * We use 32-bit pieces because these are the size of integers on which - * Javascript performs bit-operations. For operations like addition and - * multiplication, we split each number into 16-bit pieces, which can easily be - * multiplied within Javascript's floating-point representation without overflow - * or change in sign. - * - * In the algorithms below, we frequently reduce the negative case to the - * positive case by negating the input(s) and then post-processing the result. - * Note that we must ALWAYS check specially whether those values are MIN_VALUE - * (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as - * a positive number, it overflows back into a negative). Not handling this - * case would often result in infinite recursion. - * - * @class Represents the BSON Timestamp type. - * @param {Number} low the low (signed) 32 bits of the Timestamp. - * @param {Number} high the high (signed) 32 bits of the Timestamp. - */ -function Timestamp(low, high) { - if(!(this instanceof Timestamp)) return new Timestamp(low, high); - this._bsontype = 'Timestamp'; - /** - * @type {number} - * @api private - */ - this.low_ = low | 0; // force into 32 signed bits. - - /** - * @type {number} - * @api private - */ - this.high_ = high | 0; // force into 32 signed bits. -}; - -/** - * Return the int value. - * - * @return {Number} the value, assuming it is a 32-bit integer. - * @api public - */ -Timestamp.prototype.toInt = function() { - return this.low_; -}; - -/** - * Return the Number value. - * - * @return {Number} the closest floating-point representation to this value. - * @api public - */ -Timestamp.prototype.toNumber = function() { - return this.high_ * Timestamp.TWO_PWR_32_DBL_ + - this.getLowBitsUnsigned(); -}; - -/** - * Return the JSON value. - * - * @return {String} the JSON representation. - * @api public - */ -Timestamp.prototype.toJSON = function() { - return this.toString(); -} - -/** - * Return the String value. - * - * @param {Number} [opt_radix] the radix in which the text should be written. - * @return {String} the textual representation of this value. - * @api public - */ -Timestamp.prototype.toString = function(opt_radix) { - var radix = opt_radix || 10; - if (radix < 2 || 36 < radix) { - throw Error('radix out of range: ' + radix); - } - - if (this.isZero()) { - return '0'; - } - - if (this.isNegative()) { - if (this.equals(Timestamp.MIN_VALUE)) { - // We need to change the Timestamp value before it can be negated, so we remove - // the bottom-most digit in this base and then recurse to do the rest. - var radixTimestamp = Timestamp.fromNumber(radix); - var div = this.div(radixTimestamp); - var rem = div.multiply(radixTimestamp).subtract(this); - return div.toString(radix) + rem.toInt().toString(radix); - } else { - return '-' + this.negate().toString(radix); - } - } - - // Do several (6) digits each time through the loop, so as to - // minimize the calls to the very expensive emulated div. - var radixToPower = Timestamp.fromNumber(Math.pow(radix, 6)); - - var rem = this; - var result = ''; - while (true) { - var remDiv = rem.div(radixToPower); - var intval = rem.subtract(remDiv.multiply(radixToPower)).toInt(); - var digits = intval.toString(radix); - - rem = remDiv; - if (rem.isZero()) { - return digits + result; - } else { - while (digits.length < 6) { - digits = '0' + digits; - } - result = '' + digits + result; - } - } -}; - -/** - * Return the high 32-bits value. - * - * @return {Number} the high 32-bits as a signed value. - * @api public - */ -Timestamp.prototype.getHighBits = function() { - return this.high_; -}; - -/** - * Return the low 32-bits value. - * - * @return {Number} the low 32-bits as a signed value. - * @api public - */ -Timestamp.prototype.getLowBits = function() { - return this.low_; -}; - -/** - * Return the low unsigned 32-bits value. - * - * @return {Number} the low 32-bits as an unsigned value. - * @api public - */ -Timestamp.prototype.getLowBitsUnsigned = function() { - return (this.low_ >= 0) ? - this.low_ : Timestamp.TWO_PWR_32_DBL_ + this.low_; -}; - -/** - * Returns the number of bits needed to represent the absolute value of this Timestamp. - * - * @return {Number} Returns the number of bits needed to represent the absolute value of this Timestamp. - * @api public - */ -Timestamp.prototype.getNumBitsAbs = function() { - if (this.isNegative()) { - if (this.equals(Timestamp.MIN_VALUE)) { - return 64; - } else { - return this.negate().getNumBitsAbs(); - } - } else { - var val = this.high_ != 0 ? this.high_ : this.low_; - for (var bit = 31; bit > 0; bit--) { - if ((val & (1 << bit)) != 0) { - break; - } - } - return this.high_ != 0 ? bit + 33 : bit + 1; - } -}; - -/** - * Return whether this value is zero. - * - * @return {Boolean} whether this value is zero. - * @api public - */ -Timestamp.prototype.isZero = function() { - return this.high_ == 0 && this.low_ == 0; -}; - -/** - * Return whether this value is negative. - * - * @return {Boolean} whether this value is negative. - * @api public - */ -Timestamp.prototype.isNegative = function() { - return this.high_ < 0; -}; - -/** - * Return whether this value is odd. - * - * @return {Boolean} whether this value is odd. - * @api public - */ -Timestamp.prototype.isOdd = function() { - return (this.low_ & 1) == 1; -}; - -/** - * Return whether this Timestamp equals the other - * - * @param {Timestamp} other Timestamp to compare against. - * @return {Boolean} whether this Timestamp equals the other - * @api public - */ -Timestamp.prototype.equals = function(other) { - return (this.high_ == other.high_) && (this.low_ == other.low_); -}; - -/** - * Return whether this Timestamp does not equal the other. - * - * @param {Timestamp} other Timestamp to compare against. - * @return {Boolean} whether this Timestamp does not equal the other. - * @api public - */ -Timestamp.prototype.notEquals = function(other) { - return (this.high_ != other.high_) || (this.low_ != other.low_); -}; - -/** - * Return whether this Timestamp is less than the other. - * - * @param {Timestamp} other Timestamp to compare against. - * @return {Boolean} whether this Timestamp is less than the other. - * @api public - */ -Timestamp.prototype.lessThan = function(other) { - return this.compare(other) < 0; -}; - -/** - * Return whether this Timestamp is less than or equal to the other. - * - * @param {Timestamp} other Timestamp to compare against. - * @return {Boolean} whether this Timestamp is less than or equal to the other. - * @api public - */ -Timestamp.prototype.lessThanOrEqual = function(other) { - return this.compare(other) <= 0; -}; - -/** - * Return whether this Timestamp is greater than the other. - * - * @param {Timestamp} other Timestamp to compare against. - * @return {Boolean} whether this Timestamp is greater than the other. - * @api public - */ -Timestamp.prototype.greaterThan = function(other) { - return this.compare(other) > 0; -}; - -/** - * Return whether this Timestamp is greater than or equal to the other. - * - * @param {Timestamp} other Timestamp to compare against. - * @return {Boolean} whether this Timestamp is greater than or equal to the other. - * @api public - */ -Timestamp.prototype.greaterThanOrEqual = function(other) { - return this.compare(other) >= 0; -}; - -/** - * Compares this Timestamp with the given one. - * - * @param {Timestamp} other Timestamp to compare against. - * @return {Boolean} 0 if they are the same, 1 if the this is greater, and -1 if the given one is greater. - * @api public - */ -Timestamp.prototype.compare = function(other) { - if (this.equals(other)) { - return 0; - } - - var thisNeg = this.isNegative(); - var otherNeg = other.isNegative(); - if (thisNeg && !otherNeg) { - return -1; - } - if (!thisNeg && otherNeg) { - return 1; - } - - // at this point, the signs are the same, so subtraction will not overflow - if (this.subtract(other).isNegative()) { - return -1; - } else { - return 1; - } -}; - -/** - * The negation of this value. - * - * @return {Timestamp} the negation of this value. - * @api public - */ -Timestamp.prototype.negate = function() { - if (this.equals(Timestamp.MIN_VALUE)) { - return Timestamp.MIN_VALUE; - } else { - return this.not().add(Timestamp.ONE); - } -}; - -/** - * Returns the sum of this and the given Timestamp. - * - * @param {Timestamp} other Timestamp to add to this one. - * @return {Timestamp} the sum of this and the given Timestamp. - * @api public - */ -Timestamp.prototype.add = function(other) { - // Divide each number into 4 chunks of 16 bits, and then sum the chunks. - - var a48 = this.high_ >>> 16; - var a32 = this.high_ & 0xFFFF; - var a16 = this.low_ >>> 16; - var a00 = this.low_ & 0xFFFF; - - var b48 = other.high_ >>> 16; - var b32 = other.high_ & 0xFFFF; - var b16 = other.low_ >>> 16; - var b00 = other.low_ & 0xFFFF; - - var c48 = 0, c32 = 0, c16 = 0, c00 = 0; - c00 += a00 + b00; - c16 += c00 >>> 16; - c00 &= 0xFFFF; - c16 += a16 + b16; - c32 += c16 >>> 16; - c16 &= 0xFFFF; - c32 += a32 + b32; - c48 += c32 >>> 16; - c32 &= 0xFFFF; - c48 += a48 + b48; - c48 &= 0xFFFF; - return Timestamp.fromBits((c16 << 16) | c00, (c48 << 16) | c32); -}; - -/** - * Returns the difference of this and the given Timestamp. - * - * @param {Timestamp} other Timestamp to subtract from this. - * @return {Timestamp} the difference of this and the given Timestamp. - * @api public - */ -Timestamp.prototype.subtract = function(other) { - return this.add(other.negate()); -}; - -/** - * Returns the product of this and the given Timestamp. - * - * @param {Timestamp} other Timestamp to multiply with this. - * @return {Timestamp} the product of this and the other. - * @api public - */ -Timestamp.prototype.multiply = function(other) { - if (this.isZero()) { - return Timestamp.ZERO; - } else if (other.isZero()) { - return Timestamp.ZERO; - } - - if (this.equals(Timestamp.MIN_VALUE)) { - return other.isOdd() ? Timestamp.MIN_VALUE : Timestamp.ZERO; - } else if (other.equals(Timestamp.MIN_VALUE)) { - return this.isOdd() ? Timestamp.MIN_VALUE : Timestamp.ZERO; - } - - if (this.isNegative()) { - if (other.isNegative()) { - return this.negate().multiply(other.negate()); - } else { - return this.negate().multiply(other).negate(); - } - } else if (other.isNegative()) { - return this.multiply(other.negate()).negate(); - } - - // If both Timestamps are small, use float multiplication - if (this.lessThan(Timestamp.TWO_PWR_24_) && - other.lessThan(Timestamp.TWO_PWR_24_)) { - return Timestamp.fromNumber(this.toNumber() * other.toNumber()); - } - - // Divide each Timestamp into 4 chunks of 16 bits, and then add up 4x4 products. - // We can skip products that would overflow. - - var a48 = this.high_ >>> 16; - var a32 = this.high_ & 0xFFFF; - var a16 = this.low_ >>> 16; - var a00 = this.low_ & 0xFFFF; - - var b48 = other.high_ >>> 16; - var b32 = other.high_ & 0xFFFF; - var b16 = other.low_ >>> 16; - var b00 = other.low_ & 0xFFFF; - - var c48 = 0, c32 = 0, c16 = 0, c00 = 0; - c00 += a00 * b00; - c16 += c00 >>> 16; - c00 &= 0xFFFF; - c16 += a16 * b00; - c32 += c16 >>> 16; - c16 &= 0xFFFF; - c16 += a00 * b16; - c32 += c16 >>> 16; - c16 &= 0xFFFF; - c32 += a32 * b00; - c48 += c32 >>> 16; - c32 &= 0xFFFF; - c32 += a16 * b16; - c48 += c32 >>> 16; - c32 &= 0xFFFF; - c32 += a00 * b32; - c48 += c32 >>> 16; - c32 &= 0xFFFF; - c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48; - c48 &= 0xFFFF; - return Timestamp.fromBits((c16 << 16) | c00, (c48 << 16) | c32); -}; - -/** - * Returns this Timestamp divided by the given one. - * - * @param {Timestamp} other Timestamp by which to divide. - * @return {Timestamp} this Timestamp divided by the given one. - * @api public - */ -Timestamp.prototype.div = function(other) { - if (other.isZero()) { - throw Error('division by zero'); - } else if (this.isZero()) { - return Timestamp.ZERO; - } - - if (this.equals(Timestamp.MIN_VALUE)) { - if (other.equals(Timestamp.ONE) || - other.equals(Timestamp.NEG_ONE)) { - return Timestamp.MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE - } else if (other.equals(Timestamp.MIN_VALUE)) { - return Timestamp.ONE; - } else { - // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|. - var halfThis = this.shiftRight(1); - var approx = halfThis.div(other).shiftLeft(1); - if (approx.equals(Timestamp.ZERO)) { - return other.isNegative() ? Timestamp.ONE : Timestamp.NEG_ONE; - } else { - var rem = this.subtract(other.multiply(approx)); - var result = approx.add(rem.div(other)); - return result; - } - } - } else if (other.equals(Timestamp.MIN_VALUE)) { - return Timestamp.ZERO; - } - - if (this.isNegative()) { - if (other.isNegative()) { - return this.negate().div(other.negate()); - } else { - return this.negate().div(other).negate(); - } - } else if (other.isNegative()) { - return this.div(other.negate()).negate(); - } - - // Repeat the following until the remainder is less than other: find a - // floating-point that approximates remainder / other *from below*, add this - // into the result, and subtract it from the remainder. It is critical that - // the approximate value is less than or equal to the real value so that the - // remainder never becomes negative. - var res = Timestamp.ZERO; - var rem = this; - while (rem.greaterThanOrEqual(other)) { - // Approximate the result of division. This may be a little greater or - // smaller than the actual value. - var approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber())); - - // We will tweak the approximate result by changing it in the 48-th digit or - // the smallest non-fractional digit, whichever is larger. - var log2 = Math.ceil(Math.log(approx) / Math.LN2); - var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48); - - // Decrease the approximation until it is smaller than the remainder. Note - // that if it is too large, the product overflows and is negative. - var approxRes = Timestamp.fromNumber(approx); - var approxRem = approxRes.multiply(other); - while (approxRem.isNegative() || approxRem.greaterThan(rem)) { - approx -= delta; - approxRes = Timestamp.fromNumber(approx); - approxRem = approxRes.multiply(other); - } - - // We know the answer can't be zero... and actually, zero would cause - // infinite recursion since we would make no progress. - if (approxRes.isZero()) { - approxRes = Timestamp.ONE; - } - - res = res.add(approxRes); - rem = rem.subtract(approxRem); - } - return res; -}; - -/** - * Returns this Timestamp modulo the given one. - * - * @param {Timestamp} other Timestamp by which to mod. - * @return {Timestamp} this Timestamp modulo the given one. - * @api public - */ -Timestamp.prototype.modulo = function(other) { - return this.subtract(this.div(other).multiply(other)); -}; - -/** - * The bitwise-NOT of this value. - * - * @return {Timestamp} the bitwise-NOT of this value. - * @api public - */ -Timestamp.prototype.not = function() { - return Timestamp.fromBits(~this.low_, ~this.high_); -}; - -/** - * Returns the bitwise-AND of this Timestamp and the given one. - * - * @param {Timestamp} other the Timestamp with which to AND. - * @return {Timestamp} the bitwise-AND of this and the other. - * @api public - */ -Timestamp.prototype.and = function(other) { - return Timestamp.fromBits(this.low_ & other.low_, this.high_ & other.high_); -}; - -/** - * Returns the bitwise-OR of this Timestamp and the given one. - * - * @param {Timestamp} other the Timestamp with which to OR. - * @return {Timestamp} the bitwise-OR of this and the other. - * @api public - */ -Timestamp.prototype.or = function(other) { - return Timestamp.fromBits(this.low_ | other.low_, this.high_ | other.high_); -}; - -/** - * Returns the bitwise-XOR of this Timestamp and the given one. - * - * @param {Timestamp} other the Timestamp with which to XOR. - * @return {Timestamp} the bitwise-XOR of this and the other. - * @api public - */ -Timestamp.prototype.xor = function(other) { - return Timestamp.fromBits(this.low_ ^ other.low_, this.high_ ^ other.high_); -}; - -/** - * Returns this Timestamp with bits shifted to the left by the given amount. - * - * @param {Number} numBits the number of bits by which to shift. - * @return {Timestamp} this shifted to the left by the given amount. - * @api public - */ -Timestamp.prototype.shiftLeft = function(numBits) { - numBits &= 63; - if (numBits == 0) { - return this; - } else { - var low = this.low_; - if (numBits < 32) { - var high = this.high_; - return Timestamp.fromBits( - low << numBits, - (high << numBits) | (low >>> (32 - numBits))); - } else { - return Timestamp.fromBits(0, low << (numBits - 32)); - } - } -}; - -/** - * Returns this Timestamp with bits shifted to the right by the given amount. - * - * @param {Number} numBits the number of bits by which to shift. - * @return {Timestamp} this shifted to the right by the given amount. - * @api public - */ -Timestamp.prototype.shiftRight = function(numBits) { - numBits &= 63; - if (numBits == 0) { - return this; - } else { - var high = this.high_; - if (numBits < 32) { - var low = this.low_; - return Timestamp.fromBits( - (low >>> numBits) | (high << (32 - numBits)), - high >> numBits); - } else { - return Timestamp.fromBits( - high >> (numBits - 32), - high >= 0 ? 0 : -1); - } - } -}; - -/** - * Returns this Timestamp with bits shifted to the right by the given amount, with the new top bits matching the current sign bit. - * - * @param {Number} numBits the number of bits by which to shift. - * @return {Timestamp} this shifted to the right by the given amount, with zeros placed into the new leading bits. - * @api public - */ -Timestamp.prototype.shiftRightUnsigned = function(numBits) { - numBits &= 63; - if (numBits == 0) { - return this; - } else { - var high = this.high_; - if (numBits < 32) { - var low = this.low_; - return Timestamp.fromBits( - (low >>> numBits) | (high << (32 - numBits)), - high >>> numBits); - } else if (numBits == 32) { - return Timestamp.fromBits(high, 0); - } else { - return Timestamp.fromBits(high >>> (numBits - 32), 0); - } - } -}; - -/** - * Returns a Timestamp representing the given (32-bit) integer value. - * - * @param {Number} value the 32-bit integer in question. - * @return {Timestamp} the corresponding Timestamp value. - * @api public - */ -Timestamp.fromInt = function(value) { - if (-128 <= value && value < 128) { - var cachedObj = Timestamp.INT_CACHE_[value]; - if (cachedObj) { - return cachedObj; - } - } - - var obj = new Timestamp(value | 0, value < 0 ? -1 : 0); - if (-128 <= value && value < 128) { - Timestamp.INT_CACHE_[value] = obj; - } - return obj; -}; - -/** - * Returns a Timestamp representing the given value, provided that it is a finite number. Otherwise, zero is returned. - * - * @param {Number} value the number in question. - * @return {Timestamp} the corresponding Timestamp value. - * @api public - */ -Timestamp.fromNumber = function(value) { - if (isNaN(value) || !isFinite(value)) { - return Timestamp.ZERO; - } else if (value <= -Timestamp.TWO_PWR_63_DBL_) { - return Timestamp.MIN_VALUE; - } else if (value + 1 >= Timestamp.TWO_PWR_63_DBL_) { - return Timestamp.MAX_VALUE; - } else if (value < 0) { - return Timestamp.fromNumber(-value).negate(); - } else { - return new Timestamp( - (value % Timestamp.TWO_PWR_32_DBL_) | 0, - (value / Timestamp.TWO_PWR_32_DBL_) | 0); - } -}; - -/** - * Returns a Timestamp representing the 64-bit integer that comes by concatenating the given high and low bits. Each is assumed to use 32 bits. - * - * @param {Number} lowBits the low 32-bits. - * @param {Number} highBits the high 32-bits. - * @return {Timestamp} the corresponding Timestamp value. - * @api public - */ -Timestamp.fromBits = function(lowBits, highBits) { - return new Timestamp(lowBits, highBits); -}; - -/** - * Returns a Timestamp representation of the given string, written using the given radix. - * - * @param {String} str the textual representation of the Timestamp. - * @param {Number} opt_radix the radix in which the text is written. - * @return {Timestamp} the corresponding Timestamp value. - * @api public - */ -Timestamp.fromString = function(str, opt_radix) { - if (str.length == 0) { - throw Error('number format error: empty string'); - } - - var radix = opt_radix || 10; - if (radix < 2 || 36 < radix) { - throw Error('radix out of range: ' + radix); - } - - if (str.charAt(0) == '-') { - return Timestamp.fromString(str.substring(1), radix).negate(); - } else if (str.indexOf('-') >= 0) { - throw Error('number format error: interior "-" character: ' + str); - } - - // Do several (8) digits each time through the loop, so as to - // minimize the calls to the very expensive emulated div. - var radixToPower = Timestamp.fromNumber(Math.pow(radix, 8)); - - var result = Timestamp.ZERO; - for (var i = 0; i < str.length; i += 8) { - var size = Math.min(8, str.length - i); - var value = parseInt(str.substring(i, i + size), radix); - if (size < 8) { - var power = Timestamp.fromNumber(Math.pow(radix, size)); - result = result.multiply(power).add(Timestamp.fromNumber(value)); - } else { - result = result.multiply(radixToPower); - result = result.add(Timestamp.fromNumber(value)); - } - } - return result; -}; - -// NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the -// from* methods on which they depend. - - -/** - * A cache of the Timestamp representations of small integer values. - * @type {Object} - * @api private - */ -Timestamp.INT_CACHE_ = {}; - -// NOTE: the compiler should inline these constant values below and then remove -// these variables, so there should be no runtime penalty for these. - -/** - * Number used repeated below in calculations. This must appear before the - * first call to any from* function below. - * @type {number} - * @api private - */ -Timestamp.TWO_PWR_16_DBL_ = 1 << 16; - -/** - * @type {number} - * @api private - */ -Timestamp.TWO_PWR_24_DBL_ = 1 << 24; - -/** - * @type {number} - * @api private - */ -Timestamp.TWO_PWR_32_DBL_ = Timestamp.TWO_PWR_16_DBL_ * Timestamp.TWO_PWR_16_DBL_; - -/** - * @type {number} - * @api private - */ -Timestamp.TWO_PWR_31_DBL_ = Timestamp.TWO_PWR_32_DBL_ / 2; - -/** - * @type {number} - * @api private - */ -Timestamp.TWO_PWR_48_DBL_ = Timestamp.TWO_PWR_32_DBL_ * Timestamp.TWO_PWR_16_DBL_; - -/** - * @type {number} - * @api private - */ -Timestamp.TWO_PWR_64_DBL_ = Timestamp.TWO_PWR_32_DBL_ * Timestamp.TWO_PWR_32_DBL_; - -/** - * @type {number} - * @api private - */ -Timestamp.TWO_PWR_63_DBL_ = Timestamp.TWO_PWR_64_DBL_ / 2; - -/** @type {Timestamp} */ -Timestamp.ZERO = Timestamp.fromInt(0); - -/** @type {Timestamp} */ -Timestamp.ONE = Timestamp.fromInt(1); - -/** @type {Timestamp} */ -Timestamp.NEG_ONE = Timestamp.fromInt(-1); - -/** @type {Timestamp} */ -Timestamp.MAX_VALUE = - Timestamp.fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0); - -/** @type {Timestamp} */ -Timestamp.MIN_VALUE = Timestamp.fromBits(0, 0x80000000 | 0); - -/** - * @type {Timestamp} - * @api private - */ -Timestamp.TWO_PWR_24_ = Timestamp.fromInt(1 << 24); - -/** - * Expose. - */ -exports.Timestamp = Timestamp; -}, - - }); - - -if(typeof module != 'undefined' && module.exports ){ - module.exports = bson; - - if( !module.parent ){ - bson(); - } -} - -if(typeof window != 'undefined' && typeof require == 'undefined'){ - window.require = bson.require; -} diff --git a/node_modules/mongodb/node_modules/bson/browser_build/package.json b/node_modules/mongodb/node_modules/bson/browser_build/package.json deleted file mode 100644 index 3ebb587..0000000 --- a/node_modules/mongodb/node_modules/bson/browser_build/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ "name" : "bson" -, "description" : "A bson parser for node.js and the browser" -, "main": "../lib/bson/bson" -, "directories" : { "lib" : "../lib/bson" } -, "engines" : { "node" : ">=0.6.0" } -, "licenses" : [ { "type" : "Apache License, Version 2.0" - , "url" : "http://www.apache.org/licenses/LICENSE-2.0" } ] -} diff --git a/node_modules/mongodb/node_modules/bson/build/Makefile b/node_modules/mongodb/node_modules/bson/build/Makefile deleted file mode 100644 index a580dc4..0000000 --- a/node_modules/mongodb/node_modules/bson/build/Makefile +++ /dev/null @@ -1,350 +0,0 @@ -# We borrow heavily from the kernel build setup, though we are simpler since -# we don't have Kconfig tweaking settings on us. - -# The implicit make rules have it looking for RCS files, among other things. -# We instead explicitly write all the rules we care about. -# It's even quicker (saves ~200ms) to pass -r on the command line. -MAKEFLAGS=-r - -# The source directory tree. -srcdir := .. -abs_srcdir := $(abspath $(srcdir)) - -# The name of the builddir. -builddir_name ?= . - -# The V=1 flag on command line makes us verbosely print command lines. -ifdef V - quiet= -else - quiet=quiet_ -endif - -# Specify BUILDTYPE=Release on the command line for a release build. -BUILDTYPE ?= Release - -# Directory all our build output goes into. -# Note that this must be two directories beneath src/ for unit tests to pass, -# as they reach into the src/ directory for data with relative paths. -builddir ?= $(builddir_name)/$(BUILDTYPE) -abs_builddir := $(abspath $(builddir)) -depsdir := $(builddir)/.deps - -# Object output directory. -obj := $(builddir)/obj -abs_obj := $(abspath $(obj)) - -# We build up a list of every single one of the targets so we can slurp in the -# generated dependency rule Makefiles in one pass. -all_deps := - - - -CC.target ?= $(CC) -CFLAGS.target ?= $(CFLAGS) -CXX.target ?= $(CXX) -CXXFLAGS.target ?= $(CXXFLAGS) -LINK.target ?= $(LINK) -LDFLAGS.target ?= $(LDFLAGS) -AR.target ?= $(AR) - -# C++ apps need to be linked with g++. -# -# Note: flock is used to seralize linking. Linking is a memory-intensive -# process so running parallel links can often lead to thrashing. To disable -# the serialization, override LINK via an envrionment variable as follows: -# -# export LINK=g++ -# -# This will allow make to invoke N linker processes as specified in -jN. -LINK ?= ./gyp-mac-tool flock $(builddir)/linker.lock $(CXX.target) - -# TODO(evan): move all cross-compilation logic to gyp-time so we don't need -# to replicate this environment fallback in make as well. -CC.host ?= gcc -CFLAGS.host ?= -CXX.host ?= g++ -CXXFLAGS.host ?= -LINK.host ?= $(CXX.host) -LDFLAGS.host ?= -AR.host ?= ar - -# Define a dir function that can handle spaces. -# http://www.gnu.org/software/make/manual/make.html#Syntax-of-Functions -# "leading spaces cannot appear in the text of the first argument as written. -# These characters can be put into the argument value by variable substitution." -empty := -space := $(empty) $(empty) - -# http://stackoverflow.com/questions/1189781/using-make-dir-or-notdir-on-a-path-with-spaces -replace_spaces = $(subst $(space),?,$1) -unreplace_spaces = $(subst ?,$(space),$1) -dirx = $(call unreplace_spaces,$(dir $(call replace_spaces,$1))) - -# Flags to make gcc output dependency info. Note that you need to be -# careful here to use the flags that ccache and distcc can understand. -# We write to a dep file on the side first and then rename at the end -# so we can't end up with a broken dep file. -depfile = $(depsdir)/$(call replace_spaces,$@).d -DEPFLAGS = -MMD -MF $(depfile).raw - -# We have to fixup the deps output in a few ways. -# (1) the file output should mention the proper .o file. -# ccache or distcc lose the path to the target, so we convert a rule of -# the form: -# foobar.o: DEP1 DEP2 -# into -# path/to/foobar.o: DEP1 DEP2 -# (2) we want missing files not to cause us to fail to build. -# We want to rewrite -# foobar.o: DEP1 DEP2 \ -# DEP3 -# to -# DEP1: -# DEP2: -# DEP3: -# so if the files are missing, they're just considered phony rules. -# We have to do some pretty insane escaping to get those backslashes -# and dollar signs past make, the shell, and sed at the same time. -# Doesn't work with spaces, but that's fine: .d files have spaces in -# their names replaced with other characters. -define fixup_dep -# The depfile may not exist if the input file didn't have any #includes. -touch $(depfile).raw -# Fixup path as in (1). -sed -e "s|^$(notdir $@)|$@|" $(depfile).raw >> $(depfile) -# Add extra rules as in (2). -# We remove slashes and replace spaces with new lines; -# remove blank lines; -# delete the first line and append a colon to the remaining lines. -sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\ - grep -v '^$$' |\ - sed -e 1d -e 's|$$|:|' \ - >> $(depfile) -rm $(depfile).raw -endef - -# Command definitions: -# - cmd_foo is the actual command to run; -# - quiet_cmd_foo is the brief-output summary of the command. - -quiet_cmd_cc = CC($(TOOLSET)) $@ -cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $< - -quiet_cmd_cxx = CXX($(TOOLSET)) $@ -cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< - -quiet_cmd_objc = CXX($(TOOLSET)) $@ -cmd_objc = $(CC.$(TOOLSET)) $(GYP_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $< - -quiet_cmd_objcxx = CXX($(TOOLSET)) $@ -cmd_objcxx = $(CXX.$(TOOLSET)) $(GYP_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $< - -# Commands for precompiled header files. -quiet_cmd_pch_c = CXX($(TOOLSET)) $@ -cmd_pch_c = $(CC.$(TOOLSET)) $(GYP_PCH_CFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< -quiet_cmd_pch_cc = CXX($(TOOLSET)) $@ -cmd_pch_cc = $(CC.$(TOOLSET)) $(GYP_PCH_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< -quiet_cmd_pch_m = CXX($(TOOLSET)) $@ -cmd_pch_m = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $< -quiet_cmd_pch_mm = CXX($(TOOLSET)) $@ -cmd_pch_mm = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $< - -# gyp-mac-tool is written next to the root Makefile by gyp. -# Use $(4) for the command, since $(2) and $(3) are used as flag by do_cmd -# already. -quiet_cmd_mac_tool = MACTOOL $(4) $< -cmd_mac_tool = ./gyp-mac-tool $(4) $< "$@" - -quiet_cmd_mac_package_framework = PACKAGE FRAMEWORK $@ -cmd_mac_package_framework = ./gyp-mac-tool package-framework "$@" $(4) - -quiet_cmd_infoplist = INFOPLIST $@ -cmd_infoplist = $(CC.$(TOOLSET)) -E -P -Wno-trigraphs -x c $(INFOPLIST_DEFINES) "$<" -o "$@" - -quiet_cmd_touch = TOUCH $@ -cmd_touch = touch $@ - -quiet_cmd_copy = COPY $@ -# send stderr to /dev/null to ignore messages when linking directories. -cmd_copy = rm -rf "$@" && cp -af "$<" "$@" - -quiet_cmd_alink = LIBTOOL-STATIC $@ -cmd_alink = rm -f $@ && ./gyp-mac-tool filter-libtool libtool $(GYP_LIBTOOLFLAGS) -static -o $@ $(filter %.o,$^) - -quiet_cmd_link = LINK($(TOOLSET)) $@ -cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS) - -quiet_cmd_solink = SOLINK($(TOOLSET)) $@ -cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS) - -quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@ -cmd_solink_module = $(LINK.$(TOOLSET)) -bundle $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS) - - -# Define an escape_quotes function to escape single quotes. -# This allows us to handle quotes properly as long as we always use -# use single quotes and escape_quotes. -escape_quotes = $(subst ','\'',$(1)) -# This comment is here just to include a ' to unconfuse syntax highlighting. -# Define an escape_vars function to escape '$' variable syntax. -# This allows us to read/write command lines with shell variables (e.g. -# $LD_LIBRARY_PATH), without triggering make substitution. -escape_vars = $(subst $$,$$$$,$(1)) -# Helper that expands to a shell command to echo a string exactly as it is in -# make. This uses printf instead of echo because printf's behaviour with respect -# to escape sequences is more portable than echo's across different shells -# (e.g., dash, bash). -exact_echo = printf '%s\n' '$(call escape_quotes,$(1))' - -# Helper to compare the command we're about to run against the command -# we logged the last time we ran the command. Produces an empty -# string (false) when the commands match. -# Tricky point: Make has no string-equality test function. -# The kernel uses the following, but it seems like it would have false -# positives, where one string reordered its arguments. -# arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \ -# $(filter-out $(cmd_$@), $(cmd_$(1)))) -# We instead substitute each for the empty string into the other, and -# say they're equal if both substitutions produce the empty string. -# .d files contain ? instead of spaces, take that into account. -command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\ - $(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1)))) - -# Helper that is non-empty when a prerequisite changes. -# Normally make does this implicitly, but we force rules to always run -# so we can check their command lines. -# $? -- new prerequisites -# $| -- order-only dependencies -prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?)) - -# Helper that executes all postbuilds until one fails. -define do_postbuilds - @E=0;\ - for p in $(POSTBUILDS); do\ - eval $$p;\ - E=$$?;\ - if [ $$E -ne 0 ]; then\ - break;\ - fi;\ - done;\ - if [ $$E -ne 0 ]; then\ - rm -rf "$@";\ - exit $$E;\ - fi -endef - -# do_cmd: run a command via the above cmd_foo names, if necessary. -# Should always run for a given target to handle command-line changes. -# Second argument, if non-zero, makes it do asm/C/C++ dependency munging. -# Third argument, if non-zero, makes it do POSTBUILDS processing. -# Note: We intentionally do NOT call dirx for depfile, since it contains ? for -# spaces already and dirx strips the ? characters. -define do_cmd -$(if $(or $(command_changed),$(prereq_changed)), - @$(call exact_echo, $($(quiet)cmd_$(1))) - @mkdir -p "$(call dirx,$@)" "$(dir $(depfile))" - $(if $(findstring flock,$(word 2,$(cmd_$1))), - @$(cmd_$(1)) - @echo " $(quiet_cmd_$(1)): Finished", - @$(cmd_$(1)) - ) - @$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile) - @$(if $(2),$(fixup_dep)) - $(if $(and $(3), $(POSTBUILDS)), - $(call do_postbuilds) - ) -) -endef - -# Declare the "all" target first so it is the default, -# even though we don't have the deps yet. -.PHONY: all -all: - -# make looks for ways to re-generate included makefiles, but in our case, we -# don't have a direct way. Explicitly telling make that it has nothing to do -# for them makes it go faster. -%.d: ; - -# Use FORCE_DO_CMD to force a target to run. Should be coupled with -# do_cmd. -.PHONY: FORCE_DO_CMD -FORCE_DO_CMD: - -TOOLSET := target -# Suffix rules, putting all outputs into $(obj). -$(obj).$(TOOLSET)/%.o: $(srcdir)/%.c FORCE_DO_CMD - @$(call do_cmd,cc,1) -$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD - @$(call do_cmd,cxx,1) -$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD - @$(call do_cmd,cxx,1) -$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cxx FORCE_DO_CMD - @$(call do_cmd,cxx,1) -$(obj).$(TOOLSET)/%.o: $(srcdir)/%.m FORCE_DO_CMD - @$(call do_cmd,objc,1) -$(obj).$(TOOLSET)/%.o: $(srcdir)/%.mm FORCE_DO_CMD - @$(call do_cmd,objcxx,1) -$(obj).$(TOOLSET)/%.o: $(srcdir)/%.S FORCE_DO_CMD - @$(call do_cmd,cc,1) -$(obj).$(TOOLSET)/%.o: $(srcdir)/%.s FORCE_DO_CMD - @$(call do_cmd,cc,1) - -# Try building from generated source, too. -$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD - @$(call do_cmd,cc,1) -$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD - @$(call do_cmd,cxx,1) -$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD - @$(call do_cmd,cxx,1) -$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cxx FORCE_DO_CMD - @$(call do_cmd,cxx,1) -$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.m FORCE_DO_CMD - @$(call do_cmd,objc,1) -$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.mm FORCE_DO_CMD - @$(call do_cmd,objcxx,1) -$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.S FORCE_DO_CMD - @$(call do_cmd,cc,1) -$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.s FORCE_DO_CMD - @$(call do_cmd,cc,1) - -$(obj).$(TOOLSET)/%.o: $(obj)/%.c FORCE_DO_CMD - @$(call do_cmd,cc,1) -$(obj).$(TOOLSET)/%.o: $(obj)/%.cc FORCE_DO_CMD - @$(call do_cmd,cxx,1) -$(obj).$(TOOLSET)/%.o: $(obj)/%.cpp FORCE_DO_CMD - @$(call do_cmd,cxx,1) -$(obj).$(TOOLSET)/%.o: $(obj)/%.cxx FORCE_DO_CMD - @$(call do_cmd,cxx,1) -$(obj).$(TOOLSET)/%.o: $(obj)/%.m FORCE_DO_CMD - @$(call do_cmd,objc,1) -$(obj).$(TOOLSET)/%.o: $(obj)/%.mm FORCE_DO_CMD - @$(call do_cmd,objcxx,1) -$(obj).$(TOOLSET)/%.o: $(obj)/%.S FORCE_DO_CMD - @$(call do_cmd,cc,1) -$(obj).$(TOOLSET)/%.o: $(obj)/%.s FORCE_DO_CMD - @$(call do_cmd,cc,1) - - -ifeq ($(strip $(foreach prefix,$(NO_LOAD),\ - $(findstring $(join ^,$(prefix)),\ - $(join ^,bson.target.mk)))),) - include bson.target.mk -endif - -quiet_cmd_regen_makefile = ACTION Regenerating $@ -cmd_regen_makefile = cd $(srcdir); /usr/local/lib/node_modules/npm/node_modules/node-gyp/gyp/gyp_main.py -fmake --ignore-environment "--toplevel-dir=." -I/Users/voxfeed_1/code/offhours/argon/node_modules/mongodb/node_modules/bson/build/config.gypi -I/usr/local/lib/node_modules/npm/node_modules/node-gyp/addon.gypi -I/Users/voxfeed_1/.node-gyp/0.10.31/common.gypi "--depth=." "-Goutput_dir=." "--generator-output=build" "-Dlibrary=shared_library" "-Dvisibility=default" "-Dnode_root_dir=/Users/voxfeed_1/.node-gyp/0.10.31" "-Dmodule_root_dir=/Users/voxfeed_1/code/offhours/argon/node_modules/mongodb/node_modules/bson" binding.gyp -Makefile: $(srcdir)/../../../../../../../../../usr/local/lib/node_modules/npm/node_modules/node-gyp/addon.gypi $(srcdir)/build/config.gypi $(srcdir)/binding.gyp $(srcdir)/../../../../../../../.node-gyp/0.10.31/common.gypi - $(call do_cmd,regen_makefile) - -# "all" is a concatenation of the "all" targets from all the included -# sub-makefiles. This is just here to clarify. -all: - -# Add in dependency-tracking rules. $(all_deps) is the list of every single -# target in our tree. Only consider the ones with .d (dependency) info: -d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d)) -ifneq ($(d_files),) - include $(d_files) -endif diff --git a/node_modules/mongodb/node_modules/bson/build/Release/.deps/Release/bson.node.d b/node_modules/mongodb/node_modules/bson/build/Release/.deps/Release/bson.node.d deleted file mode 100644 index b3465a6..0000000 --- a/node_modules/mongodb/node_modules/bson/build/Release/.deps/Release/bson.node.d +++ /dev/null @@ -1 +0,0 @@ -cmd_Release/bson.node := ./gyp-mac-tool flock ./Release/linker.lock c++ -bundle -Wl,-search_paths_first -mmacosx-version-min=10.5 -arch x86_64 -L./Release -o Release/bson.node Release/obj.target/bson/ext/bson.o -undefined dynamic_lookup diff --git a/node_modules/mongodb/node_modules/bson/build/Release/.deps/Release/obj.target/bson/ext/bson.o.d b/node_modules/mongodb/node_modules/bson/build/Release/.deps/Release/obj.target/bson/ext/bson.o.d deleted file mode 100644 index 0198e3e..0000000 --- a/node_modules/mongodb/node_modules/bson/build/Release/.deps/Release/obj.target/bson/ext/bson.o.d +++ /dev/null @@ -1,26 +0,0 @@ -cmd_Release/obj.target/bson/ext/bson.o := c++ '-D_DARWIN_USE_64_BIT_INODE=1' '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-DBUILDING_NODE_EXTENSION' -I/Users/voxfeed_1/.node-gyp/0.10.31/src -I/Users/voxfeed_1/.node-gyp/0.10.31/deps/uv/include -I/Users/voxfeed_1/.node-gyp/0.10.31/deps/v8/include -I../node_modules/nan -Os -gdwarf-2 -mmacosx-version-min=10.5 -arch x86_64 -Wall -Wendif-labels -W -Wno-unused-parameter -fno-rtti -fno-threadsafe-statics -fno-strict-aliasing -MMD -MF ./Release/.deps/Release/obj.target/bson/ext/bson.o.d.raw -c -o Release/obj.target/bson/ext/bson.o ../ext/bson.cc -Release/obj.target/bson/ext/bson.o: ../ext/bson.cc \ - /Users/voxfeed_1/.node-gyp/0.10.31/deps/v8/include/v8.h \ - /Users/voxfeed_1/.node-gyp/0.10.31/deps/v8/include/v8stdint.h \ - /Users/voxfeed_1/.node-gyp/0.10.31/src/node.h \ - /Users/voxfeed_1/.node-gyp/0.10.31/deps/uv/include/uv.h \ - /Users/voxfeed_1/.node-gyp/0.10.31/deps/uv/include/uv-private/uv-unix.h \ - /Users/voxfeed_1/.node-gyp/0.10.31/deps/uv/include/uv-private/ngx-queue.h \ - /Users/voxfeed_1/.node-gyp/0.10.31/deps/uv/include/uv-private/uv-darwin.h \ - /Users/voxfeed_1/.node-gyp/0.10.31/src/node_object_wrap.h \ - /Users/voxfeed_1/.node-gyp/0.10.31/src/node_version.h \ - /Users/voxfeed_1/.node-gyp/0.10.31/src/node_buffer.h ../ext/bson.h \ - ../node_modules/nan/nan.h -../ext/bson.cc: -/Users/voxfeed_1/.node-gyp/0.10.31/deps/v8/include/v8.h: -/Users/voxfeed_1/.node-gyp/0.10.31/deps/v8/include/v8stdint.h: -/Users/voxfeed_1/.node-gyp/0.10.31/src/node.h: -/Users/voxfeed_1/.node-gyp/0.10.31/deps/uv/include/uv.h: -/Users/voxfeed_1/.node-gyp/0.10.31/deps/uv/include/uv-private/uv-unix.h: -/Users/voxfeed_1/.node-gyp/0.10.31/deps/uv/include/uv-private/ngx-queue.h: -/Users/voxfeed_1/.node-gyp/0.10.31/deps/uv/include/uv-private/uv-darwin.h: -/Users/voxfeed_1/.node-gyp/0.10.31/src/node_object_wrap.h: -/Users/voxfeed_1/.node-gyp/0.10.31/src/node_version.h: -/Users/voxfeed_1/.node-gyp/0.10.31/src/node_buffer.h: -../ext/bson.h: -../node_modules/nan/nan.h: diff --git a/node_modules/mongodb/node_modules/bson/build/Release/bson.node b/node_modules/mongodb/node_modules/bson/build/Release/bson.node deleted file mode 100755 index b15b30551aa6b005e722b07a14a3d90e786657ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58484 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 diff --git a/node_modules/mongodb/node_modules/bson/build/Release/linker.lock b/node_modules/mongodb/node_modules/bson/build/Release/linker.lock deleted file mode 100644 index e69de29..0000000 diff --git a/node_modules/mongodb/node_modules/bson/build/Release/obj.target/bson/ext/bson.o b/node_modules/mongodb/node_modules/bson/build/Release/obj.target/bson/ext/bson.o deleted file mode 100644 index b7754e187f6f15a5aee17a48b48542d12e2773bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 336876 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 z z^>$X6x3j{$1%-JF3iB2e=G~`Zp;wpaEhyC6kD*tOJaPj1?my2NcvZ*Levgg208X7h z?Z?`S*W4JG6&&8}a_H^)+lv0z7o$|*?Iwq}n;cj7cgX_{HUAYTpNsw${"): - lines[i] = None - lines[i - 1] = None - lines = '\n'.join(filter(lambda x: x is not None, lines)) - - # Write out the file with variables replaced. - fd = open(dest, 'w') - fd.write(lines) - fd.close() - - # Now write out PkgInfo file now that the Info.plist file has been - # "compiled". - self._WritePkgInfo(dest) - - def _WritePkgInfo(self, info_plist): - """This writes the PkgInfo file from the data stored in Info.plist.""" - plist = plistlib.readPlist(info_plist) - if not plist: - return - - # Only create PkgInfo for executable types. - package_type = plist['CFBundlePackageType'] - if package_type != 'APPL': - return - - # The format of PkgInfo is eight characters, representing the bundle type - # and bundle signature, each four characters. If that is missing, four - # '?' characters are used instead. - signature_code = plist.get('CFBundleSignature', '????') - if len(signature_code) != 4: # Wrong length resets everything, too. - signature_code = '?' * 4 - - dest = os.path.join(os.path.dirname(info_plist), 'PkgInfo') - fp = open(dest, 'w') - fp.write('%s%s' % (package_type, signature_code)) - fp.close() - - def ExecFlock(self, lockfile, *cmd_list): - """Emulates the most basic behavior of Linux's flock(1).""" - # Rely on exception handling to report errors. - fd = os.open(lockfile, os.O_RDONLY|os.O_NOCTTY|os.O_CREAT, 0o666) - fcntl.flock(fd, fcntl.LOCK_EX) - return subprocess.call(cmd_list) - - def ExecFilterLibtool(self, *cmd_list): - """Calls libtool and filters out '/path/to/libtool: file: foo.o has no - symbols'.""" - libtool_re = re.compile(r'^.*libtool: file: .* has no symbols$') - libtoolout = subprocess.Popen(cmd_list, stderr=subprocess.PIPE) - _, err = libtoolout.communicate() - for line in err.splitlines(): - if not libtool_re.match(line): - print >>sys.stderr, line - return libtoolout.returncode - - def ExecPackageFramework(self, framework, version): - """Takes a path to Something.framework and the Current version of that and - sets up all the symlinks.""" - # Find the name of the binary based on the part before the ".framework". - binary = os.path.basename(framework).split('.')[0] - - CURRENT = 'Current' - RESOURCES = 'Resources' - VERSIONS = 'Versions' - - if not os.path.exists(os.path.join(framework, VERSIONS, version, binary)): - # Binary-less frameworks don't seem to contain symlinks (see e.g. - # chromium's out/Debug/org.chromium.Chromium.manifest/ bundle). - return - - # Move into the framework directory to set the symlinks correctly. - pwd = os.getcwd() - os.chdir(framework) - - # Set up the Current version. - self._Relink(version, os.path.join(VERSIONS, CURRENT)) - - # Set up the root symlinks. - self._Relink(os.path.join(VERSIONS, CURRENT, binary), binary) - self._Relink(os.path.join(VERSIONS, CURRENT, RESOURCES), RESOURCES) - - # Back to where we were before! - os.chdir(pwd) - - def _Relink(self, dest, link): - """Creates a symlink to |dest| named |link|. If |link| already exists, - it is overwritten.""" - if os.path.lexists(link): - os.remove(link) - os.symlink(dest, link) - - def ExecCodeSignBundle(self, key, resource_rules, entitlements, provisioning): - """Code sign a bundle. - - This function tries to code sign an iOS bundle, following the same - algorithm as Xcode: - 1. copy ResourceRules.plist from the user or the SDK into the bundle, - 2. pick the provisioning profile that best match the bundle identifier, - and copy it into the bundle as embedded.mobileprovision, - 3. copy Entitlements.plist from user or SDK next to the bundle, - 4. code sign the bundle. - """ - resource_rules_path = self._InstallResourceRules(resource_rules) - substitutions, overrides = self._InstallProvisioningProfile( - provisioning, self._GetCFBundleIdentifier()) - entitlements_path = self._InstallEntitlements( - entitlements, substitutions, overrides) - subprocess.check_call([ - 'codesign', '--force', '--sign', key, '--resource-rules', - resource_rules_path, '--entitlements', entitlements_path, - os.path.join( - os.environ['TARGET_BUILD_DIR'], - os.environ['FULL_PRODUCT_NAME'])]) - - def _InstallResourceRules(self, resource_rules): - """Installs ResourceRules.plist from user or SDK into the bundle. - - Args: - resource_rules: string, optional, path to the ResourceRules.plist file - to use, default to "${SDKROOT}/ResourceRules.plist" - - Returns: - Path to the copy of ResourceRules.plist into the bundle. - """ - source_path = resource_rules - target_path = os.path.join( - os.environ['BUILT_PRODUCTS_DIR'], - os.environ['CONTENTS_FOLDER_PATH'], - 'ResourceRules.plist') - if not source_path: - source_path = os.path.join( - os.environ['SDKROOT'], 'ResourceRules.plist') - shutil.copy2(source_path, target_path) - return target_path - - def _InstallProvisioningProfile(self, profile, bundle_identifier): - """Installs embedded.mobileprovision into the bundle. - - Args: - profile: string, optional, short name of the .mobileprovision file - to use, if empty or the file is missing, the best file installed - will be used - bundle_identifier: string, value of CFBundleIdentifier from Info.plist - - Returns: - A tuple containing two dictionary: variables substitutions and values - to overrides when generating the entitlements file. - """ - source_path, provisioning_data, team_id = self._FindProvisioningProfile( - profile, bundle_identifier) - target_path = os.path.join( - os.environ['BUILT_PRODUCTS_DIR'], - os.environ['CONTENTS_FOLDER_PATH'], - 'embedded.mobileprovision') - shutil.copy2(source_path, target_path) - substitutions = self._GetSubstitutions(bundle_identifier, team_id + '.') - return substitutions, provisioning_data['Entitlements'] - - def _FindProvisioningProfile(self, profile, bundle_identifier): - """Finds the .mobileprovision file to use for signing the bundle. - - Checks all the installed provisioning profiles (or if the user specified - the PROVISIONING_PROFILE variable, only consult it) and select the most - specific that correspond to the bundle identifier. - - Args: - profile: string, optional, short name of the .mobileprovision file - to use, if empty or the file is missing, the best file installed - will be used - bundle_identifier: string, value of CFBundleIdentifier from Info.plist - - Returns: - A tuple of the path to the selected provisioning profile, the data of - the embedded plist in the provisioning profile and the team identifier - to use for code signing. - - Raises: - SystemExit: if no .mobileprovision can be used to sign the bundle. - """ - profiles_dir = os.path.join( - os.environ['HOME'], 'Library', 'MobileDevice', 'Provisioning Profiles') - if not os.path.isdir(profiles_dir): - print >>sys.stderr, ( - 'cannot find mobile provisioning for %s' % bundle_identifier) - sys.exit(1) - provisioning_profiles = None - if profile: - profile_path = os.path.join(profiles_dir, profile + '.mobileprovision') - if os.path.exists(profile_path): - provisioning_profiles = [profile_path] - if not provisioning_profiles: - provisioning_profiles = glob.glob( - os.path.join(profiles_dir, '*.mobileprovision')) - valid_provisioning_profiles = {} - for profile_path in provisioning_profiles: - profile_data = self._LoadProvisioningProfile(profile_path) - app_id_pattern = profile_data.get( - 'Entitlements', {}).get('application-identifier', '') - for team_identifier in profile_data.get('TeamIdentifier', []): - app_id = '%s.%s' % (team_identifier, bundle_identifier) - if fnmatch.fnmatch(app_id, app_id_pattern): - valid_provisioning_profiles[app_id_pattern] = ( - profile_path, profile_data, team_identifier) - if not valid_provisioning_profiles: - print >>sys.stderr, ( - 'cannot find mobile provisioning for %s' % bundle_identifier) - sys.exit(1) - # If the user has multiple provisioning profiles installed that can be - # used for ${bundle_identifier}, pick the most specific one (ie. the - # provisioning profile whose pattern is the longest). - selected_key = max(valid_provisioning_profiles, key=lambda v: len(v)) - return valid_provisioning_profiles[selected_key] - - def _LoadProvisioningProfile(self, profile_path): - """Extracts the plist embedded in a provisioning profile. - - Args: - profile_path: string, path to the .mobileprovision file - - Returns: - Content of the plist embedded in the provisioning profile as a dictionary. - """ - with tempfile.NamedTemporaryFile() as temp: - subprocess.check_call([ - 'security', 'cms', '-D', '-i', profile_path, '-o', temp.name]) - return self._LoadPlistMaybeBinary(temp.name) - - def _LoadPlistMaybeBinary(self, plist_path): - """Loads into a memory a plist possibly encoded in binary format. - - This is a wrapper around plistlib.readPlist that tries to convert the - plist to the XML format if it can't be parsed (assuming that it is in - the binary format). - - Args: - plist_path: string, path to a plist file, in XML or binary format - - Returns: - Content of the plist as a dictionary. - """ - try: - # First, try to read the file using plistlib that only supports XML, - # and if an exception is raised, convert a temporary copy to XML and - # load that copy. - return plistlib.readPlist(plist_path) - except: - pass - with tempfile.NamedTemporaryFile() as temp: - shutil.copy2(plist_path, temp.name) - subprocess.check_call(['plutil', '-convert', 'xml1', temp.name]) - return plistlib.readPlist(temp.name) - - def _GetSubstitutions(self, bundle_identifier, app_identifier_prefix): - """Constructs a dictionary of variable substitutions for Entitlements.plist. - - Args: - bundle_identifier: string, value of CFBundleIdentifier from Info.plist - app_identifier_prefix: string, value for AppIdentifierPrefix - - Returns: - Dictionary of substitutions to apply when generating Entitlements.plist. - """ - return { - 'CFBundleIdentifier': bundle_identifier, - 'AppIdentifierPrefix': app_identifier_prefix, - } - - def _GetCFBundleIdentifier(self): - """Extracts CFBundleIdentifier value from Info.plist in the bundle. - - Returns: - Value of CFBundleIdentifier in the Info.plist located in the bundle. - """ - info_plist_path = os.path.join( - os.environ['TARGET_BUILD_DIR'], - os.environ['INFOPLIST_PATH']) - info_plist_data = self._LoadPlistMaybeBinary(info_plist_path) - return info_plist_data['CFBundleIdentifier'] - - def _InstallEntitlements(self, entitlements, substitutions, overrides): - """Generates and install the ${BundleName}.xcent entitlements file. - - Expands variables "$(variable)" pattern in the source entitlements file, - add extra entitlements defined in the .mobileprovision file and the copy - the generated plist to "${BundlePath}.xcent". - - Args: - entitlements: string, optional, path to the Entitlements.plist template - to use, defaults to "${SDKROOT}/Entitlements.plist" - substitutions: dictionary, variable substitutions - overrides: dictionary, values to add to the entitlements - - Returns: - Path to the generated entitlements file. - """ - source_path = entitlements - target_path = os.path.join( - os.environ['BUILT_PRODUCTS_DIR'], - os.environ['PRODUCT_NAME'] + '.xcent') - if not source_path: - source_path = os.path.join( - os.environ['SDKROOT'], - 'Entitlements.plist') - shutil.copy2(source_path, target_path) - data = self._LoadPlistMaybeBinary(target_path) - data = self._ExpandVariables(data, substitutions) - if overrides: - for key in overrides: - if key not in data: - data[key] = overrides[key] - plistlib.writePlist(data, target_path) - return target_path - - def _ExpandVariables(self, data, substitutions): - """Expands variables "$(variable)" in data. - - Args: - data: object, can be either string, list or dictionary - substitutions: dictionary, variable substitutions to perform - - Returns: - Copy of data where each references to "$(variable)" has been replaced - by the corresponding value found in substitutions, or left intact if - the key was not found. - """ - if isinstance(data, str): - for key, value in substitutions.iteritems(): - data = data.replace('$(%s)' % key, value) - return data - if isinstance(data, list): - return [self._ExpandVariables(v, substitutions) for v in data] - if isinstance(data, dict): - return dict((k, self._ExpandVariables(data[k], - substitutions)) for k in data) - return data - -if __name__ == '__main__': - sys.exit(main(sys.argv[1:])) diff --git a/node_modules/mongodb/node_modules/bson/build_browser.js b/node_modules/mongodb/node_modules/bson/build_browser.js deleted file mode 100644 index bb80238..0000000 --- a/node_modules/mongodb/node_modules/bson/build_browser.js +++ /dev/null @@ -1,7 +0,0 @@ -require('one'); - -one('./package.json') - .tie('bson', BSON) - // .exclude('buffer') - .tie('buffer', {}) - .save('./browser_build/bson.js') \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/bson/builderror.log b/node_modules/mongodb/node_modules/bson/builderror.log deleted file mode 100644 index 9c12da4..0000000 --- a/node_modules/mongodb/node_modules/bson/builderror.log +++ /dev/null @@ -1,4 +0,0 @@ -xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance - -xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance - diff --git a/node_modules/mongodb/node_modules/bson/ext/Makefile b/node_modules/mongodb/node_modules/bson/ext/Makefile deleted file mode 100644 index 435999e..0000000 --- a/node_modules/mongodb/node_modules/bson/ext/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -NODE = node -name = all -JOBS = 1 - -all: - rm -rf build .lock-wscript bson.node - node-waf configure build - cp -R ./build/Release/bson.node . || true - -all_debug: - rm -rf build .lock-wscript bson.node - node-waf --debug configure build - cp -R ./build/Release/bson.node . || true - -clang: - rm -rf build .lock-wscript bson.node - CXX=clang node-waf configure build - cp -R ./build/Release/bson.node . || true - -clang_debug: - rm -rf build .lock-wscript bson.node - CXX=clang node-waf --debug configure build - cp -R ./build/Release/bson.node . || true - -clean: - rm -rf build .lock-wscript bson.node - -.PHONY: all \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/bson/ext/bson.cc b/node_modules/mongodb/node_modules/bson/ext/bson.cc deleted file mode 100644 index 90e2ef9..0000000 --- a/node_modules/mongodb/node_modules/bson/ext/bson.cc +++ /dev/null @@ -1,1072 +0,0 @@ -//=========================================================================== - -#include -#include -#include -#include -#include - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-parameter" -#endif - -#include - -// this and the above block must be around the v8.h header otherwise -// v8 is not happy -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -#include -#include -#include - -#include -#include -#include -#include -#include - -#if defined(__sun) || defined(_AIX) - #include -#endif - -#include "bson.h" - -using namespace v8; -using namespace node; - -void die(const char *message) { - if(errno) { - perror(message); - } else { - printf("ERROR: %s\n", message); - } - - exit(1); -} - -//=========================================================================== - -void DataStream::WriteObjectId(const Handle& object, const Handle& key) -{ - uint16_t buffer[12]; - object->Get(key)->ToString()->Write(buffer, 0, 12); - for(uint32_t i = 0; i < 12; ++i) - { - *p++ = (char) buffer[i]; - } -} - -void ThrowAllocatedStringException(size_t allocationSize, const char* format, ...) -{ - va_list args; - va_start(args, format); - char* string = (char*) malloc(allocationSize); - if(string == NULL) die("Failed to allocate ThrowAllocatedStringException"); - vsprintf(string, format, args); - va_end(args); - throw string; -} - -void DataStream::CheckKey(const Local& keyName) -{ - size_t keyLength = keyName->Utf8Length(); - if(keyLength == 0) return; - - // Allocate space for the key, do not need to zero terminate as WriteUtf8 does it - char* keyStringBuffer = (char*) alloca(keyLength + 1); - // Write the key to the allocated buffer - keyName->WriteUtf8(keyStringBuffer); - // Check for the zero terminator - char* terminator = strchr(keyStringBuffer, 0x00); - - // If the location is not at the end of the string we've got an illegal 0x00 byte somewhere - if(terminator != &keyStringBuffer[keyLength]) { - ThrowAllocatedStringException(64+keyLength, "key %s must not contain null bytes", keyStringBuffer); - } - - if(keyStringBuffer[0] == '$') - { - ThrowAllocatedStringException(64+keyLength, "key %s must not start with '$'", keyStringBuffer); - } - - if(strchr(keyStringBuffer, '.') != NULL) - { - ThrowAllocatedStringException(64+keyLength, "key %s must not contain '.'", keyStringBuffer); - } -} - -template void BSONSerializer::SerializeDocument(const Handle& value) -{ - void* documentSize = this->BeginWriteSize(); - Local object = bson->GetSerializeObject(value); - - // Get the object property names - Local propertyNames = object->GetPropertyNames(); - - // Length of the property - int propertyLength = propertyNames->Length(); - for(int i = 0; i < propertyLength; ++i) - { - const Local& propertyName = propertyNames->Get(i)->ToString(); - if(checkKeys) this->CheckKey(propertyName); - - const Local& propertyValue = object->Get(propertyName); - - if(serializeFunctions || !propertyValue->IsFunction()) - { - void* typeLocation = this->BeginWriteType(); - this->WriteString(propertyName); - SerializeValue(typeLocation, propertyValue); - } - } - - this->WriteByte(0); - this->CommitSize(documentSize); -} - -template void BSONSerializer::SerializeArray(const Handle& value) -{ - void* documentSize = this->BeginWriteSize(); - - Local array = Local::Cast(value->ToObject()); - uint32_t arrayLength = array->Length(); - - for(uint32_t i = 0; i < arrayLength; ++i) - { - void* typeLocation = this->BeginWriteType(); - this->WriteUInt32String(i); - SerializeValue(typeLocation, array->Get(i)); - } - - this->WriteByte(0); - this->CommitSize(documentSize); -} - -// This is templated so that we can use this function to both count the number of bytes, and to serialize those bytes. -// The template approach eliminates almost all of the inspection of values unless they're required (eg. string lengths) -// and ensures that there is always consistency between bytes counted and bytes written by design. -template void BSONSerializer::SerializeValue(void* typeLocation, const Handle constValue) -{ - // Turn into local value - Local value = NanNew(constValue); - - // Check for toBSON function - if(value->IsObject()) { - Local object = value->ToObject(); - - // NanNew("toBSON") - // NanNew(BSON::_toBSONString) - - if(object->Has(NanNew("toBSON"))) { - const Local& toBSON = object->Get(NanNew("toBSON")); - if(!toBSON->IsFunction()) ThrowAllocatedStringException(64, "toBSON is not a function"); - value = Local::Cast(toBSON)->Call(object, 0, NULL); - } - } - - // Process all the values - if(value->IsNumber()) - { - double doubleValue = value->NumberValue(); - int intValue = (int) doubleValue; - if(intValue == doubleValue) - { - this->CommitType(typeLocation, BSON_TYPE_INT); - this->WriteInt32(intValue); - } - else - { - this->CommitType(typeLocation, BSON_TYPE_NUMBER); - this->WriteDouble(doubleValue); - } - } - else if(value->IsString()) - { - this->CommitType(typeLocation, BSON_TYPE_STRING); - this->WriteLengthPrefixedString(value->ToString()); - } - else if(value->IsBoolean()) - { - this->CommitType(typeLocation, BSON_TYPE_BOOLEAN); - this->WriteBool(value); - } - else if(value->IsArray()) - { - this->CommitType(typeLocation, BSON_TYPE_ARRAY); - SerializeArray(value); - } - else if(value->IsDate()) - { - this->CommitType(typeLocation, BSON_TYPE_DATE); - this->WriteInt64(value); - } - else if(value->IsRegExp()) - { - this->CommitType(typeLocation, BSON_TYPE_REGEXP); - const Handle& regExp = Handle::Cast(value); - - this->WriteString(regExp->GetSource()); - - int flags = regExp->GetFlags(); - if(flags & RegExp::kGlobal) this->WriteByte('s'); - if(flags & RegExp::kIgnoreCase) this->WriteByte('i'); - if(flags & RegExp::kMultiline) this->WriteByte('m'); - this->WriteByte(0); - } - else if(value->IsFunction()) - { - this->CommitType(typeLocation, BSON_TYPE_CODE); - this->WriteLengthPrefixedString(value->ToString()); - } - else if(value->IsObject()) - { - const Local& object = value->ToObject(); - if(object->Has(NanNew(bson->_bsontypeString))) - { - const Local& constructorString = object->Get(NanNew(bson->_bsontypeString))->ToString(); - if(NanNew(bson->longString)->StrictEquals(constructorString)) - { - this->CommitType(typeLocation, BSON_TYPE_LONG); - this->WriteInt32(object, NanNew(bson->_longLowString)); - this->WriteInt32(object, NanNew(bson->_longHighString)); - } - else if(NanNew(bson->timestampString)->StrictEquals(constructorString)) - { - this->CommitType(typeLocation, BSON_TYPE_TIMESTAMP); - this->WriteInt32(object, NanNew(bson->_longLowString)); - this->WriteInt32(object, NanNew(bson->_longHighString)); - } - else if(NanNew(bson->objectIDString)->StrictEquals(constructorString)) - { - this->CommitType(typeLocation, BSON_TYPE_OID); - this->WriteObjectId(object, NanNew(bson->_objectIDidString)); - } - else if(NanNew(bson->binaryString)->StrictEquals(constructorString)) - { - this->CommitType(typeLocation, BSON_TYPE_BINARY); - - uint32_t length = object->Get(NanNew(bson->_binaryPositionString))->Uint32Value(); - Local bufferObj = object->Get(NanNew(bson->_binaryBufferString))->ToObject(); - - this->WriteInt32(length); - this->WriteByte(object, NanNew(bson->_binarySubTypeString)); // write subtype - // If type 0x02 write the array length aswell - if(object->Get(NanNew(bson->_binarySubTypeString))->Int32Value() == 0x02) { - this->WriteInt32(length); - } - // Write the actual data - this->WriteData(Buffer::Data(bufferObj), length); - } - else if(NanNew(bson->doubleString)->StrictEquals(constructorString)) - { - this->CommitType(typeLocation, BSON_TYPE_NUMBER); - this->WriteDouble(object, NanNew(bson->_doubleValueString)); - } - else if(NanNew(bson->symbolString)->StrictEquals(constructorString)) - { - this->CommitType(typeLocation, BSON_TYPE_SYMBOL); - this->WriteLengthPrefixedString(object->Get(NanNew(bson->_symbolValueString))->ToString()); - } - else if(NanNew(bson->codeString)->StrictEquals(constructorString)) - { - const Local& function = object->Get(NanNew(bson->_codeCodeString))->ToString(); - const Local& scope = object->Get(NanNew(bson->_codeScopeString))->ToObject(); - - // For Node < 0.6.X use the GetPropertyNames - #if NODE_MAJOR_VERSION == 0 && NODE_MINOR_VERSION < 6 - uint32_t propertyNameLength = scope->GetPropertyNames()->Length(); - #else - uint32_t propertyNameLength = scope->GetOwnPropertyNames()->Length(); - #endif - - if(propertyNameLength > 0) - { - this->CommitType(typeLocation, BSON_TYPE_CODE_W_SCOPE); - void* codeWidthScopeSize = this->BeginWriteSize(); - this->WriteLengthPrefixedString(function->ToString()); - SerializeDocument(scope); - this->CommitSize(codeWidthScopeSize); - } - else - { - this->CommitType(typeLocation, BSON_TYPE_CODE); - this->WriteLengthPrefixedString(function->ToString()); - } - } - else if(NanNew(bson->dbrefString)->StrictEquals(constructorString)) - { - this->CommitType(typeLocation, BSON_TYPE_OBJECT); - - void* dbRefSize = this->BeginWriteSize(); - - void* refType = this->BeginWriteType(); - this->WriteData("$ref", 5); - SerializeValue(refType, object->Get(NanNew(bson->_dbRefNamespaceString))); - - void* idType = this->BeginWriteType(); - this->WriteData("$id", 4); - SerializeValue(idType, object->Get(NanNew(bson->_dbRefOidString))); - - const Local& refDbValue = object->Get(NanNew(bson->_dbRefDbString)); - if(!refDbValue->IsUndefined()) - { - void* dbType = this->BeginWriteType(); - this->WriteData("$db", 4); - SerializeValue(dbType, refDbValue); - } - - this->WriteByte(0); - this->CommitSize(dbRefSize); - } - else if(NanNew(bson->minKeyString)->StrictEquals(constructorString)) - { - this->CommitType(typeLocation, BSON_TYPE_MIN_KEY); - } - else if(NanNew(bson->maxKeyString)->StrictEquals(constructorString)) - { - this->CommitType(typeLocation, BSON_TYPE_MAX_KEY); - } - } - else if(Buffer::HasInstance(value)) - { - this->CommitType(typeLocation, BSON_TYPE_BINARY); - - #if NODE_MAJOR_VERSION == 0 && NODE_MINOR_VERSION < 3 - Local buffer = ObjectWrap::Unwrap(value->ToObject()); - uint32_t length = object->length(); - #else - uint32_t length = Buffer::Length(value->ToObject()); - #endif - - this->WriteInt32(length); - this->WriteByte(0); - this->WriteData(Buffer::Data(value->ToObject()), length); - } - else - { - this->CommitType(typeLocation, BSON_TYPE_OBJECT); - SerializeDocument(value); - } - } - else if(value->IsNull() || value->IsUndefined()) - { - this->CommitType(typeLocation, BSON_TYPE_NULL); - } -} - -// Data points to start of element list, length is length of entire document including '\0' but excluding initial size -BSONDeserializer::BSONDeserializer(BSON* aBson, char* data, size_t length) -: bson(aBson), - pStart(data), - p(data), - pEnd(data + length - 1) -{ - if(*pEnd != '\0') ThrowAllocatedStringException(64, "Missing end of document marker '\\0'"); -} - -BSONDeserializer::BSONDeserializer(BSONDeserializer& parentSerializer, size_t length) -: bson(parentSerializer.bson), - pStart(parentSerializer.p), - p(parentSerializer.p), - pEnd(parentSerializer.p + length - 1) -{ - parentSerializer.p += length; - if(pEnd > parentSerializer.pEnd) ThrowAllocatedStringException(64, "Child document exceeds parent's bounds"); - if(*pEnd != '\0') ThrowAllocatedStringException(64, "Missing end of document marker '\\0'"); -} - -Handle BSONDeserializer::ReadCString() -{ - char* start = p; - while(*p++ && (p < pEnd)) { } - if(p > pEnd) { - return NanNull(); - } - return NanNew(start, (int32_t) (p-start-1) ); -} - -int32_t BSONDeserializer::ReadRegexOptions() -{ - int32_t options = 0; - for(;;) - { - switch(*p++) - { - case '\0': return options; - case 's': options |= RegExp::kGlobal; break; - case 'i': options |= RegExp::kIgnoreCase; break; - case 'm': options |= RegExp::kMultiline; break; - } - } -} - -uint32_t BSONDeserializer::ReadIntegerString() -{ - uint32_t value = 0; - while(*p) - { - if(*p < '0' || *p > '9') ThrowAllocatedStringException(64, "Invalid key for array"); - value = value * 10 + *p++ - '0'; - } - ++p; - return value; -} - -Local BSONDeserializer::ReadString() -{ - uint32_t length = ReadUInt32(); - char* start = p; - p += length; - return NanNew(start, length-1); -} - -Local BSONDeserializer::ReadObjectId() -{ - uint16_t objectId[12]; - for(size_t i = 0; i < 12; ++i) - { - objectId[i] = *reinterpret_cast(p++); - } - return NanNew(objectId, 12); -} - -Handle BSONDeserializer::DeserializeDocument(bool promoteLongs) -{ - uint32_t length = ReadUInt32(); - if(length < 5) ThrowAllocatedStringException(64, "Bad BSON: Document is less than 5 bytes"); - - BSONDeserializer documentDeserializer(*this, length-4); - return documentDeserializer.DeserializeDocumentInternal(promoteLongs); -} - -Handle BSONDeserializer::DeserializeDocumentInternal(bool promoteLongs) -{ - Local returnObject = NanNew(); - - while(HasMoreData()) - { - BsonType type = (BsonType) ReadByte(); - const Handle& name = ReadCString(); - if(name->IsNull()) ThrowAllocatedStringException(64, "Bad BSON Document: illegal CString"); - // name->Is - const Handle& value = DeserializeValue(type, promoteLongs); - returnObject->ForceSet(name, value); - } - if(p != pEnd) ThrowAllocatedStringException(64, "Bad BSON Document: Serialize consumed unexpected number of bytes"); - - // From JavaScript: - // if(object['$id'] != null) object = new DBRef(object['$ref'], object['$id'], object['$db']); - if(returnObject->Has(NanNew(bson->_dbRefIdRefString))) - { - Local argv[] = { returnObject->Get(NanNew(bson->_dbRefRefString)), returnObject->Get(NanNew(bson->_dbRefIdRefString)), returnObject->Get(NanNew(bson->_dbRefDbRefString)) }; - return NanNew(bson->dbrefConstructor)->NewInstance(3, argv); - } - else - { - return returnObject; - } -} - -Handle BSONDeserializer::DeserializeArray(bool promoteLongs) -{ - uint32_t length = ReadUInt32(); - if(length < 5) ThrowAllocatedStringException(64, "Bad BSON: Array Document is less than 5 bytes"); - - BSONDeserializer documentDeserializer(*this, length-4); - return documentDeserializer.DeserializeArrayInternal(promoteLongs); -} - -Handle BSONDeserializer::DeserializeArrayInternal(bool promoteLongs) -{ - Local returnArray = NanNew(); - - while(HasMoreData()) - { - BsonType type = (BsonType) ReadByte(); - uint32_t index = ReadIntegerString(); - const Handle& value = DeserializeValue(type, promoteLongs); - returnArray->Set(index, value); - } - if(p != pEnd) ThrowAllocatedStringException(64, "Bad BSON Array: Serialize consumed unexpected number of bytes"); - - return returnArray; -} - -Handle BSONDeserializer::DeserializeValue(BsonType type, bool promoteLongs) -{ - switch(type) - { - case BSON_TYPE_STRING: - return ReadString(); - - case BSON_TYPE_INT: - return NanNew(ReadInt32()); - - case BSON_TYPE_NUMBER: - return NanNew(ReadDouble()); - - case BSON_TYPE_NULL: - return NanNull(); - - case BSON_TYPE_UNDEFINED: - return NanNull(); - - case BSON_TYPE_TIMESTAMP: - { - int32_t lowBits = ReadInt32(); - int32_t highBits = ReadInt32(); - Local argv[] = { NanNew(lowBits), NanNew(highBits) }; - return NanNew(bson->timestampConstructor)->NewInstance(2, argv); - } - - case BSON_TYPE_BOOLEAN: - return (ReadByte() != 0) ? NanTrue() : NanFalse(); - - case BSON_TYPE_REGEXP: - { - const Handle& regex = ReadCString(); - if(regex->IsNull()) ThrowAllocatedStringException(64, "Bad BSON Document: illegal CString"); - int32_t options = ReadRegexOptions(); - return NanNew(regex->ToString(), (RegExp::Flags) options); - } - - case BSON_TYPE_CODE: - { - const Local& code = ReadString(); - const Local& scope = NanNew(); - Local argv[] = { code, scope }; - return NanNew(bson->codeConstructor)->NewInstance(2, argv); - } - - case BSON_TYPE_CODE_W_SCOPE: - { - ReadUInt32(); - const Local& code = ReadString(); - const Handle& scope = DeserializeDocument(promoteLongs); - Local argv[] = { code, scope->ToObject() }; - return NanNew(bson->codeConstructor)->NewInstance(2, argv); - } - - case BSON_TYPE_OID: - { - Local argv[] = { ReadObjectId() }; - return NanNew(bson->objectIDConstructor)->NewInstance(1, argv); - } - - case BSON_TYPE_BINARY: - { - uint32_t length = ReadUInt32(); - uint32_t subType = ReadByte(); - if(subType == 0x02) { - length = ReadInt32(); - } - - Local buffer = NanNewBufferHandle(p, length); - p += length; - - Handle argv[] = { buffer, NanNew(subType) }; - return NanNew(bson->binaryConstructor)->NewInstance(2, argv); - } - - case BSON_TYPE_LONG: - { - // Read 32 bit integers - int32_t lowBits = (int32_t) ReadInt32(); - int32_t highBits = (int32_t) ReadInt32(); - - // Promote long is enabled - if(promoteLongs) { - // If value is < 2^53 and >-2^53 - if((highBits < 0x200000 || (highBits == 0x200000 && lowBits == 0)) && highBits >= -0x200000) { - // Adjust the pointer and read as 64 bit value - p -= 8; - // Read the 64 bit value - int64_t finalValue = (int64_t) ReadInt64(); - return NanNew(finalValue); - } - } - - // Decode the Long value - Local argv[] = { NanNew(lowBits), NanNew(highBits) }; - return NanNew(bson->longConstructor)->NewInstance(2, argv); - } - - case BSON_TYPE_DATE: - return NanNew((double) ReadInt64()); - - case BSON_TYPE_ARRAY: - return DeserializeArray(promoteLongs); - - case BSON_TYPE_OBJECT: - return DeserializeDocument(promoteLongs); - - case BSON_TYPE_SYMBOL: - { - const Local& string = ReadString(); - Local argv[] = { string }; - return NanNew(bson->symbolConstructor)->NewInstance(1, argv); - } - - case BSON_TYPE_MIN_KEY: - return NanNew(bson->minKeyConstructor)->NewInstance(); - - case BSON_TYPE_MAX_KEY: - return NanNew(bson->maxKeyConstructor)->NewInstance(); - - default: - ThrowAllocatedStringException(64, "Unhandled BSON Type: %d", type); - } - - return NanNull(); -} - -Persistent BSON::constructor_template; - -BSON::BSON() : ObjectWrap() -{ - // Setup pre-allocated comparision objects - NanAssignPersistent(_bsontypeString, NanNew("_bsontype")); - NanAssignPersistent(_longLowString, NanNew("low_")); - NanAssignPersistent(_longHighString, NanNew("high_")); - NanAssignPersistent(_objectIDidString, NanNew("id")); - NanAssignPersistent(_binaryPositionString, NanNew("position")); - NanAssignPersistent(_binarySubTypeString, NanNew("sub_type")); - NanAssignPersistent(_binaryBufferString, NanNew("buffer")); - NanAssignPersistent(_doubleValueString, NanNew("value")); - NanAssignPersistent(_symbolValueString, NanNew("value")); - NanAssignPersistent(_dbRefRefString, NanNew("$ref")); - NanAssignPersistent(_dbRefIdRefString, NanNew("$id")); - NanAssignPersistent(_dbRefDbRefString, NanNew("$db")); - NanAssignPersistent(_dbRefNamespaceString, NanNew("namespace")); - NanAssignPersistent(_dbRefDbString, NanNew("db")); - NanAssignPersistent(_dbRefOidString, NanNew("oid")); - NanAssignPersistent(_codeCodeString, NanNew("code")); - NanAssignPersistent(_codeScopeString, NanNew("scope")); - NanAssignPersistent(_toBSONString, NanNew("toBSON")); - - NanAssignPersistent(longString, NanNew("Long")); - NanAssignPersistent(objectIDString, NanNew("ObjectID")); - NanAssignPersistent(binaryString, NanNew("Binary")); - NanAssignPersistent(codeString, NanNew("Code")); - NanAssignPersistent(dbrefString, NanNew("DBRef")); - NanAssignPersistent(symbolString, NanNew("Symbol")); - NanAssignPersistent(doubleString, NanNew("Double")); - NanAssignPersistent(timestampString, NanNew("Timestamp")); - NanAssignPersistent(minKeyString, NanNew("MinKey")); - NanAssignPersistent(maxKeyString, NanNew("MaxKey")); -} - -void BSON::Initialize(v8::Handle target) -{ - // Grab the scope of the call from Node - NanScope(); - // Define a new function template - Local t = NanNew(New); - t->InstanceTemplate()->SetInternalFieldCount(1); - t->SetClassName(NanNew("BSON")); - - // Instance methods - NODE_SET_PROTOTYPE_METHOD(t, "calculateObjectSize", CalculateObjectSize); - NODE_SET_PROTOTYPE_METHOD(t, "serialize", BSONSerialize); - NODE_SET_PROTOTYPE_METHOD(t, "serializeWithBufferAndIndex", SerializeWithBufferAndIndex); - NODE_SET_PROTOTYPE_METHOD(t, "deserialize", BSONDeserialize); - NODE_SET_PROTOTYPE_METHOD(t, "deserializeStream", BSONDeserializeStream); - - NanAssignPersistent(constructor_template, t); - - target->ForceSet(NanNew("BSON"), t->GetFunction()); -} - -// Create a new instance of BSON and passing it the existing context -NAN_METHOD(BSON::New) -{ - NanScope(); - - // Check that we have an array - if(args.Length() == 1 && args[0]->IsArray()) - { - // Cast the array to a local reference - Local array = Local::Cast(args[0]); - - if(array->Length() > 0) - { - // Create a bson object instance and return it - BSON *bson = new BSON(); - - uint32_t foundClassesMask = 0; - - // Iterate over all entries to save the instantiate functions - for(uint32_t i = 0; i < array->Length(); i++) { - // Let's get a reference to the function - Local func = Local::Cast(array->Get(i)); - Local functionName = func->GetName()->ToString(); - - // Save the functions making them persistant handles (they don't get collected) - if(functionName->StrictEquals(NanNew(bson->longString))) { - NanAssignPersistent(bson->longConstructor, func); - foundClassesMask |= 1; - } else if(functionName->StrictEquals(NanNew(bson->objectIDString))) { - NanAssignPersistent(bson->objectIDConstructor, func); - foundClassesMask |= 2; - } else if(functionName->StrictEquals(NanNew(bson->binaryString))) { - NanAssignPersistent(bson->binaryConstructor, func); - foundClassesMask |= 4; - } else if(functionName->StrictEquals(NanNew(bson->codeString))) { - NanAssignPersistent(bson->codeConstructor, func); - foundClassesMask |= 8; - } else if(functionName->StrictEquals(NanNew(bson->dbrefString))) { - NanAssignPersistent(bson->dbrefConstructor, func); - foundClassesMask |= 0x10; - } else if(functionName->StrictEquals(NanNew(bson->symbolString))) { - NanAssignPersistent(bson->symbolConstructor, func); - foundClassesMask |= 0x20; - } else if(functionName->StrictEquals(NanNew(bson->doubleString))) { - NanAssignPersistent(bson->doubleConstructor, func); - foundClassesMask |= 0x40; - } else if(functionName->StrictEquals(NanNew(bson->timestampString))) { - NanAssignPersistent(bson->timestampConstructor, func); - foundClassesMask |= 0x80; - } else if(functionName->StrictEquals(NanNew(bson->minKeyString))) { - NanAssignPersistent(bson->minKeyConstructor, func); - foundClassesMask |= 0x100; - } else if(functionName->StrictEquals(NanNew(bson->maxKeyString))) { - NanAssignPersistent(bson->maxKeyConstructor, func); - foundClassesMask |= 0x200; - } - } - - // Check if we have the right number of constructors otherwise throw an error - if(foundClassesMask != 0x3ff) { - delete bson; - return NanThrowError("Missing function constructor for either [Long/ObjectID/Binary/Code/DbRef/Symbol/Double/Timestamp/MinKey/MaxKey]"); - } else { - bson->Wrap(args.This()); - NanReturnValue(args.This()); - } - } - else - { - return NanThrowError("No types passed in"); - } - } - else - { - return NanThrowTypeError("Argument passed in must be an array of types"); - } -} - -//------------------------------------------------------------------------------------------------ -//------------------------------------------------------------------------------------------------ -//------------------------------------------------------------------------------------------------ -//------------------------------------------------------------------------------------------------ - -NAN_METHOD(BSON::BSONDeserialize) -{ - NanScope(); - - // Fail if the first argument is not a string or a buffer - if(args.Length() > 1 && !args[0]->IsString() && !Buffer::HasInstance(args[0])) - return NanThrowError("First Argument must be a Buffer or String."); - - // Promote longs - bool promoteLongs = true; - - // If we have an options object - if(args.Length() == 2 && args[1]->IsObject()) { - Local options = args[1]->ToObject(); - - if(options->Has(NanNew("promoteLongs"))) { - promoteLongs = options->Get(NanNew("promoteLongs"))->ToBoolean()->Value(); - } - } - - // Define pointer to data - Local obj = args[0]->ToObject(); - - // Unpack the BSON parser instance - BSON *bson = ObjectWrap::Unwrap(args.This()); - - // If we passed in a buffer, let's unpack it, otherwise let's unpack the string - if(Buffer::HasInstance(obj)) - { -#if NODE_MAJOR_VERSION == 0 && NODE_MINOR_VERSION < 3 - Local buffer = ObjectWrap::Unwrap(obj); - char* data = buffer->data(); - size_t length = buffer->length(); -#else - char* data = Buffer::Data(obj); - size_t length = Buffer::Length(obj); -#endif - - // Validate that we have at least 5 bytes - if(length < 5) return NanThrowError("corrupt bson message < 5 bytes long"); - - try - { - BSONDeserializer deserializer(bson, data, length); - // deserializer.promoteLongs = promoteLongs; - NanReturnValue(deserializer.DeserializeDocument(promoteLongs)); - } - catch(char* exception) - { - Local error = NanNew(exception); - free(exception); - return NanThrowError(error); - } - - } - else - { - // The length of the data for this encoding - ssize_t len = DecodeBytes(args[0], BINARY); - - // Validate that we have at least 5 bytes - if(len < 5) return NanThrowError("corrupt bson message < 5 bytes long"); - - // Let's define the buffer size - char* data = (char *)malloc(len); - if(data == NULL) die("Failed to allocate char buffer for BSON serialization"); - DecodeWrite(data, len, args[0], BINARY); - - try - { - BSONDeserializer deserializer(bson, data, len); - // deserializer.promoteLongs = promoteLongs; - Handle result = deserializer.DeserializeDocument(promoteLongs); - free(data); - NanReturnValue(result); - - } - catch(char* exception) - { - Local error = NanNew(exception); - free(exception); - free(data); - return NanThrowError(error); - } - } -} - -Local BSON::GetSerializeObject(const Handle& argValue) -{ - Local object = argValue->ToObject(); - if(object->Has(NanNew(_toBSONString))) - { - const Local& toBSON = object->Get(NanNew(_toBSONString)); - if(!toBSON->IsFunction()) ThrowAllocatedStringException(64, "toBSON is not a function"); - - Local result = Local::Cast(toBSON)->Call(object, 0, NULL); - if(!result->IsObject()) ThrowAllocatedStringException(64, "toBSON function did not return an object"); - return result->ToObject(); - } - else - { - return object; - } -} - -NAN_METHOD(BSON::BSONSerialize) -{ - NanScope(); - - if(args.Length() == 1 && !args[0]->IsObject()) return NanThrowError("One, two or tree arguments required - [object] or [object, boolean] or [object, boolean, boolean]"); - if(args.Length() == 2 && !args[0]->IsObject() && !args[1]->IsBoolean()) return NanThrowError("One, two or tree arguments required - [object] or [object, boolean] or [object, boolean, boolean]"); - if(args.Length() == 3 && !args[0]->IsObject() && !args[1]->IsBoolean() && !args[2]->IsBoolean()) return NanThrowError("One, two or tree arguments required - [object] or [object, boolean] or [object, boolean, boolean]"); - if(args.Length() == 4 && !args[0]->IsObject() && !args[1]->IsBoolean() && !args[2]->IsBoolean() && !args[3]->IsBoolean()) return NanThrowError("One, two or tree arguments required - [object] or [object, boolean] or [object, boolean, boolean] or [object, boolean, boolean, boolean]"); - if(args.Length() > 4) return NanThrowError("One, two, tree or four arguments required - [object] or [object, boolean] or [object, boolean, boolean] or [object, boolean, boolean, boolean]"); - - // Check if we have an array as the object - if(args[0]->IsArray()) return NanThrowError("Only javascript objects supported"); - - // Unpack the BSON parser instance - BSON *bson = ObjectWrap::Unwrap(args.This()); - - // Calculate the total size of the document in binary form to ensure we only allocate memory once - // With serialize function - bool serializeFunctions = (args.Length() >= 4) && args[3]->BooleanValue(); - - char *serialized_object = NULL; - size_t object_size; - try - { - Local object = bson->GetSerializeObject(args[0]); - - BSONSerializer counter(bson, false, serializeFunctions); - counter.SerializeDocument(object); - object_size = counter.GetSerializeSize(); - - // Allocate the memory needed for the serialization - serialized_object = (char *)malloc(object_size); - if(serialized_object == NULL) die("Failed to allocate memory for object"); - - // Check if we have a boolean value - bool checkKeys = args.Length() >= 3 && args[1]->IsBoolean() && args[1]->BooleanValue(); - BSONSerializer data(bson, checkKeys, serializeFunctions, serialized_object); - data.SerializeDocument(object); - } - catch(char *err_msg) - { - free(serialized_object); - Local error = NanNew(err_msg); - free(err_msg); - return NanThrowError(error); - } - - // If we have 3 arguments - if(args.Length() == 3 || args.Length() == 4) - { - Local buffer = NanNewBufferHandle(serialized_object, object_size); - free(serialized_object); - NanReturnValue(buffer); - } - else - { - Local bin_value = Encode(serialized_object, object_size, BINARY)->ToString(); - free(serialized_object); - NanReturnValue(bin_value); - } -} - -NAN_METHOD(BSON::CalculateObjectSize) -{ - NanScope(); - // Ensure we have a valid object - if(args.Length() == 1 && !args[0]->IsObject()) return NanThrowError("One argument required - [object]"); - if(args.Length() == 2 && !args[0]->IsObject() && !args[1]->IsBoolean()) return NanThrowError("Two arguments required - [object, boolean]"); - if(args.Length() > 3) return NanThrowError("One or two arguments required - [object] or [object, boolean]"); - - // Unpack the BSON parser instance - BSON *bson = ObjectWrap::Unwrap(args.This()); - bool serializeFunctions = (args.Length() >= 2) && args[1]->BooleanValue(); - BSONSerializer countSerializer(bson, false, serializeFunctions); - countSerializer.SerializeDocument(args[0]); - - // Return the object size - NanReturnValue(NanNew((uint32_t) countSerializer.GetSerializeSize())); -} - -NAN_METHOD(BSON::SerializeWithBufferAndIndex) -{ - NanScope(); - - //BSON.serializeWithBufferAndIndex = function serializeWithBufferAndIndex(object, ->, buffer, index) { - // Ensure we have the correct values - if(args.Length() > 5) return NanThrowError("Four or five parameters required [object, boolean, Buffer, int] or [object, boolean, Buffer, int, boolean]"); - if(args.Length() == 4 && !args[0]->IsObject() && !args[1]->IsBoolean() && !Buffer::HasInstance(args[2]) && !args[3]->IsUint32()) return NanThrowError("Four parameters required [object, boolean, Buffer, int]"); - if(args.Length() == 5 && !args[0]->IsObject() && !args[1]->IsBoolean() && !Buffer::HasInstance(args[2]) && !args[3]->IsUint32() && !args[4]->IsBoolean()) return NanThrowError("Four parameters required [object, boolean, Buffer, int, boolean]"); - - uint32_t index; - size_t object_size; - - try - { - BSON *bson = ObjectWrap::Unwrap(args.This()); - - Local obj = args[2]->ToObject(); - char* data = Buffer::Data(obj); - size_t length = Buffer::Length(obj); - - index = args[3]->Uint32Value(); - bool checkKeys = args.Length() >= 4 && args[1]->IsBoolean() && args[1]->BooleanValue(); - bool serializeFunctions = (args.Length() == 5) && args[4]->BooleanValue(); - - BSONSerializer dataSerializer(bson, checkKeys, serializeFunctions, data+index); - dataSerializer.SerializeDocument(bson->GetSerializeObject(args[0])); - object_size = dataSerializer.GetSerializeSize(); - - if(object_size + index > length) return NanThrowError("Serious error - overflowed buffer!!"); - } - catch(char *exception) - { - Local error = NanNew(exception); - free(exception); - return NanThrowError(error); - } - - NanReturnValue(NanNew((uint32_t) (index + object_size - 1))); -} - -NAN_METHOD(BSON::BSONDeserializeStream) -{ - NanScope(); - - // At least 3 arguments required - if(args.Length() < 5) return NanThrowError("Arguments required (Buffer(data), Number(index in data), Number(number of documents to deserialize), Array(results), Number(index in the array), Object(optional))"); - - // If the number of argumets equals 3 - if(args.Length() >= 5) - { - if(!Buffer::HasInstance(args[0])) return NanThrowError("First argument must be Buffer instance"); - if(!args[1]->IsUint32()) return NanThrowError("Second argument must be a positive index number"); - if(!args[2]->IsUint32()) return NanThrowError("Third argument must be a positive number of documents to deserialize"); - if(!args[3]->IsArray()) return NanThrowError("Fourth argument must be an array the size of documents to deserialize"); - if(!args[4]->IsUint32()) return NanThrowError("Sixth argument must be a positive index number"); - } - - // If we have 4 arguments - if(args.Length() == 6 && !args[5]->IsObject()) return NanThrowError("Fifth argument must be an object with options"); - - // Define pointer to data - Local obj = args[0]->ToObject(); - uint32_t numberOfDocuments = args[2]->Uint32Value(); - uint32_t index = args[1]->Uint32Value(); - uint32_t resultIndex = args[4]->Uint32Value(); - bool promoteLongs = true; - - // Check for the value promoteLongs in the options object - if(args.Length() == 6) { - Local options = args[5]->ToObject(); - - // Check if we have the promoteLong variable - if(options->Has(NanNew("promoteLongs"))) { - promoteLongs = options->Get(NanNew("promoteLongs"))->ToBoolean()->Value(); - } - } - - // Unpack the BSON parser instance - BSON *bson = ObjectWrap::Unwrap(args.This()); - - // Unpack the buffer variable -#if NODE_MAJOR_VERSION == 0 && NODE_MINOR_VERSION < 3 - Local buffer = ObjectWrap::Unwrap(obj); - char* data = buffer->data(); - size_t length = buffer->length(); -#else - char* data = Buffer::Data(obj); - size_t length = Buffer::Length(obj); -#endif - - // Fetch the documents - Local documents = args[3]->ToObject(); - - BSONDeserializer deserializer(bson, data+index, length-index); - for(uint32_t i = 0; i < numberOfDocuments; i++) - { - try - { - documents->Set(i + resultIndex, deserializer.DeserializeDocument(promoteLongs)); - } - catch (char* exception) - { - Local error = NanNew(exception); - free(exception); - return NanThrowError(error); - } - } - - // Return new index of parsing - NanReturnValue(NanNew((uint32_t) (index + deserializer.GetSerializeSize()))); -} - -// Exporting function -extern "C" void init(Handle target) -{ - NanScope(); - BSON::Initialize(target); -} - -NODE_MODULE(bson, BSON::Initialize); diff --git a/node_modules/mongodb/node_modules/bson/ext/bson.h b/node_modules/mongodb/node_modules/bson/ext/bson.h deleted file mode 100644 index a7feff7..0000000 --- a/node_modules/mongodb/node_modules/bson/ext/bson.h +++ /dev/null @@ -1,278 +0,0 @@ -//=========================================================================== - -#ifndef BSON_H_ -#define BSON_H_ - -//=========================================================================== - -#ifdef __arm__ -#define USE_MISALIGNED_MEMORY_ACCESS 0 -#else -#define USE_MISALIGNED_MEMORY_ACCESS 1 -#endif - -#include -#include -#include -#include "nan.h" - -using namespace v8; -using namespace node; - -//=========================================================================== - -enum BsonType -{ - BSON_TYPE_NUMBER = 1, - BSON_TYPE_STRING = 2, - BSON_TYPE_OBJECT = 3, - BSON_TYPE_ARRAY = 4, - BSON_TYPE_BINARY = 5, - BSON_TYPE_UNDEFINED = 6, - BSON_TYPE_OID = 7, - BSON_TYPE_BOOLEAN = 8, - BSON_TYPE_DATE = 9, - BSON_TYPE_NULL = 10, - BSON_TYPE_REGEXP = 11, - BSON_TYPE_CODE = 13, - BSON_TYPE_SYMBOL = 14, - BSON_TYPE_CODE_W_SCOPE = 15, - BSON_TYPE_INT = 16, - BSON_TYPE_TIMESTAMP = 17, - BSON_TYPE_LONG = 18, - BSON_TYPE_MAX_KEY = 0x7f, - BSON_TYPE_MIN_KEY = 0xff -}; - -//=========================================================================== - -template class BSONSerializer; - -class BSON : public ObjectWrap { -public: - BSON(); - ~BSON() {} - - static void Initialize(Handle target); - static NAN_METHOD(BSONDeserializeStream); - - // JS based objects - static NAN_METHOD(BSONSerialize); - static NAN_METHOD(BSONDeserialize); - - // Calculate size of function - static NAN_METHOD(CalculateObjectSize); - static NAN_METHOD(SerializeWithBufferAndIndex); - - // Constructor used for creating new BSON objects from C++ - static Persistent constructor_template; - -private: - static NAN_METHOD(New); - static Handle deserialize(BSON *bson, char *data, uint32_t dataLength, uint32_t startIndex, bool is_array_item); - - // BSON type instantiate functions - Persistent longConstructor; - Persistent objectIDConstructor; - Persistent binaryConstructor; - Persistent codeConstructor; - Persistent dbrefConstructor; - Persistent symbolConstructor; - Persistent doubleConstructor; - Persistent timestampConstructor; - Persistent minKeyConstructor; - Persistent maxKeyConstructor; - - // Equality Objects - Persistent longString; - Persistent objectIDString; - Persistent binaryString; - Persistent codeString; - Persistent dbrefString; - Persistent symbolString; - Persistent doubleString; - Persistent timestampString; - Persistent minKeyString; - Persistent maxKeyString; - - // Equality speed up comparison objects - Persistent _bsontypeString; - Persistent _longLowString; - Persistent _longHighString; - Persistent _objectIDidString; - Persistent _binaryPositionString; - Persistent _binarySubTypeString; - Persistent _binaryBufferString; - Persistent _doubleValueString; - Persistent _symbolValueString; - - Persistent _dbRefRefString; - Persistent _dbRefIdRefString; - Persistent _dbRefDbRefString; - Persistent _dbRefNamespaceString; - Persistent _dbRefDbString; - Persistent _dbRefOidString; - - Persistent _codeCodeString; - Persistent _codeScopeString; - Persistent _toBSONString; - - Local GetSerializeObject(const Handle& object); - - template friend class BSONSerializer; - friend class BSONDeserializer; -}; - -//=========================================================================== - -class CountStream -{ -public: - CountStream() : count(0) { } - - void WriteByte(int value) { ++count; } - void WriteByte(const Handle&, const Handle&) { ++count; } - void WriteBool(const Handle& value) { ++count; } - void WriteInt32(int32_t value) { count += 4; } - void WriteInt32(const Handle& value) { count += 4; } - void WriteInt32(const Handle& object, const Handle& key) { count += 4; } - void WriteInt64(int64_t value) { count += 8; } - void WriteInt64(const Handle& value) { count += 8; } - void WriteDouble(double value) { count += 8; } - void WriteDouble(const Handle& value) { count += 8; } - void WriteDouble(const Handle&, const Handle&) { count += 8; } - void WriteUInt32String(uint32_t name) { char buffer[32]; count += sprintf(buffer, "%u", name) + 1; } - void WriteLengthPrefixedString(const Local& value) { count += value->Utf8Length()+5; } - void WriteObjectId(const Handle& object, const Handle& key) { count += 12; } - void WriteString(const Local& value) { count += value->Utf8Length() + 1; } // This returns the number of bytes exclusive of the NULL terminator - void WriteData(const char* data, size_t length) { count += length; } - - void* BeginWriteType() { ++count; return NULL; } - void CommitType(void*, BsonType) { } - void* BeginWriteSize() { count += 4; return NULL; } - void CommitSize(void*) { } - - size_t GetSerializeSize() const { return count; } - - // Do nothing. CheckKey is implemented for DataStream - void CheckKey(const Local&) { } - -private: - size_t count; -}; - -class DataStream -{ -public: - DataStream(char* aDestinationBuffer) : destinationBuffer(aDestinationBuffer), p(aDestinationBuffer) { } - - void WriteByte(int value) { *p++ = value; } - void WriteByte(const Handle& object, const Handle& key) { *p++ = object->Get(key)->Int32Value(); } -#if USE_MISALIGNED_MEMORY_ACCESS - void WriteInt32(int32_t value) { *reinterpret_cast(p) = value; p += 4; } - void WriteInt64(int64_t value) { *reinterpret_cast(p) = value; p += 8; } - void WriteDouble(double value) { *reinterpret_cast(p) = value; p += 8; } -#else - void WriteInt32(int32_t value) { memcpy(p, &value, 4); p += 4; } - void WriteInt64(int64_t value) { memcpy(p, &value, 8); p += 8; } - void WriteDouble(double value) { memcpy(p, &value, 8); p += 8; } -#endif - void WriteBool(const Handle& value) { WriteByte(value->BooleanValue() ? 1 : 0); } - void WriteInt32(const Handle& value) { WriteInt32(value->Int32Value()); } - void WriteInt32(const Handle& object, const Handle& key) { WriteInt32(object->Get(key)); } - void WriteInt64(const Handle& value) { WriteInt64(value->IntegerValue()); } - void WriteDouble(const Handle& value) { WriteDouble(value->NumberValue()); } - void WriteDouble(const Handle& object, const Handle& key) { WriteDouble(object->Get(key)); } - void WriteUInt32String(uint32_t name) { p += sprintf(p, "%u", name) + 1; } - void WriteLengthPrefixedString(const Local& value) { WriteInt32(value->Utf8Length()+1); WriteString(value); } - void WriteObjectId(const Handle& object, const Handle& key); - void WriteString(const Local& value) { p += value->WriteUtf8(p); } // This returns the number of bytes inclusive of the NULL terminator. - void WriteData(const char* data, size_t length) { memcpy(p, data, length); p += length; } - - void* BeginWriteType() { void* returnValue = p; p++; return returnValue; } - void CommitType(void* beginPoint, BsonType value) { *reinterpret_cast(beginPoint) = value; } - void* BeginWriteSize() { void* returnValue = p; p += 4; return returnValue; } - -#if USE_MISALIGNED_MEMORY_ACCESS - void CommitSize(void* beginPoint) { *reinterpret_cast(beginPoint) = (int32_t) (p - (char*) beginPoint); } -#else - void CommitSize(void* beginPoint) { int32_t value = (int32_t) (p - (char*) beginPoint); memcpy(beginPoint, &value, 4); } -#endif - - size_t GetSerializeSize() const { return p - destinationBuffer; } - - void CheckKey(const Local& keyName); - -protected: - char *const destinationBuffer; // base, never changes - char* p; // cursor into buffer -}; - -template class BSONSerializer : public T -{ -private: - typedef T Inherited; - -public: - BSONSerializer(BSON* aBson, bool aCheckKeys, bool aSerializeFunctions) : Inherited(), checkKeys(aCheckKeys), serializeFunctions(aSerializeFunctions), bson(aBson) { } - BSONSerializer(BSON* aBson, bool aCheckKeys, bool aSerializeFunctions, char* parentParam) : Inherited(parentParam), checkKeys(aCheckKeys), serializeFunctions(aSerializeFunctions), bson(aBson) { } - - void SerializeDocument(const Handle& value); - void SerializeArray(const Handle& value); - void SerializeValue(void* typeLocation, const Handle value); - -private: - bool checkKeys; - bool serializeFunctions; - BSON* bson; -}; - -//=========================================================================== - -class BSONDeserializer -{ -public: - BSONDeserializer(BSON* aBson, char* data, size_t length); - BSONDeserializer(BSONDeserializer& parentSerializer, size_t length); - - Handle DeserializeDocument(bool promoteLongs); - - bool HasMoreData() const { return p < pEnd; } - Handle ReadCString(); - uint32_t ReadIntegerString(); - int32_t ReadRegexOptions(); - Local ReadString(); - Local ReadObjectId(); - - unsigned char ReadByte() { return *reinterpret_cast(p++); } -#if USE_MISALIGNED_MEMORY_ACCESS - int32_t ReadInt32() { int32_t returnValue = *reinterpret_cast(p); p += 4; return returnValue; } - uint32_t ReadUInt32() { uint32_t returnValue = *reinterpret_cast(p); p += 4; return returnValue; } - int64_t ReadInt64() { int64_t returnValue = *reinterpret_cast(p); p += 8; return returnValue; } - double ReadDouble() { double returnValue = *reinterpret_cast(p); p += 8; return returnValue; } -#else - int32_t ReadInt32() { int32_t returnValue; memcpy(&returnValue, p, 4); p += 4; return returnValue; } - uint32_t ReadUInt32() { uint32_t returnValue; memcpy(&returnValue, p, 4); p += 4; return returnValue; } - int64_t ReadInt64() { int64_t returnValue; memcpy(&returnValue, p, 8); p += 8; return returnValue; } - double ReadDouble() { double returnValue; memcpy(&returnValue, p, 8); p += 8; return returnValue; } -#endif - - size_t GetSerializeSize() const { return p - pStart; } - -private: - Handle DeserializeArray(bool promoteLongs); - Handle DeserializeValue(BsonType type, bool promoteLongs); - Handle DeserializeDocumentInternal(bool promoteLongs); - Handle DeserializeArrayInternal(bool promoteLongs); - - BSON* bson; - char* const pStart; - char* p; - char* const pEnd; -}; - -//=========================================================================== - -#endif // BSON_H_ - -//=========================================================================== diff --git a/node_modules/mongodb/node_modules/bson/ext/index.js b/node_modules/mongodb/node_modules/bson/ext/index.js deleted file mode 100644 index af4d9a5..0000000 --- a/node_modules/mongodb/node_modules/bson/ext/index.js +++ /dev/null @@ -1,40 +0,0 @@ -var bson = null; - -try { - // Load the precompiled win32 binary - if(process.platform == "win32" && process.arch == "x64") { - bson = require('./win32/x64/bson'); - } else if(process.platform == "win32" && process.arch == "ia32") { - bson = require('./win32/ia32/bson'); - } else { - bson = require('../build/Release/bson'); - } -} catch(err) { - // Attempt to load the release bson version - try { - bson = require('../build/Release/bson'); - } catch (err) { - console.error("js-bson: Failed to load c++ bson extension, using pure JS version"); - bson = require('../lib/bson/bson'); - } -} - -exports.BSON = bson.BSON; -exports.Long = require('../lib/bson/long').Long; -exports.ObjectID = require('../lib/bson/objectid').ObjectID; -exports.DBRef = require('../lib/bson/db_ref').DBRef; -exports.Code = require('../lib/bson/code').Code; -exports.Timestamp = require('../lib/bson/timestamp').Timestamp; -exports.Binary = require('../lib/bson/binary').Binary; -exports.Double = require('../lib/bson/double').Double; -exports.MaxKey = require('../lib/bson/max_key').MaxKey; -exports.MinKey = require('../lib/bson/min_key').MinKey; -exports.Symbol = require('../lib/bson/symbol').Symbol; - -// Just add constants tot he Native BSON parser -exports.BSON.BSON_BINARY_SUBTYPE_DEFAULT = 0; -exports.BSON.BSON_BINARY_SUBTYPE_FUNCTION = 1; -exports.BSON.BSON_BINARY_SUBTYPE_BYTE_ARRAY = 2; -exports.BSON.BSON_BINARY_SUBTYPE_UUID = 3; -exports.BSON.BSON_BINARY_SUBTYPE_MD5 = 4; -exports.BSON.BSON_BINARY_SUBTYPE_USER_DEFINED = 128; diff --git a/node_modules/mongodb/node_modules/bson/ext/win32/ia32/bson.node b/node_modules/mongodb/node_modules/bson/ext/win32/ia32/bson.node deleted file mode 100644 index 7f54835e7d9cdef60f29f9a6a6397eedc586c535..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 113664 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 255) throw new Error("only accepts number in a valid unsigned byte range 0-255"); - - // Decode the byte value once - var decoded_byte = null; - if(typeof byte_value == 'string') { - decoded_byte = byte_value.charCodeAt(0); - } else if(byte_value['length'] != null) { - decoded_byte = byte_value[0]; - } else { - decoded_byte = byte_value; - } - - if(this.buffer.length > this.position) { - this.buffer[this.position++] = decoded_byte; - } else { - if(typeof Buffer != 'undefined' && Buffer.isBuffer(this.buffer)) { - // Create additional overflow buffer - var buffer = new Buffer(Binary.BUFFER_SIZE + this.buffer.length); - // Combine the two buffers together - this.buffer.copy(buffer, 0, 0, this.buffer.length); - this.buffer = buffer; - this.buffer[this.position++] = decoded_byte; - } else { - var buffer = null; - // Create a new buffer (typed or normal array) - if(Object.prototype.toString.call(this.buffer) == '[object Uint8Array]') { - buffer = new Uint8Array(new ArrayBuffer(Binary.BUFFER_SIZE + this.buffer.length)); - } else { - buffer = new Array(Binary.BUFFER_SIZE + this.buffer.length); - } - - // We need to copy all the content to the new array - for(var i = 0; i < this.buffer.length; i++) { - buffer[i] = this.buffer[i]; - } - - // Reassign the buffer - this.buffer = buffer; - // Write the byte - this.buffer[this.position++] = decoded_byte; - } - } -}; - -/** - * Writes a buffer or string to the binary. - * - * @param {Buffer|String} string a string or buffer to be written to the Binary BSON object. - * @param {Number} offset specify the binary of where to write the content. - * @api public - */ -Binary.prototype.write = function write(string, offset) { - offset = typeof offset == 'number' ? offset : this.position; - - // If the buffer is to small let's extend the buffer - if(this.buffer.length < offset + string.length) { - var buffer = null; - // If we are in node.js - if(typeof Buffer != 'undefined' && Buffer.isBuffer(this.buffer)) { - buffer = new Buffer(this.buffer.length + string.length); - this.buffer.copy(buffer, 0, 0, this.buffer.length); - } else if(Object.prototype.toString.call(this.buffer) == '[object Uint8Array]') { - // Create a new buffer - buffer = new Uint8Array(new ArrayBuffer(this.buffer.length + string.length)) - // Copy the content - for(var i = 0; i < this.position; i++) { - buffer[i] = this.buffer[i]; - } - } - - // Assign the new buffer - this.buffer = buffer; - } - - if(typeof Buffer != 'undefined' && Buffer.isBuffer(string) && Buffer.isBuffer(this.buffer)) { - string.copy(this.buffer, offset, 0, string.length); - this.position = (offset + string.length) > this.position ? (offset + string.length) : this.position; - // offset = string.length - } else if(typeof Buffer != 'undefined' && typeof string == 'string' && Buffer.isBuffer(this.buffer)) { - this.buffer.write(string, 'binary', offset); - this.position = (offset + string.length) > this.position ? (offset + string.length) : this.position; - // offset = string.length; - } else if(Object.prototype.toString.call(string) == '[object Uint8Array]' - || Object.prototype.toString.call(string) == '[object Array]' && typeof string != 'string') { - for(var i = 0; i < string.length; i++) { - this.buffer[offset++] = string[i]; - } - - this.position = offset > this.position ? offset : this.position; - } else if(typeof string == 'string') { - for(var i = 0; i < string.length; i++) { - this.buffer[offset++] = string.charCodeAt(i); - } - - this.position = offset > this.position ? offset : this.position; - } -}; - -/** - * Reads **length** bytes starting at **position**. - * - * @param {Number} position read from the given position in the Binary. - * @param {Number} length the number of bytes to read. - * @return {Buffer} - * @api public - */ -Binary.prototype.read = function read(position, length) { - length = length && length > 0 - ? length - : this.position; - - // Let's return the data based on the type we have - if(this.buffer['slice']) { - return this.buffer.slice(position, position + length); - } else { - // Create a buffer to keep the result - var buffer = typeof Uint8Array != 'undefined' ? new Uint8Array(new ArrayBuffer(length)) : new Array(length); - for(var i = 0; i < length; i++) { - buffer[i] = this.buffer[position++]; - } - } - // Return the buffer - return buffer; -}; - -/** - * Returns the value of this binary as a string. - * - * @return {String} - * @api public - */ -Binary.prototype.value = function value(asRaw) { - asRaw = asRaw == null ? false : asRaw; - - // Optimize to serialize for the situation where the data == size of buffer - if(asRaw && typeof Buffer != 'undefined' && Buffer.isBuffer(this.buffer) && this.buffer.length == this.position) - return this.buffer; - - // If it's a node.js buffer object - if(typeof Buffer != 'undefined' && Buffer.isBuffer(this.buffer)) { - return asRaw ? this.buffer.slice(0, this.position) : this.buffer.toString('binary', 0, this.position); - } else { - if(asRaw) { - // we support the slice command use it - if(this.buffer['slice'] != null) { - return this.buffer.slice(0, this.position); - } else { - // Create a new buffer to copy content to - var newBuffer = Object.prototype.toString.call(this.buffer) == '[object Uint8Array]' ? new Uint8Array(new ArrayBuffer(this.position)) : new Array(this.position); - // Copy content - for(var i = 0; i < this.position; i++) { - newBuffer[i] = this.buffer[i]; - } - // Return the buffer - return newBuffer; - } - } else { - return convertArraytoUtf8BinaryString(this.buffer, 0, this.position); - } - } -}; - -/** - * Length. - * - * @return {Number} the length of the binary. - * @api public - */ -Binary.prototype.length = function length() { - return this.position; -}; - -/** - * @ignore - * @api private - */ -Binary.prototype.toJSON = function() { - return this.buffer != null ? this.buffer.toString('base64') : ''; -} - -/** - * @ignore - * @api private - */ -Binary.prototype.toString = function(format) { - return this.buffer != null ? this.buffer.slice(0, this.position).toString(format) : ''; -} - -Binary.BUFFER_SIZE = 256; - -/** - * Default BSON type - * - * @classconstant SUBTYPE_DEFAULT - **/ -Binary.SUBTYPE_DEFAULT = 0; -/** - * Function BSON type - * - * @classconstant SUBTYPE_DEFAULT - **/ -Binary.SUBTYPE_FUNCTION = 1; -/** - * Byte Array BSON type - * - * @classconstant SUBTYPE_DEFAULT - **/ -Binary.SUBTYPE_BYTE_ARRAY = 2; -/** - * OLD UUID BSON type - * - * @classconstant SUBTYPE_DEFAULT - **/ -Binary.SUBTYPE_UUID_OLD = 3; -/** - * UUID BSON type - * - * @classconstant SUBTYPE_DEFAULT - **/ -Binary.SUBTYPE_UUID = 4; -/** - * MD5 BSON type - * - * @classconstant SUBTYPE_DEFAULT - **/ -Binary.SUBTYPE_MD5 = 5; -/** - * User BSON type - * - * @classconstant SUBTYPE_DEFAULT - **/ -Binary.SUBTYPE_USER_DEFINED = 128; - -/** - * Expose. - */ -exports.Binary = Binary; - diff --git a/node_modules/mongodb/node_modules/bson/lib/bson/binary_parser.js b/node_modules/mongodb/node_modules/bson/lib/bson/binary_parser.js deleted file mode 100644 index d2fc811..0000000 --- a/node_modules/mongodb/node_modules/bson/lib/bson/binary_parser.js +++ /dev/null @@ -1,385 +0,0 @@ -/** - * Binary Parser. - * Jonas Raoni Soares Silva - * http://jsfromhell.com/classes/binary-parser [v1.0] - */ -var chr = String.fromCharCode; - -var maxBits = []; -for (var i = 0; i < 64; i++) { - maxBits[i] = Math.pow(2, i); -} - -function BinaryParser (bigEndian, allowExceptions) { - if(!(this instanceof BinaryParser)) return new BinaryParser(bigEndian, allowExceptions); - - this.bigEndian = bigEndian; - this.allowExceptions = allowExceptions; -}; - -BinaryParser.warn = function warn (msg) { - if (this.allowExceptions) { - throw new Error(msg); - } - - return 1; -}; - -BinaryParser.decodeFloat = function decodeFloat (data, precisionBits, exponentBits) { - var b = new this.Buffer(this.bigEndian, data); - - b.checkBuffer(precisionBits + exponentBits + 1); - - var bias = maxBits[exponentBits - 1] - 1 - , signal = b.readBits(precisionBits + exponentBits, 1) - , exponent = b.readBits(precisionBits, exponentBits) - , significand = 0 - , divisor = 2 - , curByte = b.buffer.length + (-precisionBits >> 3) - 1; - - do { - for (var byteValue = b.buffer[ ++curByte ], startBit = precisionBits % 8 || 8, mask = 1 << startBit; mask >>= 1; ( byteValue & mask ) && ( significand += 1 / divisor ), divisor *= 2 ); - } while (precisionBits -= startBit); - - return exponent == ( bias << 1 ) + 1 ? significand ? NaN : signal ? -Infinity : +Infinity : ( 1 + signal * -2 ) * ( exponent || significand ? !exponent ? Math.pow( 2, -bias + 1 ) * significand : Math.pow( 2, exponent - bias ) * ( 1 + significand ) : 0 ); -}; - -BinaryParser.decodeInt = function decodeInt (data, bits, signed, forceBigEndian) { - var b = new this.Buffer(this.bigEndian || forceBigEndian, data) - , x = b.readBits(0, bits) - , max = maxBits[bits]; //max = Math.pow( 2, bits ); - - return signed && x >= max / 2 - ? x - max - : x; -}; - -BinaryParser.encodeFloat = function encodeFloat (data, precisionBits, exponentBits) { - var bias = maxBits[exponentBits - 1] - 1 - , minExp = -bias + 1 - , maxExp = bias - , minUnnormExp = minExp - precisionBits - , n = parseFloat(data) - , status = isNaN(n) || n == -Infinity || n == +Infinity ? n : 0 - , exp = 0 - , len = 2 * bias + 1 + precisionBits + 3 - , bin = new Array(len) - , signal = (n = status !== 0 ? 0 : n) < 0 - , intPart = Math.floor(n = Math.abs(n)) - , floatPart = n - intPart - , lastBit - , rounded - , result - , i - , j; - - for (i = len; i; bin[--i] = 0); - - for (i = bias + 2; intPart && i; bin[--i] = intPart % 2, intPart = Math.floor(intPart / 2)); - - for (i = bias + 1; floatPart > 0 && i; (bin[++i] = ((floatPart *= 2) >= 1) - 0 ) && --floatPart); - - for (i = -1; ++i < len && !bin[i];); - - if (bin[(lastBit = precisionBits - 1 + (i = (exp = bias + 1 - i) >= minExp && exp <= maxExp ? i + 1 : bias + 1 - (exp = minExp - 1))) + 1]) { - if (!(rounded = bin[lastBit])) { - for (j = lastBit + 2; !rounded && j < len; rounded = bin[j++]); - } - - for (j = lastBit + 1; rounded && --j >= 0; (bin[j] = !bin[j] - 0) && (rounded = 0)); - } - - for (i = i - 2 < 0 ? -1 : i - 3; ++i < len && !bin[i];); - - if ((exp = bias + 1 - i) >= minExp && exp <= maxExp) { - ++i; - } else if (exp < minExp) { - exp != bias + 1 - len && exp < minUnnormExp && this.warn("encodeFloat::float underflow"); - i = bias + 1 - (exp = minExp - 1); - } - - if (intPart || status !== 0) { - this.warn(intPart ? "encodeFloat::float overflow" : "encodeFloat::" + status); - exp = maxExp + 1; - i = bias + 2; - - if (status == -Infinity) { - signal = 1; - } else if (isNaN(status)) { - bin[i] = 1; - } - } - - for (n = Math.abs(exp + bias), j = exponentBits + 1, result = ""; --j; result = (n % 2) + result, n = n >>= 1); - - for (n = 0, j = 0, i = (result = (signal ? "1" : "0") + result + bin.slice(i, i + precisionBits).join("")).length, r = []; i; j = (j + 1) % 8) { - n += (1 << j) * result.charAt(--i); - if (j == 7) { - r[r.length] = String.fromCharCode(n); - n = 0; - } - } - - r[r.length] = n - ? String.fromCharCode(n) - : ""; - - return (this.bigEndian ? r.reverse() : r).join(""); -}; - -BinaryParser.encodeInt = function encodeInt (data, bits, signed, forceBigEndian) { - var max = maxBits[bits]; - - if (data >= max || data < -(max / 2)) { - this.warn("encodeInt::overflow"); - data = 0; - } - - if (data < 0) { - data += max; - } - - for (var r = []; data; r[r.length] = String.fromCharCode(data % 256), data = Math.floor(data / 256)); - - for (bits = -(-bits >> 3) - r.length; bits--; r[r.length] = "\0"); - - return ((this.bigEndian || forceBigEndian) ? r.reverse() : r).join(""); -}; - -BinaryParser.toSmall = function( data ){ return this.decodeInt( data, 8, true ); }; -BinaryParser.fromSmall = function( data ){ return this.encodeInt( data, 8, true ); }; -BinaryParser.toByte = function( data ){ return this.decodeInt( data, 8, false ); }; -BinaryParser.fromByte = function( data ){ return this.encodeInt( data, 8, false ); }; -BinaryParser.toShort = function( data ){ return this.decodeInt( data, 16, true ); }; -BinaryParser.fromShort = function( data ){ return this.encodeInt( data, 16, true ); }; -BinaryParser.toWord = function( data ){ return this.decodeInt( data, 16, false ); }; -BinaryParser.fromWord = function( data ){ return this.encodeInt( data, 16, false ); }; -BinaryParser.toInt = function( data ){ return this.decodeInt( data, 32, true ); }; -BinaryParser.fromInt = function( data ){ return this.encodeInt( data, 32, true ); }; -BinaryParser.toLong = function( data ){ return this.decodeInt( data, 64, true ); }; -BinaryParser.fromLong = function( data ){ return this.encodeInt( data, 64, true ); }; -BinaryParser.toDWord = function( data ){ return this.decodeInt( data, 32, false ); }; -BinaryParser.fromDWord = function( data ){ return this.encodeInt( data, 32, false ); }; -BinaryParser.toQWord = function( data ){ return this.decodeInt( data, 64, true ); }; -BinaryParser.fromQWord = function( data ){ return this.encodeInt( data, 64, true ); }; -BinaryParser.toFloat = function( data ){ return this.decodeFloat( data, 23, 8 ); }; -BinaryParser.fromFloat = function( data ){ return this.encodeFloat( data, 23, 8 ); }; -BinaryParser.toDouble = function( data ){ return this.decodeFloat( data, 52, 11 ); }; -BinaryParser.fromDouble = function( data ){ return this.encodeFloat( data, 52, 11 ); }; - -// Factor out the encode so it can be shared by add_header and push_int32 -BinaryParser.encode_int32 = function encode_int32 (number, asArray) { - var a, b, c, d, unsigned; - unsigned = (number < 0) ? (number + 0x100000000) : number; - a = Math.floor(unsigned / 0xffffff); - unsigned &= 0xffffff; - b = Math.floor(unsigned / 0xffff); - unsigned &= 0xffff; - c = Math.floor(unsigned / 0xff); - unsigned &= 0xff; - d = Math.floor(unsigned); - return asArray ? [chr(a), chr(b), chr(c), chr(d)] : chr(a) + chr(b) + chr(c) + chr(d); -}; - -BinaryParser.encode_int64 = function encode_int64 (number) { - var a, b, c, d, e, f, g, h, unsigned; - unsigned = (number < 0) ? (number + 0x10000000000000000) : number; - a = Math.floor(unsigned / 0xffffffffffffff); - unsigned &= 0xffffffffffffff; - b = Math.floor(unsigned / 0xffffffffffff); - unsigned &= 0xffffffffffff; - c = Math.floor(unsigned / 0xffffffffff); - unsigned &= 0xffffffffff; - d = Math.floor(unsigned / 0xffffffff); - unsigned &= 0xffffffff; - e = Math.floor(unsigned / 0xffffff); - unsigned &= 0xffffff; - f = Math.floor(unsigned / 0xffff); - unsigned &= 0xffff; - g = Math.floor(unsigned / 0xff); - unsigned &= 0xff; - h = Math.floor(unsigned); - return chr(a) + chr(b) + chr(c) + chr(d) + chr(e) + chr(f) + chr(g) + chr(h); -}; - -/** - * UTF8 methods - */ - -// Take a raw binary string and return a utf8 string -BinaryParser.decode_utf8 = function decode_utf8 (binaryStr) { - var len = binaryStr.length - , decoded = '' - , i = 0 - , c = 0 - , c1 = 0 - , c2 = 0 - , c3; - - while (i < len) { - c = binaryStr.charCodeAt(i); - if (c < 128) { - decoded += String.fromCharCode(c); - i++; - } else if ((c > 191) && (c < 224)) { - c2 = binaryStr.charCodeAt(i+1); - decoded += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); - i += 2; - } else { - c2 = binaryStr.charCodeAt(i+1); - c3 = binaryStr.charCodeAt(i+2); - decoded += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); - i += 3; - } - } - - return decoded; -}; - -// Encode a cstring -BinaryParser.encode_cstring = function encode_cstring (s) { - return unescape(encodeURIComponent(s)) + BinaryParser.fromByte(0); -}; - -// Take a utf8 string and return a binary string -BinaryParser.encode_utf8 = function encode_utf8 (s) { - var a = "" - , c; - - for (var n = 0, len = s.length; n < len; n++) { - c = s.charCodeAt(n); - - if (c < 128) { - a += String.fromCharCode(c); - } else if ((c > 127) && (c < 2048)) { - a += String.fromCharCode((c>>6) | 192) ; - a += String.fromCharCode((c&63) | 128); - } else { - a += String.fromCharCode((c>>12) | 224); - a += String.fromCharCode(((c>>6) & 63) | 128); - a += String.fromCharCode((c&63) | 128); - } - } - - return a; -}; - -BinaryParser.hprint = function hprint (s) { - var number; - - for (var i = 0, len = s.length; i < len; i++) { - if (s.charCodeAt(i) < 32) { - number = s.charCodeAt(i) <= 15 - ? "0" + s.charCodeAt(i).toString(16) - : s.charCodeAt(i).toString(16); - process.stdout.write(number + " ") - } else { - number = s.charCodeAt(i) <= 15 - ? "0" + s.charCodeAt(i).toString(16) - : s.charCodeAt(i).toString(16); - process.stdout.write(number + " ") - } - } - - process.stdout.write("\n\n"); -}; - -BinaryParser.ilprint = function hprint (s) { - var number; - - for (var i = 0, len = s.length; i < len; i++) { - if (s.charCodeAt(i) < 32) { - number = s.charCodeAt(i) <= 15 - ? "0" + s.charCodeAt(i).toString(10) - : s.charCodeAt(i).toString(10); - - require('util').debug(number+' : '); - } else { - number = s.charCodeAt(i) <= 15 - ? "0" + s.charCodeAt(i).toString(10) - : s.charCodeAt(i).toString(10); - require('util').debug(number+' : '+ s.charAt(i)); - } - } -}; - -BinaryParser.hlprint = function hprint (s) { - var number; - - for (var i = 0, len = s.length; i < len; i++) { - if (s.charCodeAt(i) < 32) { - number = s.charCodeAt(i) <= 15 - ? "0" + s.charCodeAt(i).toString(16) - : s.charCodeAt(i).toString(16); - require('util').debug(number+' : '); - } else { - number = s.charCodeAt(i) <= 15 - ? "0" + s.charCodeAt(i).toString(16) - : s.charCodeAt(i).toString(16); - require('util').debug(number+' : '+ s.charAt(i)); - } - } -}; - -/** - * BinaryParser buffer constructor. - */ -function BinaryParserBuffer (bigEndian, buffer) { - this.bigEndian = bigEndian || 0; - this.buffer = []; - this.setBuffer(buffer); -}; - -BinaryParserBuffer.prototype.setBuffer = function setBuffer (data) { - var l, i, b; - - if (data) { - i = l = data.length; - b = this.buffer = new Array(l); - for (; i; b[l - i] = data.charCodeAt(--i)); - this.bigEndian && b.reverse(); - } -}; - -BinaryParserBuffer.prototype.hasNeededBits = function hasNeededBits (neededBits) { - return this.buffer.length >= -(-neededBits >> 3); -}; - -BinaryParserBuffer.prototype.checkBuffer = function checkBuffer (neededBits) { - if (!this.hasNeededBits(neededBits)) { - throw new Error("checkBuffer::missing bytes"); - } -}; - -BinaryParserBuffer.prototype.readBits = function readBits (start, length) { - //shl fix: Henri Torgemane ~1996 (compressed by Jonas Raoni) - - function shl (a, b) { - for (; b--; a = ((a %= 0x7fffffff + 1) & 0x40000000) == 0x40000000 ? a * 2 : (a - 0x40000000) * 2 + 0x7fffffff + 1); - return a; - } - - if (start < 0 || length <= 0) { - return 0; - } - - this.checkBuffer(start + length); - - var offsetLeft - , offsetRight = start % 8 - , curByte = this.buffer.length - ( start >> 3 ) - 1 - , lastByte = this.buffer.length + ( -( start + length ) >> 3 ) - , diff = curByte - lastByte - , sum = ((this.buffer[ curByte ] >> offsetRight) & ((1 << (diff ? 8 - offsetRight : length)) - 1)) + (diff && (offsetLeft = (start + length) % 8) ? (this.buffer[lastByte++] & ((1 << offsetLeft) - 1)) << (diff-- << 3) - offsetRight : 0); - - for(; diff; sum += shl(this.buffer[lastByte++], (diff-- << 3) - offsetRight)); - - return sum; -}; - -/** - * Expose. - */ -BinaryParser.Buffer = BinaryParserBuffer; - -exports.BinaryParser = BinaryParser; diff --git a/node_modules/mongodb/node_modules/bson/lib/bson/bson.js b/node_modules/mongodb/node_modules/bson/lib/bson/bson.js deleted file mode 100644 index e0590e8..0000000 --- a/node_modules/mongodb/node_modules/bson/lib/bson/bson.js +++ /dev/null @@ -1,1573 +0,0 @@ -var Long = require('./long').Long - , Double = require('./double').Double - , Timestamp = require('./timestamp').Timestamp - , ObjectID = require('./objectid').ObjectID - , Symbol = require('./symbol').Symbol - , Code = require('./code').Code - , MinKey = require('./min_key').MinKey - , MaxKey = require('./max_key').MaxKey - , DBRef = require('./db_ref').DBRef - , Binary = require('./binary').Binary - , BinaryParser = require('./binary_parser').BinaryParser - , writeIEEE754 = require('./float_parser').writeIEEE754 - , readIEEE754 = require('./float_parser').readIEEE754 - -// To ensure that 0.4 of node works correctly -var isDate = function isDate(d) { - return typeof d === 'object' && Object.prototype.toString.call(d) === '[object Date]'; -} - -/** - * Create a new BSON instance - * - * @class Represents the BSON Parser - * @return {BSON} instance of BSON Parser. - */ -function BSON () {}; - -/** - * @ignore - * @api private - */ -// BSON MAX VALUES -BSON.BSON_INT32_MAX = 0x7FFFFFFF; -BSON.BSON_INT32_MIN = -0x80000000; - -BSON.BSON_INT64_MAX = Math.pow(2, 63) - 1; -BSON.BSON_INT64_MIN = -Math.pow(2, 63); - -// JS MAX PRECISE VALUES -BSON.JS_INT_MAX = 0x20000000000000; // Any integer up to 2^53 can be precisely represented by a double. -BSON.JS_INT_MIN = -0x20000000000000; // Any integer down to -2^53 can be precisely represented by a double. - -// Internal long versions -var JS_INT_MAX_LONG = Long.fromNumber(0x20000000000000); // Any integer up to 2^53 can be precisely represented by a double. -var JS_INT_MIN_LONG = Long.fromNumber(-0x20000000000000); // Any integer down to -2^53 can be precisely represented by a double. - -/** - * Number BSON Type - * - * @classconstant BSON_DATA_NUMBER - **/ -BSON.BSON_DATA_NUMBER = 1; -/** - * String BSON Type - * - * @classconstant BSON_DATA_STRING - **/ -BSON.BSON_DATA_STRING = 2; -/** - * Object BSON Type - * - * @classconstant BSON_DATA_OBJECT - **/ -BSON.BSON_DATA_OBJECT = 3; -/** - * Array BSON Type - * - * @classconstant BSON_DATA_ARRAY - **/ -BSON.BSON_DATA_ARRAY = 4; -/** - * Binary BSON Type - * - * @classconstant BSON_DATA_BINARY - **/ -BSON.BSON_DATA_BINARY = 5; -/** - * Binary BSON Type - * - * @classconstant BSON_DATA_UNDEFINED - **/ -BSON.BSON_DATA_UNDEFINED = 6; -/** - * ObjectID BSON Type - * - * @classconstant BSON_DATA_OID - **/ -BSON.BSON_DATA_OID = 7; -/** - * Boolean BSON Type - * - * @classconstant BSON_DATA_BOOLEAN - **/ -BSON.BSON_DATA_BOOLEAN = 8; -/** - * Date BSON Type - * - * @classconstant BSON_DATA_DATE - **/ -BSON.BSON_DATA_DATE = 9; -/** - * null BSON Type - * - * @classconstant BSON_DATA_NULL - **/ -BSON.BSON_DATA_NULL = 10; -/** - * RegExp BSON Type - * - * @classconstant BSON_DATA_REGEXP - **/ -BSON.BSON_DATA_REGEXP = 11; -/** - * Code BSON Type - * - * @classconstant BSON_DATA_CODE - **/ -BSON.BSON_DATA_CODE = 13; -/** - * Symbol BSON Type - * - * @classconstant BSON_DATA_SYMBOL - **/ -BSON.BSON_DATA_SYMBOL = 14; -/** - * Code with Scope BSON Type - * - * @classconstant BSON_DATA_CODE_W_SCOPE - **/ -BSON.BSON_DATA_CODE_W_SCOPE = 15; -/** - * 32 bit Integer BSON Type - * - * @classconstant BSON_DATA_INT - **/ -BSON.BSON_DATA_INT = 16; -/** - * Timestamp BSON Type - * - * @classconstant BSON_DATA_TIMESTAMP - **/ -BSON.BSON_DATA_TIMESTAMP = 17; -/** - * Long BSON Type - * - * @classconstant BSON_DATA_LONG - **/ -BSON.BSON_DATA_LONG = 18; -/** - * MinKey BSON Type - * - * @classconstant BSON_DATA_MIN_KEY - **/ -BSON.BSON_DATA_MIN_KEY = 0xff; -/** - * MaxKey BSON Type - * - * @classconstant BSON_DATA_MAX_KEY - **/ -BSON.BSON_DATA_MAX_KEY = 0x7f; - -/** - * Binary Default Type - * - * @classconstant BSON_BINARY_SUBTYPE_DEFAULT - **/ -BSON.BSON_BINARY_SUBTYPE_DEFAULT = 0; -/** - * Binary Function Type - * - * @classconstant BSON_BINARY_SUBTYPE_FUNCTION - **/ -BSON.BSON_BINARY_SUBTYPE_FUNCTION = 1; -/** - * Binary Byte Array Type - * - * @classconstant BSON_BINARY_SUBTYPE_BYTE_ARRAY - **/ -BSON.BSON_BINARY_SUBTYPE_BYTE_ARRAY = 2; -/** - * Binary UUID Type - * - * @classconstant BSON_BINARY_SUBTYPE_UUID - **/ -BSON.BSON_BINARY_SUBTYPE_UUID = 3; -/** - * Binary MD5 Type - * - * @classconstant BSON_BINARY_SUBTYPE_MD5 - **/ -BSON.BSON_BINARY_SUBTYPE_MD5 = 4; -/** - * Binary User Defined Type - * - * @classconstant BSON_BINARY_SUBTYPE_USER_DEFINED - **/ -BSON.BSON_BINARY_SUBTYPE_USER_DEFINED = 128; - -/** - * Calculate the bson size for a passed in Javascript object. - * - * @param {Object} object the Javascript object to calculate the BSON byte size for. - * @param {Boolean} [serializeFunctions] serialize all functions in the object **(default:false)**. - * @return {Number} returns the number of bytes the BSON object will take up. - * @api public - */ -BSON.calculateObjectSize = function calculateObjectSize(object, serializeFunctions) { - var totalLength = (4 + 1); - - if(Array.isArray(object)) { - for(var i = 0; i < object.length; i++) { - totalLength += calculateElement(i.toString(), object[i], serializeFunctions) - } - } else { - // If we have toBSON defined, override the current object - if(object.toBSON) { - object = object.toBSON(); - } - - // Calculate size - for(var key in object) { - totalLength += calculateElement(key, object[key], serializeFunctions) - } - } - - return totalLength; -} - -/** - * @ignore - * @api private - */ -function calculateElement(name, value, serializeFunctions) { - var isBuffer = typeof Buffer !== 'undefined'; - - // If we have toBSON defined, override the current object - if(value && value.toBSON){ - value = value.toBSON(); - } - - switch(typeof value) { - case 'string': - return 1 + (!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1 + 4 + (!isBuffer ? numberOfBytes(value) : Buffer.byteLength(value, 'utf8')) + 1; - case 'number': - if(Math.floor(value) === value && value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) { - if(value >= BSON.BSON_INT32_MIN && value <= BSON.BSON_INT32_MAX) { // 32 bit - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (4 + 1); - } else { - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (8 + 1); - } - } else { // 64 bit - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (8 + 1); - } - case 'undefined': - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (1); - case 'boolean': - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (1 + 1); - case 'object': - if(value == null || value instanceof MinKey || value instanceof MaxKey || value['_bsontype'] == 'MinKey' || value['_bsontype'] == 'MaxKey') { - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (1); - } else if(value instanceof ObjectID || value['_bsontype'] == 'ObjectID') { - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (12 + 1); - } else if(value instanceof Date || isDate(value)) { - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (8 + 1); - } else if(typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) { - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (1 + 4 + 1) + value.length; - } else if(value instanceof Long || value instanceof Double || value instanceof Timestamp - || value['_bsontype'] == 'Long' || value['_bsontype'] == 'Double' || value['_bsontype'] == 'Timestamp') { - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (8 + 1); - } else if(value instanceof Code || value['_bsontype'] == 'Code') { - // Calculate size depending on the availability of a scope - if(value.scope != null && Object.keys(value.scope).length > 0) { - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + 4 + 4 + (!isBuffer ? numberOfBytes(value.code.toString()) : Buffer.byteLength(value.code.toString(), 'utf8')) + 1 + BSON.calculateObjectSize(value.scope, serializeFunctions); - } else { - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + 4 + (!isBuffer ? numberOfBytes(value.code.toString()) : Buffer.byteLength(value.code.toString(), 'utf8')) + 1; - } - } else if(value instanceof Binary || value['_bsontype'] == 'Binary') { - // Check what kind of subtype we have - if(value.sub_type == Binary.SUBTYPE_BYTE_ARRAY) { - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (value.position + 1 + 4 + 1 + 4); - } else { - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + (value.position + 1 + 4 + 1); - } - } else if(value instanceof Symbol || value['_bsontype'] == 'Symbol') { - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + ((!isBuffer ? numberOfBytes(value.value) : Buffer.byteLength(value.value, 'utf8')) + 4 + 1 + 1); - } else if(value instanceof DBRef || value['_bsontype'] == 'DBRef') { - // Set up correct object for serialization - var ordered_values = { - '$ref': value.namespace - , '$id' : value.oid - }; - - // Add db reference if it exists - if(null != value.db) { - ordered_values['$db'] = value.db; - } - - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + BSON.calculateObjectSize(ordered_values, serializeFunctions); - } else if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]') { - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + (!isBuffer ? numberOfBytes(value.source) : Buffer.byteLength(value.source, 'utf8')) + 1 - + (value.global ? 1 : 0) + (value.ignoreCase ? 1 : 0) + (value.multiline ? 1 : 0) + 1 - } else { - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + BSON.calculateObjectSize(value, serializeFunctions) + 1; - } - case 'function': - // WTF for 0.4.X where typeof /someregexp/ === 'function' - if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]' || String.call(value) == '[object RegExp]') { - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + (!isBuffer ? numberOfBytes(value.source) : Buffer.byteLength(value.source, 'utf8')) + 1 - + (value.global ? 1 : 0) + (value.ignoreCase ? 1 : 0) + (value.multiline ? 1 : 0) + 1 - } else { - if(serializeFunctions && value.scope != null && Object.keys(value.scope).length > 0) { - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + 4 + 4 + (!isBuffer ? numberOfBytes(value.toString()) : Buffer.byteLength(value.toString(), 'utf8')) + 1 + BSON.calculateObjectSize(value.scope, serializeFunctions); - } else if(serializeFunctions) { - return (name != null ? ((!isBuffer ? numberOfBytes(name) : Buffer.byteLength(name, 'utf8')) + 1) : 0) + 1 + 4 + (!isBuffer ? numberOfBytes(value.toString()) : Buffer.byteLength(value.toString(), 'utf8')) + 1; - } - } - } - - return 0; -} - -/** - * Serialize a Javascript object using a predefined Buffer and index into the buffer, useful when pre-allocating the space for serialization. - * - * @param {Object} object the Javascript object to serialize. - * @param {Boolean} checkKeys the serializer will check if keys are valid. - * @param {Buffer} buffer the Buffer you pre-allocated to store the serialized BSON object. - * @param {Number} index the index in the buffer where we wish to start serializing into. - * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**. - * @return {Number} returns the new write index in the Buffer. - * @api public - */ -BSON.serializeWithBufferAndIndex = function serializeWithBufferAndIndex(object, checkKeys, buffer, index, serializeFunctions) { - // Default setting false - serializeFunctions = serializeFunctions == null ? false : serializeFunctions; - // Write end information (length of the object) - var size = buffer.length; - // Write the size of the object - buffer[index++] = size & 0xff; - buffer[index++] = (size >> 8) & 0xff; - buffer[index++] = (size >> 16) & 0xff; - buffer[index++] = (size >> 24) & 0xff; - return serializeObject(object, checkKeys, buffer, index, serializeFunctions) - 1; -} - -/** - * @ignore - * @api private - */ -var serializeObject = function(object, checkKeys, buffer, index, serializeFunctions) { - if(object.toBSON) { - if(typeof object.toBSON != 'function') throw new Error("toBSON is not a function"); - object = object.toBSON(); - if(object != null && typeof object != 'object') throw new Error("toBSON function did not return an object"); - } - - // Process the object - if(Array.isArray(object)) { - for(var i = 0; i < object.length; i++) { - index = packElement(i.toString(), object[i], checkKeys, buffer, index, serializeFunctions); - } - } else { - // If we have toBSON defined, override the current object - if(object.toBSON) { - object = object.toBSON(); - } - - // Serialize the object - for(var key in object) { - // Check the key and throw error if it's illegal - if (key != '$db' && key != '$ref' && key != '$id') { - // dollars and dots ok - BSON.checkKey(key, !checkKeys); - } - - // Pack the element - index = packElement(key, object[key], checkKeys, buffer, index, serializeFunctions); - } - } - - // Write zero - buffer[index++] = 0; - return index; -} - -var stringToBytes = function(str) { - var ch, st, re = []; - for (var i = 0; i < str.length; i++ ) { - ch = str.charCodeAt(i); // get char - st = []; // set up "stack" - do { - st.push( ch & 0xFF ); // push byte to stack - ch = ch >> 8; // shift value down by 1 byte - } - while ( ch ); - // add stack contents to result - // done because chars have "wrong" endianness - re = re.concat( st.reverse() ); - } - // return an array of bytes - return re; -} - -var numberOfBytes = function(str) { - var ch, st, re = 0; - for (var i = 0; i < str.length; i++ ) { - ch = str.charCodeAt(i); // get char - st = []; // set up "stack" - do { - st.push( ch & 0xFF ); // push byte to stack - ch = ch >> 8; // shift value down by 1 byte - } - while ( ch ); - // add stack contents to result - // done because chars have "wrong" endianness - re = re + st.length; - } - // return an array of bytes - return re; -} - -/** - * @ignore - * @api private - */ -var writeToTypedArray = function(buffer, string, index) { - var bytes = stringToBytes(string); - for(var i = 0; i < bytes.length; i++) { - buffer[index + i] = bytes[i]; - } - return bytes.length; -} - -/** - * @ignore - * @api private - */ -var supportsBuffer = typeof Buffer != 'undefined'; - -/** - * @ignore - * @api private - */ -var packElement = function(name, value, checkKeys, buffer, index, serializeFunctions) { - - // If we have toBSON defined, override the current object - if(value && value.toBSON){ - value = value.toBSON(); - } - - var startIndex = index; - - switch(typeof value) { - case 'string': - // console.log("+++++++++++ index string:: " + index) - // Encode String type - buffer[index++] = BSON.BSON_DATA_STRING; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - - // Calculate size - var size = supportsBuffer ? Buffer.byteLength(value) + 1 : numberOfBytes(value) + 1; - // console.log("====== key :: " + name + " size ::" + size) - // Write the size of the string to buffer - buffer[index + 3] = (size >> 24) & 0xff; - buffer[index + 2] = (size >> 16) & 0xff; - buffer[index + 1] = (size >> 8) & 0xff; - buffer[index] = size & 0xff; - // Ajust the index - index = index + 4; - // Write the string - supportsBuffer ? buffer.write(value, index, 'utf8') : writeToTypedArray(buffer, value, index); - // Update index - index = index + size - 1; - // Write zero - buffer[index++] = 0; - // Return index - return index; - case 'number': - // We have an integer value - if(Math.floor(value) === value && value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) { - // If the value fits in 32 bits encode as int, if it fits in a double - // encode it as a double, otherwise long - if(value >= BSON.BSON_INT32_MIN && value <= BSON.BSON_INT32_MAX) { - // Set int type 32 bits or less - buffer[index++] = BSON.BSON_DATA_INT; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - // Write the int value - buffer[index++] = value & 0xff; - buffer[index++] = (value >> 8) & 0xff; - buffer[index++] = (value >> 16) & 0xff; - buffer[index++] = (value >> 24) & 0xff; - } else if(value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) { - // Encode as double - buffer[index++] = BSON.BSON_DATA_NUMBER; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - // Write float - writeIEEE754(buffer, value, index, 'little', 52, 8); - // Ajust index - index = index + 8; - } else { - // Set long type - buffer[index++] = BSON.BSON_DATA_LONG; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - var longVal = Long.fromNumber(value); - var lowBits = longVal.getLowBits(); - var highBits = longVal.getHighBits(); - // Encode low bits - buffer[index++] = lowBits & 0xff; - buffer[index++] = (lowBits >> 8) & 0xff; - buffer[index++] = (lowBits >> 16) & 0xff; - buffer[index++] = (lowBits >> 24) & 0xff; - // Encode high bits - buffer[index++] = highBits & 0xff; - buffer[index++] = (highBits >> 8) & 0xff; - buffer[index++] = (highBits >> 16) & 0xff; - buffer[index++] = (highBits >> 24) & 0xff; - } - } else { - // Encode as double - buffer[index++] = BSON.BSON_DATA_NUMBER; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - // Write float - writeIEEE754(buffer, value, index, 'little', 52, 8); - // Ajust index - index = index + 8; - } - - return index; - case 'undefined': - // Set long type - buffer[index++] = BSON.BSON_DATA_NULL; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - return index; - case 'boolean': - // Write the type - buffer[index++] = BSON.BSON_DATA_BOOLEAN; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - // Encode the boolean value - buffer[index++] = value ? 1 : 0; - return index; - case 'object': - if(value === null || value instanceof MinKey || value instanceof MaxKey - || value['_bsontype'] == 'MinKey' || value['_bsontype'] == 'MaxKey') { - // Write the type of either min or max key - if(value === null) { - buffer[index++] = BSON.BSON_DATA_NULL; - } else if(value instanceof MinKey) { - buffer[index++] = BSON.BSON_DATA_MIN_KEY; - } else { - buffer[index++] = BSON.BSON_DATA_MAX_KEY; - } - - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - return index; - } else if(value instanceof ObjectID || value['_bsontype'] == 'ObjectID') { - // console.log("+++++++++++ index OBJECTID:: " + index) - // Write the type - buffer[index++] = BSON.BSON_DATA_OID; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - - // Write objectid - supportsBuffer ? buffer.write(value.id, index, 'binary') : writeToTypedArray(buffer, value.id, index); - // Ajust index - index = index + 12; - return index; - } else if(value instanceof Date || isDate(value)) { - // Write the type - buffer[index++] = BSON.BSON_DATA_DATE; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - - // Write the date - var dateInMilis = Long.fromNumber(value.getTime()); - var lowBits = dateInMilis.getLowBits(); - var highBits = dateInMilis.getHighBits(); - // Encode low bits - buffer[index++] = lowBits & 0xff; - buffer[index++] = (lowBits >> 8) & 0xff; - buffer[index++] = (lowBits >> 16) & 0xff; - buffer[index++] = (lowBits >> 24) & 0xff; - // Encode high bits - buffer[index++] = highBits & 0xff; - buffer[index++] = (highBits >> 8) & 0xff; - buffer[index++] = (highBits >> 16) & 0xff; - buffer[index++] = (highBits >> 24) & 0xff; - return index; - } else if(typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) { - // Write the type - buffer[index++] = BSON.BSON_DATA_BINARY; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - // Get size of the buffer (current write point) - var size = value.length; - // Write the size of the string to buffer - buffer[index++] = size & 0xff; - buffer[index++] = (size >> 8) & 0xff; - buffer[index++] = (size >> 16) & 0xff; - buffer[index++] = (size >> 24) & 0xff; - // Write the default subtype - buffer[index++] = BSON.BSON_BINARY_SUBTYPE_DEFAULT; - // Copy the content form the binary field to the buffer - value.copy(buffer, index, 0, size); - // Adjust the index - index = index + size; - return index; - } else if(value instanceof Long || value instanceof Timestamp || value['_bsontype'] == 'Long' || value['_bsontype'] == 'Timestamp') { - // Write the type - buffer[index++] = value instanceof Long || value['_bsontype'] == 'Long' ? BSON.BSON_DATA_LONG : BSON.BSON_DATA_TIMESTAMP; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - // Write the date - var lowBits = value.getLowBits(); - var highBits = value.getHighBits(); - // Encode low bits - buffer[index++] = lowBits & 0xff; - buffer[index++] = (lowBits >> 8) & 0xff; - buffer[index++] = (lowBits >> 16) & 0xff; - buffer[index++] = (lowBits >> 24) & 0xff; - // Encode high bits - buffer[index++] = highBits & 0xff; - buffer[index++] = (highBits >> 8) & 0xff; - buffer[index++] = (highBits >> 16) & 0xff; - buffer[index++] = (highBits >> 24) & 0xff; - return index; - } else if(value instanceof Double || value['_bsontype'] == 'Double') { - // Encode as double - buffer[index++] = BSON.BSON_DATA_NUMBER; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - // Write float - writeIEEE754(buffer, value, index, 'little', 52, 8); - // Ajust index - index = index + 8; - return index; - } else if(value instanceof Code || value['_bsontype'] == 'Code') { - if(value.scope != null && Object.keys(value.scope).length > 0) { - // Write the type - buffer[index++] = BSON.BSON_DATA_CODE_W_SCOPE; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - // Calculate the scope size - var scopeSize = BSON.calculateObjectSize(value.scope, serializeFunctions); - // Function string - var functionString = value.code.toString(); - // Function Size - var codeSize = supportsBuffer ? Buffer.byteLength(functionString) + 1 : numberOfBytes(functionString) + 1; - - // Calculate full size of the object - var totalSize = 4 + codeSize + scopeSize + 4; - - // Write the total size of the object - buffer[index++] = totalSize & 0xff; - buffer[index++] = (totalSize >> 8) & 0xff; - buffer[index++] = (totalSize >> 16) & 0xff; - buffer[index++] = (totalSize >> 24) & 0xff; - - // Write the size of the string to buffer - buffer[index++] = codeSize & 0xff; - buffer[index++] = (codeSize >> 8) & 0xff; - buffer[index++] = (codeSize >> 16) & 0xff; - buffer[index++] = (codeSize >> 24) & 0xff; - - // Write the string - supportsBuffer ? buffer.write(functionString, index, 'utf8') : writeToTypedArray(buffer, functionString, index); - // Update index - index = index + codeSize - 1; - // Write zero - buffer[index++] = 0; - // Serialize the scope object - var scopeObjectBuffer = supportsBuffer ? new Buffer(scopeSize) : new Uint8Array(new ArrayBuffer(scopeSize)); - // Execute the serialization into a seperate buffer - serializeObject(value.scope, checkKeys, scopeObjectBuffer, 0, serializeFunctions); - - // Adjusted scope Size (removing the header) - var scopeDocSize = scopeSize; - // Write scope object size - buffer[index++] = scopeDocSize & 0xff; - buffer[index++] = (scopeDocSize >> 8) & 0xff; - buffer[index++] = (scopeDocSize >> 16) & 0xff; - buffer[index++] = (scopeDocSize >> 24) & 0xff; - - // Write the scopeObject into the buffer - supportsBuffer ? scopeObjectBuffer.copy(buffer, index, 0, scopeSize) : buffer.set(scopeObjectBuffer, index); - // Adjust index, removing the empty size of the doc (5 bytes 0000000005) - index = index + scopeDocSize - 5; - // Write trailing zero - buffer[index++] = 0; - return index - } else { - buffer[index++] = BSON.BSON_DATA_CODE; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - // Function string - var functionString = value.code.toString(); - // Function Size - var size = supportsBuffer ? Buffer.byteLength(functionString) + 1 : numberOfBytes(functionString) + 1; - // Write the size of the string to buffer - buffer[index++] = size & 0xff; - buffer[index++] = (size >> 8) & 0xff; - buffer[index++] = (size >> 16) & 0xff; - buffer[index++] = (size >> 24) & 0xff; - // Write the string - supportsBuffer ? buffer.write(functionString, index, 'utf8') : writeToTypedArray(buffer, functionString, index); - // Update index - index = index + size - 1; - // Write zero - buffer[index++] = 0; - return index; - } - } else if(value instanceof Binary || value['_bsontype'] == 'Binary') { - // Write the type - buffer[index++] = BSON.BSON_DATA_BINARY; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - // Extract the buffer - var data = value.value(true); - // Calculate size - var size = value.position; - // Write the size of the string to buffer - buffer[index++] = size & 0xff; - buffer[index++] = (size >> 8) & 0xff; - buffer[index++] = (size >> 16) & 0xff; - buffer[index++] = (size >> 24) & 0xff; - // Write the subtype to the buffer - buffer[index++] = value.sub_type; - - // If we have binary type 2 the 4 first bytes are the size - if(value.sub_type == Binary.SUBTYPE_BYTE_ARRAY) { - buffer[index++] = size & 0xff; - buffer[index++] = (size >> 8) & 0xff; - buffer[index++] = (size >> 16) & 0xff; - buffer[index++] = (size >> 24) & 0xff; - } - - // Write the data to the object - supportsBuffer ? data.copy(buffer, index, 0, value.position) : buffer.set(data, index); - // Ajust index - index = index + value.position; - return index; - } else if(value instanceof Symbol || value['_bsontype'] == 'Symbol') { - // Write the type - buffer[index++] = BSON.BSON_DATA_SYMBOL; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - // Calculate size - var size = supportsBuffer ? Buffer.byteLength(value.value) + 1 : numberOfBytes(value.value) + 1; - // Write the size of the string to buffer - buffer[index++] = size & 0xff; - buffer[index++] = (size >> 8) & 0xff; - buffer[index++] = (size >> 16) & 0xff; - buffer[index++] = (size >> 24) & 0xff; - // Write the string - buffer.write(value.value, index, 'utf8'); - // Update index - index = index + size - 1; - // Write zero - buffer[index++] = 0x00; - return index; - } else if(value instanceof DBRef || value['_bsontype'] == 'DBRef') { - // Write the type - buffer[index++] = BSON.BSON_DATA_OBJECT; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - // Set up correct object for serialization - var ordered_values = { - '$ref': value.namespace - , '$id' : value.oid - }; - - // Add db reference if it exists - if(null != value.db) { - ordered_values['$db'] = value.db; - } - - // Message size - var size = BSON.calculateObjectSize(ordered_values, serializeFunctions); - // Serialize the object - var endIndex = BSON.serializeWithBufferAndIndex(ordered_values, checkKeys, buffer, index, serializeFunctions); - // Write the size of the string to buffer - buffer[index++] = size & 0xff; - buffer[index++] = (size >> 8) & 0xff; - buffer[index++] = (size >> 16) & 0xff; - buffer[index++] = (size >> 24) & 0xff; - // Write zero for object - buffer[endIndex++] = 0x00; - // Return the end index - return endIndex; - } else if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]') { - // Write the type - buffer[index++] = BSON.BSON_DATA_REGEXP; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - - // Write the regular expression string - supportsBuffer ? buffer.write(value.source, index, 'utf8') : writeToTypedArray(buffer, value.source, index); - // Adjust the index - index = index + (supportsBuffer ? Buffer.byteLength(value.source) : numberOfBytes(value.source)); - // Write zero - buffer[index++] = 0x00; - // Write the parameters - if(value.global) buffer[index++] = 0x73; // s - if(value.ignoreCase) buffer[index++] = 0x69; // i - if(value.multiline) buffer[index++] = 0x6d; // m - // Add ending zero - buffer[index++] = 0x00; - return index; - } else { - // Write the type - buffer[index++] = Array.isArray(value) ? BSON.BSON_DATA_ARRAY : BSON.BSON_DATA_OBJECT; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Adjust the index - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - var endIndex = serializeObject(value, checkKeys, buffer, index + 4, serializeFunctions); - // Write size - var size = endIndex - index; - // Write the size of the string to buffer - buffer[index++] = size & 0xff; - buffer[index++] = (size >> 8) & 0xff; - buffer[index++] = (size >> 16) & 0xff; - buffer[index++] = (size >> 24) & 0xff; - return endIndex; - } - case 'function': - // WTF for 0.4.X where typeof /someregexp/ === 'function' - if(value instanceof RegExp || Object.prototype.toString.call(value) === '[object RegExp]' || String.call(value) == '[object RegExp]') { - // Write the type - buffer[index++] = BSON.BSON_DATA_REGEXP; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - - // Write the regular expression string - buffer.write(value.source, index, 'utf8'); - // Adjust the index - index = index + (supportsBuffer ? Buffer.byteLength(value.source) : numberOfBytes(value.source)); - // Write zero - buffer[index++] = 0x00; - // Write the parameters - if(value.global) buffer[index++] = 0x73; // s - if(value.ignoreCase) buffer[index++] = 0x69; // i - if(value.multiline) buffer[index++] = 0x6d; // m - // Add ending zero - buffer[index++] = 0x00; - return index; - } else { - if(serializeFunctions && value.scope != null && Object.keys(value.scope).length > 0) { - // Write the type - buffer[index++] = BSON.BSON_DATA_CODE_W_SCOPE; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - // Calculate the scope size - var scopeSize = BSON.calculateObjectSize(value.scope, serializeFunctions); - // Function string - var functionString = value.toString(); - // Function Size - var codeSize = supportsBuffer ? Buffer.byteLength(functionString) + 1 : numberOfBytes(functionString) + 1; - - // Calculate full size of the object - var totalSize = 4 + codeSize + scopeSize; - - // Write the total size of the object - buffer[index++] = totalSize & 0xff; - buffer[index++] = (totalSize >> 8) & 0xff; - buffer[index++] = (totalSize >> 16) & 0xff; - buffer[index++] = (totalSize >> 24) & 0xff; - - // Write the size of the string to buffer - buffer[index++] = codeSize & 0xff; - buffer[index++] = (codeSize >> 8) & 0xff; - buffer[index++] = (codeSize >> 16) & 0xff; - buffer[index++] = (codeSize >> 24) & 0xff; - - // Write the string - supportsBuffer ? buffer.write(functionString, index, 'utf8') : writeToTypedArray(buffer, functionString, index); - // Update index - index = index + codeSize - 1; - // Write zero - buffer[index++] = 0; - // Serialize the scope object - var scopeObjectBuffer = new Buffer(scopeSize); - // Execute the serialization into a seperate buffer - serializeObject(value.scope, checkKeys, scopeObjectBuffer, 0, serializeFunctions); - - // Adjusted scope Size (removing the header) - var scopeDocSize = scopeSize - 4; - // Write scope object size - buffer[index++] = scopeDocSize & 0xff; - buffer[index++] = (scopeDocSize >> 8) & 0xff; - buffer[index++] = (scopeDocSize >> 16) & 0xff; - buffer[index++] = (scopeDocSize >> 24) & 0xff; - - // Write the scopeObject into the buffer - scopeObjectBuffer.copy(buffer, index, 0, scopeSize); - - // Adjust index, removing the empty size of the doc (5 bytes 0000000005) - index = index + scopeDocSize - 5; - // Write trailing zero - buffer[index++] = 0; - return index - } else if(serializeFunctions) { - buffer[index++] = BSON.BSON_DATA_CODE; - // Number of written bytes - var numberOfWrittenBytes = supportsBuffer ? buffer.write(name, index, 'utf8') : writeToTypedArray(buffer, name, index); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - // Function string - var functionString = value.toString(); - // Function Size - var size = supportsBuffer ? Buffer.byteLength(functionString) + 1 : numberOfBytes(functionString) + 1; - // Write the size of the string to buffer - buffer[index++] = size & 0xff; - buffer[index++] = (size >> 8) & 0xff; - buffer[index++] = (size >> 16) & 0xff; - buffer[index++] = (size >> 24) & 0xff; - // Write the string - supportsBuffer ? buffer.write(functionString, index, 'utf8') : writeToTypedArray(buffer, functionString, index); - // Update index - index = index + size - 1; - // Write zero - buffer[index++] = 0; - return index; - } - } - } - - // If no value to serialize - return index; -} - -/** - * Serialize a Javascript object. - * - * @param {Object} object the Javascript object to serialize. - * @param {Boolean} checkKeys the serializer will check if keys are valid. - * @param {Boolean} asBuffer return the serialized object as a Buffer object **(ignore)**. - * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**. - * @return {Buffer} returns the Buffer object containing the serialized object. - * @api public - */ -BSON.serialize = function(object, checkKeys, asBuffer, serializeFunctions) { - // Throw error if we are trying serialize an illegal type - if(object == null || typeof object != 'object' || Array.isArray(object)) - throw new Error("Only javascript objects supported"); - - // Emoty target buffer - var buffer = null; - // Calculate the size of the object - var size = BSON.calculateObjectSize(object, serializeFunctions); - // Fetch the best available type for storing the binary data - if(buffer = typeof Buffer != 'undefined') { - buffer = new Buffer(size); - asBuffer = true; - } else if(typeof Uint8Array != 'undefined') { - buffer = new Uint8Array(new ArrayBuffer(size)); - } else { - buffer = new Array(size); - } - - // If asBuffer is false use typed arrays - BSON.serializeWithBufferAndIndex(object, checkKeys, buffer, 0, serializeFunctions); - // console.log("++++++++++++++++++++++++++++++++++++ OLDJS :: " + buffer.length) - // console.log(buffer.toString('hex')) - // console.log(buffer.toString('ascii')) - return buffer; -} - -/** - * Contains the function cache if we have that enable to allow for avoiding the eval step on each deserialization, comparison is by md5 - * - * @ignore - * @api private - */ -var functionCache = BSON.functionCache = {}; - -/** - * Crc state variables shared by function - * - * @ignore - * @api private - */ -var table = [0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D]; - -/** - * CRC32 hash method, Fast and enough versitility for our usage - * - * @ignore - * @api private - */ -var crc32 = function(string, start, end) { - var crc = 0 - var x = 0; - var y = 0; - crc = crc ^ (-1); - - for(var i = start, iTop = end; i < iTop;i++) { - y = (crc ^ string[i]) & 0xFF; - x = table[y]; - crc = (crc >>> 8) ^ x; - } - - return crc ^ (-1); -} - -/** - * Deserialize stream data as BSON documents. - * - * Options - * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized. - * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse. - * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function. - * - **promoteLongs** {Boolean, default:true}, when deserializing a Long will fit it into a Number if it's smaller than 53 bits - * - * @param {Buffer} data the buffer containing the serialized set of BSON documents. - * @param {Number} startIndex the start index in the data Buffer where the deserialization is to start. - * @param {Number} numberOfDocuments number of documents to deserialize. - * @param {Array} documents an array where to store the deserialized documents. - * @param {Number} docStartIndex the index in the documents array from where to start inserting documents. - * @param {Object} [options] additional options used for the deserialization. - * @return {Number} returns the next index in the buffer after deserialization **x** numbers of documents. - * @api public - */ -BSON.deserializeStream = function(data, startIndex, numberOfDocuments, documents, docStartIndex, options) { - // if(numberOfDocuments !== documents.length) throw new Error("Number of expected results back is less than the number of documents"); - options = options != null ? options : {}; - var index = startIndex; - // Loop over all documents - for(var i = 0; i < numberOfDocuments; i++) { - // Find size of the document - var size = data[index] | data[index + 1] << 8 | data[index + 2] << 16 | data[index + 3] << 24; - // Update options with index - options['index'] = index; - // Parse the document at this point - documents[docStartIndex + i] = BSON.deserialize(data, options); - // Adjust index by the document size - index = index + size; - } - - // Return object containing end index of parsing and list of documents - return index; -} - -/** - * Ensure eval is isolated. - * - * @ignore - * @api private - */ -var isolateEvalWithHash = function(functionCache, hash, functionString, object) { - // Contains the value we are going to set - var value = null; - - // Check for cache hit, eval if missing and return cached function - if(functionCache[hash] == null) { - eval("value = " + functionString); - functionCache[hash] = value; - } - // Set the object - return functionCache[hash].bind(object); -} - -/** - * Ensure eval is isolated. - * - * @ignore - * @api private - */ -var isolateEval = function(functionString) { - // Contains the value we are going to set - var value = null; - // Eval the function - eval("value = " + functionString); - return value; -} - -/** - * Convert Uint8Array to String - * - * @ignore - * @api private - */ -var convertUint8ArrayToUtf8String = function(byteArray, startIndex, endIndex) { - return BinaryParser.decode_utf8(convertArraytoUtf8BinaryString(byteArray, startIndex, endIndex)); -} - -var convertArraytoUtf8BinaryString = function(byteArray, startIndex, endIndex) { - var result = ""; - for(var i = startIndex; i < endIndex; i++) { - result = result + String.fromCharCode(byteArray[i]); - } - - return result; -}; - -/** - * Deserialize data as BSON. - * - * Options - * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized. - * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse. - * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function. - * - **promoteLongs** {Boolean, default:true}, when deserializing a Long will fit it into a Number if it's smaller than 53 bits - * - * @param {Buffer} buffer the buffer containing the serialized set of BSON documents. - * @param {Object} [options] additional options used for the deserialization. - * @param {Boolean} [isArray] ignore used for recursive parsing. - * @return {Object} returns the deserialized Javascript Object. - * @api public - */ -BSON.deserialize = function(buffer, options, isArray) { - // Options - options = options == null ? {} : options; - var evalFunctions = options['evalFunctions'] == null ? false : options['evalFunctions']; - var cacheFunctions = options['cacheFunctions'] == null ? false : options['cacheFunctions']; - var cacheFunctionsCrc32 = options['cacheFunctionsCrc32'] == null ? false : options['cacheFunctionsCrc32']; - var promoteLongs = options['promoteLongs'] == null ? true : options['promoteLongs']; - - // Validate that we have at least 4 bytes of buffer - if(buffer.length < 5) throw new Error("corrupt bson message < 5 bytes long"); - - // Set up index - var index = typeof options['index'] == 'number' ? options['index'] : 0; - // Reads in a C style string - var readCStyleString = function() { - // Get the start search index - var i = index; - // Locate the end of the c string - while(buffer[i] !== 0x00 && i < buffer.length) { - i++ - } - // If are at the end of the buffer there is a problem with the document - if(i >= buffer.length) throw new Error("Bad BSON Document: illegal CString") - // Grab utf8 encoded string - var string = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('utf8', index, i) : convertUint8ArrayToUtf8String(buffer, index, i); - // Update index position - index = i + 1; - // Return string - return string; - } - - // Create holding object - var object = isArray ? [] : {}; - - // Read the document size - var size = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; - - // Ensure buffer is valid size - if(size < 5 || size > buffer.length) throw new Error("corrupt bson message"); - - // While we have more left data left keep parsing - while(true) { - // Read the type - var elementType = buffer[index++]; - // If we get a zero it's the last byte, exit - if(elementType == 0) break; - // Read the name of the field - var name = readCStyleString(); - // Switch on the type - switch(elementType) { - case BSON.BSON_DATA_OID: - var string = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('binary', index, index + 12) : convertArraytoUtf8BinaryString(buffer, index, index + 12); - // Decode the oid - object[name] = new ObjectID(string); - // Update index - index = index + 12; - break; - case BSON.BSON_DATA_STRING: - // Read the content of the field - var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; - // Add string to object - object[name] = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('utf8', index, index + stringSize - 1) : convertUint8ArrayToUtf8String(buffer, index, index + stringSize - 1); - // Update parse index position - index = index + stringSize; - break; - case BSON.BSON_DATA_INT: - // Decode the 32bit value - object[name] = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; - break; - case BSON.BSON_DATA_NUMBER: - // Decode the double value - object[name] = readIEEE754(buffer, index, 'little', 52, 8); - // Update the index - index = index + 8; - break; - case BSON.BSON_DATA_DATE: - // Unpack the low and high bits - var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; - var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; - // Set date object - object[name] = new Date(new Long(lowBits, highBits).toNumber()); - break; - case BSON.BSON_DATA_BOOLEAN: - // Parse the boolean value - object[name] = buffer[index++] == 1; - break; - case BSON.BSON_DATA_UNDEFINED: - case BSON.BSON_DATA_NULL: - // Parse the boolean value - object[name] = null; - break; - case BSON.BSON_DATA_BINARY: - // Decode the size of the binary blob - var binarySize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; - // Decode the subtype - var subType = buffer[index++]; - // Decode as raw Buffer object if options specifies it - if(buffer['slice'] != null) { - // If we have subtype 2 skip the 4 bytes for the size - if(subType == Binary.SUBTYPE_BYTE_ARRAY) { - binarySize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; - } - // Slice the data - object[name] = new Binary(buffer.slice(index, index + binarySize), subType); - } else { - var _buffer = typeof Uint8Array != 'undefined' ? new Uint8Array(new ArrayBuffer(binarySize)) : new Array(binarySize); - // If we have subtype 2 skip the 4 bytes for the size - if(subType == Binary.SUBTYPE_BYTE_ARRAY) { - binarySize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; - } - // Copy the data - for(var i = 0; i < binarySize; i++) { - _buffer[i] = buffer[index + i]; - } - // Create the binary object - object[name] = new Binary(_buffer, subType); - } - // Update the index - index = index + binarySize; - break; - case BSON.BSON_DATA_ARRAY: - options['index'] = index; - // Decode the size of the array document - var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24; - // Set the array to the object - object[name] = BSON.deserialize(buffer, options, true); - // Adjust the index - index = index + objectSize; - break; - case BSON.BSON_DATA_OBJECT: - options['index'] = index; - // Decode the size of the object document - var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24; - // Set the array to the object - object[name] = BSON.deserialize(buffer, options, false); - // Adjust the index - index = index + objectSize; - break; - case BSON.BSON_DATA_REGEXP: - // Create the regexp - var source = readCStyleString(); - var regExpOptions = readCStyleString(); - // For each option add the corresponding one for javascript - var optionsArray = new Array(regExpOptions.length); - - // Parse options - for(var i = 0; i < regExpOptions.length; i++) { - switch(regExpOptions[i]) { - case 'm': - optionsArray[i] = 'm'; - break; - case 's': - optionsArray[i] = 'g'; - break; - case 'i': - optionsArray[i] = 'i'; - break; - } - } - - object[name] = new RegExp(source, optionsArray.join('')); - break; - case BSON.BSON_DATA_LONG: - // Unpack the low and high bits - var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; - var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; - // Create long object - var long = new Long(lowBits, highBits); - // Promote the long if possible - if(promoteLongs) { - object[name] = long.lessThanOrEqual(JS_INT_MAX_LONG) && long.greaterThanOrEqual(JS_INT_MIN_LONG) ? long.toNumber() : long; - } else { - object[name] = long; - } - break; - case BSON.BSON_DATA_SYMBOL: - // Read the content of the field - var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; - // Add string to object - object[name] = new Symbol(buffer.toString('utf8', index, index + stringSize - 1)); - // Update parse index position - index = index + stringSize; - break; - case BSON.BSON_DATA_TIMESTAMP: - // Unpack the low and high bits - var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; - var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; - // Set the object - object[name] = new Timestamp(lowBits, highBits); - break; - case BSON.BSON_DATA_MIN_KEY: - // Parse the object - object[name] = new MinKey(); - break; - case BSON.BSON_DATA_MAX_KEY: - // Parse the object - object[name] = new MaxKey(); - break; - case BSON.BSON_DATA_CODE: - // Read the content of the field - var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; - // Function string - var functionString = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('utf8', index, index + stringSize - 1) : convertUint8ArrayToUtf8String(buffer, index, index + stringSize - 1); - - // If we are evaluating the functions - if(evalFunctions) { - // Contains the value we are going to set - var value = null; - // If we have cache enabled let's look for the md5 of the function in the cache - if(cacheFunctions) { - var hash = cacheFunctionsCrc32 ? crc32(functionString) : functionString; - // Got to do this to avoid V8 deoptimizing the call due to finding eval - object[name] = isolateEvalWithHash(functionCache, hash, functionString, object); - } else { - // Set directly - object[name] = isolateEval(functionString); - } - } else { - object[name] = new Code(functionString, {}); - } - - // Update parse index position - index = index + stringSize; - break; - case BSON.BSON_DATA_CODE_W_SCOPE: - // Read the content of the field - var totalSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; - var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; - // Javascript function - var functionString = supportsBuffer && Buffer.isBuffer(buffer) ? buffer.toString('utf8', index, index + stringSize - 1) : convertUint8ArrayToUtf8String(buffer, index, index + stringSize - 1); - // Update parse index position - index = index + stringSize; - // Parse the element - options['index'] = index; - // Decode the size of the object document - var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24; - // Decode the scope object - var scopeObject = BSON.deserialize(buffer, options, false); - // Adjust the index - index = index + objectSize; - - // If we are evaluating the functions - if(evalFunctions) { - // Contains the value we are going to set - var value = null; - // If we have cache enabled let's look for the md5 of the function in the cache - if(cacheFunctions) { - var hash = cacheFunctionsCrc32 ? crc32(functionString) : functionString; - // Got to do this to avoid V8 deoptimizing the call due to finding eval - object[name] = isolateEvalWithHash(functionCache, hash, functionString, object); - } else { - // Set directly - object[name] = isolateEval(functionString); - } - - // Set the scope on the object - object[name].scope = scopeObject; - } else { - object[name] = new Code(functionString, scopeObject); - } - - // Add string to object - break; - } - } - - // Check if we have a db ref object - if(object['$id'] != null) object = new DBRef(object['$ref'], object['$id'], object['$db']); - - // Return the final objects - return object; -} - -/** - * Check if key name is valid. - * - * @ignore - * @api private - */ -BSON.checkKey = function checkKey (key, dollarsAndDotsOk) { - if (!key.length) return; - // Check if we have a legal key for the object - if (!!~key.indexOf("\x00")) { - // The BSON spec doesn't allow keys with null bytes because keys are - // null-terminated. - throw Error("key " + key + " must not contain null bytes"); - } - if (!dollarsAndDotsOk) { - if('$' == key[0]) { - throw Error("key " + key + " must not start with '$'"); - } else if (!!~key.indexOf('.')) { - throw Error("key " + key + " must not contain '.'"); - } - } -}; - -/** - * Deserialize data as BSON. - * - * Options - * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized. - * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse. - * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function. - * - * @param {Buffer} buffer the buffer containing the serialized set of BSON documents. - * @param {Object} [options] additional options used for the deserialization. - * @param {Boolean} [isArray] ignore used for recursive parsing. - * @return {Object} returns the deserialized Javascript Object. - * @api public - */ -BSON.prototype.deserialize = function(data, options) { - return BSON.deserialize(data, options); -} - -/** - * Deserialize stream data as BSON documents. - * - * Options - * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized. - * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse. - * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function. - * - * @param {Buffer} data the buffer containing the serialized set of BSON documents. - * @param {Number} startIndex the start index in the data Buffer where the deserialization is to start. - * @param {Number} numberOfDocuments number of documents to deserialize. - * @param {Array} documents an array where to store the deserialized documents. - * @param {Number} docStartIndex the index in the documents array from where to start inserting documents. - * @param {Object} [options] additional options used for the deserialization. - * @return {Number} returns the next index in the buffer after deserialization **x** numbers of documents. - * @api public - */ -BSON.prototype.deserializeStream = function(data, startIndex, numberOfDocuments, documents, docStartIndex, options) { - return BSON.deserializeStream(data, startIndex, numberOfDocuments, documents, docStartIndex, options); -} - -/** - * Serialize a Javascript object. - * - * @param {Object} object the Javascript object to serialize. - * @param {Boolean} checkKeys the serializer will check if keys are valid. - * @param {Boolean} asBuffer return the serialized object as a Buffer object **(ignore)**. - * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**. - * @return {Buffer} returns the Buffer object containing the serialized object. - * @api public - */ -BSON.prototype.serialize = function(object, checkKeys, asBuffer, serializeFunctions) { - return BSON.serialize(object, checkKeys, asBuffer, serializeFunctions); -} - -/** - * Calculate the bson size for a passed in Javascript object. - * - * @param {Object} object the Javascript object to calculate the BSON byte size for. - * @param {Boolean} [serializeFunctions] serialize all functions in the object **(default:false)**. - * @return {Number} returns the number of bytes the BSON object will take up. - * @api public - */ -BSON.prototype.calculateObjectSize = function(object, serializeFunctions) { - return BSON.calculateObjectSize(object, serializeFunctions); -} - -/** - * Serialize a Javascript object using a predefined Buffer and index into the buffer, useful when pre-allocating the space for serialization. - * - * @param {Object} object the Javascript object to serialize. - * @param {Boolean} checkKeys the serializer will check if keys are valid. - * @param {Buffer} buffer the Buffer you pre-allocated to store the serialized BSON object. - * @param {Number} index the index in the buffer where we wish to start serializing into. - * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**. - * @return {Number} returns the new write index in the Buffer. - * @api public - */ -BSON.prototype.serializeWithBufferAndIndex = function(object, checkKeys, buffer, startIndex, serializeFunctions) { - return BSON.serializeWithBufferAndIndex(object, checkKeys, buffer, startIndex, serializeFunctions); -} - -/** - * @ignore - * @api private - */ -exports.Code = Code; -exports.Symbol = Symbol; -exports.BSON = BSON; -exports.DBRef = DBRef; -exports.Binary = Binary; -exports.ObjectID = ObjectID; -exports.Long = Long; -exports.Timestamp = Timestamp; -exports.Double = Double; -exports.MinKey = MinKey; -exports.MaxKey = MaxKey; diff --git a/node_modules/mongodb/node_modules/bson/lib/bson/bson_new.js b/node_modules/mongodb/node_modules/bson/lib/bson/bson_new.js deleted file mode 100644 index 0b1b38d..0000000 --- a/node_modules/mongodb/node_modules/bson/lib/bson/bson_new.js +++ /dev/null @@ -1,776 +0,0 @@ -var writeIEEE754 = require('./float_parser').writeIEEE754 - , Long = require('./long').Long - , Double = require('./double').Double - , Timestamp = require('./timestamp').Timestamp - , ObjectID = require('./objectid').ObjectID - , Symbol = require('./symbol').Symbol - , Code = require('./code').Code - , MinKey = require('./min_key').MinKey - , MaxKey = require('./max_key').MaxKey - , DBRef = require('./db_ref').DBRef - , Binary = require('./binary').Binary - , BinaryParser = require('./binary_parser').BinaryParser; - -// Max Document Buffer size -var buffer = new Buffer(1024 * 1024 * 16); - -var checkKey = function checkKey (key, dollarsAndDotsOk) { - if (!key.length) return; - // Check if we have a legal key for the object - if (!!~key.indexOf("\x00")) { - // The BSON spec doesn't allow keys with null bytes because keys are - // null-terminated. - throw Error("key " + key + " must not contain null bytes"); - } - if (!dollarsAndDotsOk) { - if('$' == key[0]) { - throw Error("key " + key + " must not start with '$'"); - } else if (!!~key.indexOf('.')) { - throw Error("key " + key + " must not contain '.'"); - } - } -}; - -var serializeString = function(key, value, index) { - // Encode String type - buffer[index++] = BSON.BSON_DATA_STRING; - // Number of written bytes - var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); - // Encode the name - index = index + numberOfWrittenBytes + 1; - buffer[index - 1] = 0; - - // Calculate size - var size = Buffer.byteLength(value) + 1; - // Write the size of the string to buffer - buffer[index + 3] = (size >> 24) & 0xff; - buffer[index + 2] = (size >> 16) & 0xff; - buffer[index + 1] = (size >> 8) & 0xff; - buffer[index] = size & 0xff; - // Ajust the index - index = index + 4; - // Write the string - buffer.write(value, index, 'utf8'); - // Update index - index = index + size - 1; - // Write zero - buffer[index++] = 0; - return index; -} - -var serializeNumber = function(key, value, index) { - // We have an integer value - if(Math.floor(value) === value && value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) { - // If the value fits in 32 bits encode as int, if it fits in a double - // encode it as a double, otherwise long - if(value >= BSON.BSON_INT32_MIN && value <= BSON.BSON_INT32_MAX) { - // Set int type 32 bits or less - buffer[index++] = BSON.BSON_DATA_INT; - // Number of written bytes - var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); - // Encode the name - index = index + numberOfWrittenBytes; - buffer[index++] = 0; - // Write the int value - buffer[index++] = value & 0xff; - buffer[index++] = (value >> 8) & 0xff; - buffer[index++] = (value >> 16) & 0xff; - buffer[index++] = (value >> 24) & 0xff; - } else if(value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) { - // Encode as double - buffer[index++] = BSON.BSON_DATA_NUMBER; - // Number of written bytes - var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); - // Encode the name - index = index + numberOfWrittenBytes; - buffer[index++] = 0; - // Write float - writeIEEE754(buffer, value, index, 'little', 52, 8); - // Ajust index - index = index + 8; - } else { - // Set long type - buffer[index++] = BSON.BSON_DATA_LONG; - // Number of written bytes - var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); - // Encode the name - index = index + numberOfWrittenBytes; - buffer[index++] = 0; - var longVal = Long.fromNumber(value); - var lowBits = longVal.getLowBits(); - var highBits = longVal.getHighBits(); - // Encode low bits - buffer[index++] = lowBits & 0xff; - buffer[index++] = (lowBits >> 8) & 0xff; - buffer[index++] = (lowBits >> 16) & 0xff; - buffer[index++] = (lowBits >> 24) & 0xff; - // Encode high bits - buffer[index++] = highBits & 0xff; - buffer[index++] = (highBits >> 8) & 0xff; - buffer[index++] = (highBits >> 16) & 0xff; - buffer[index++] = (highBits >> 24) & 0xff; - } - } else { - // Encode as double - buffer[index++] = BSON.BSON_DATA_NUMBER; - // Number of written bytes - var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); - // Encode the name - index = index + numberOfWrittenBytes; - buffer[index++] = 0; - // Write float - writeIEEE754(buffer, value, index, 'little', 52, 8); - // Ajust index - index = index + 8; - } - - return index; -} - -var serializeUndefined = function(key, value, index) { - // Set long type - buffer[index++] = BSON.BSON_DATA_NULL; - // Number of written bytes - var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); - // Encode the name - index = index + numberOfWrittenBytes; - buffer[index++] = 0; - return index; -} - -var serializeBoolean = function(key, value, index) { - // Write the type - buffer[index++] = BSON.BSON_DATA_BOOLEAN; - // Number of written bytes - var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); - // Encode the name - index = index + numberOfWrittenBytes; - buffer[index++] = 0; - // Encode the boolean value - buffer[index++] = value ? 1 : 0; - return index; -} - -var serializeDate = function(key, value, index) { - // Write the type - buffer[index++] = BSON.BSON_DATA_DATE; - // Number of written bytes - var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); - // Encode the name - index = index + numberOfWrittenBytes; - buffer[index++] = 0; - - // Write the date - var dateInMilis = Long.fromNumber(value.getTime()); - var lowBits = dateInMilis.getLowBits(); - var highBits = dateInMilis.getHighBits(); - // Encode low bits - buffer[index++] = lowBits & 0xff; - buffer[index++] = (lowBits >> 8) & 0xff; - buffer[index++] = (lowBits >> 16) & 0xff; - buffer[index++] = (lowBits >> 24) & 0xff; - // Encode high bits - buffer[index++] = highBits & 0xff; - buffer[index++] = (highBits >> 8) & 0xff; - buffer[index++] = (highBits >> 16) & 0xff; - buffer[index++] = (highBits >> 24) & 0xff; - return index; -} - -var serializeRegExp = function(key, value, index) { - // Write the type - buffer[index++] = BSON.BSON_DATA_REGEXP; - // Number of written bytes - var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); - // Encode the name - index = index + numberOfWrittenBytes; - buffer[index++] = 0; - - // Write the regular expression string - buffer.write(value.source, index, 'utf8'); - // Adjust the index - index = index + Buffer.byteLength(value.source); - // Write zero - buffer[index++] = 0x00; - // Write the parameters - if(value.global) buffer[index++] = 0x73; // s - if(value.ignoreCase) buffer[index++] = 0x69; // i - if(value.multiline) buffer[index++] = 0x6d; // m - // Add ending zero - buffer[index++] = 0x00; - return index; -} - -var serializeMinMax = function(key, value, index) { - // Write the type of either min or max key - if(value === null) { - buffer[index++] = BSON.BSON_DATA_NULL; - } else if(value instanceof MinKey) { - buffer[index++] = BSON.BSON_DATA_MIN_KEY; - } else { - buffer[index++] = BSON.BSON_DATA_MAX_KEY; - } - - // Number of written bytes - var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); - // Encode the name - index = index + numberOfWrittenBytes; - buffer[index++] = 0; - return index; -} - -var serializeObjectId = function(key, value, index) { - // Write the type - buffer[index++] = BSON.BSON_DATA_OID; - // Number of written bytes - var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); - // Encode the name - index = index + numberOfWrittenBytes; - buffer[index++] = 0; - - for(var j = 0; j < 12; j++) { - buffer[index + j] = value.binId[j]; - } - - // Ajust index - index = index + 12; - return index; -} - -var serializeBuffer = function(key, value, index) { - // Write the type - buffer[index++] = BSON.BSON_DATA_BINARY; - // Number of written bytes - var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); - // Encode the name - index = index + numberOfWrittenBytes; - buffer[index++] = 0; - // Get size of the buffer (current write point) - var size = value.length; - // Write the size of the string to buffer - buffer[index++] = size & 0xff; - buffer[index++] = (size >> 8) & 0xff; - buffer[index++] = (size >> 16) & 0xff; - buffer[index++] = (size >> 24) & 0xff; - // Write the default subtype - buffer[index++] = BSON.BSON_BINARY_SUBTYPE_DEFAULT; - // Copy the content form the binary field to the buffer - value.copy(buffer, index, 0, size); - // Adjust the index - index = index + size; - return index; -} - -var serializeObject = function(key, value, index, checkKeys, depth) { - // Write the type - buffer[index++] = Array.isArray(value) ? BSON.BSON_DATA_ARRAY : BSON.BSON_DATA_OBJECT; - // Number of written bytes - var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); - // Encode the name - index = index + numberOfWrittenBytes; - buffer[index++] = 0; - var endIndex = serializeInto(value, checkKeys, index, depth + 1); - // Write size - var size = endIndex - index; - return endIndex; -} - -var serializeLong = function(key, value, index) { - // Write the type - buffer[index++] = value instanceof Long ? BSON.BSON_DATA_LONG : BSON.BSON_DATA_TIMESTAMP; - // Number of written bytes - var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); - // Encode the name - index = index + numberOfWrittenBytes; - buffer[index++] = 0; - // Write the date - var lowBits = value.getLowBits(); - var highBits = value.getHighBits(); - // Encode low bits - buffer[index++] = lowBits & 0xff; - buffer[index++] = (lowBits >> 8) & 0xff; - buffer[index++] = (lowBits >> 16) & 0xff; - buffer[index++] = (lowBits >> 24) & 0xff; - // Encode high bits - buffer[index++] = highBits & 0xff; - buffer[index++] = (highBits >> 8) & 0xff; - buffer[index++] = (highBits >> 16) & 0xff; - buffer[index++] = (highBits >> 24) & 0xff; - return index; -} - -var serializeDouble = function(key, value, index) { - // Encode as double - buffer[index++] = BSON.BSON_DATA_NUMBER; - // Number of written bytes - var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); - // Encode the name - index = index + numberOfWrittenBytes; - buffer[index++] = 0; - // Write float - writeIEEE754(buffer, value, index, 'little', 52, 8); - // Ajust index - index = index + 8; - return index; -} - -var serializeCode = function(key, value, index, checkKeys, depth) { - if(value.scope != null && Object.keys(value.scope).length > 0) { - // Write the type - buffer[index++] = BSON.BSON_DATA_CODE_W_SCOPE; - // Number of written bytes - var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); - // Encode the name - index = index + numberOfWrittenBytes; - buffer[index++] = 0; - - // Starting index - var startIndex = index; - - // Serialize the function - // Get the function string - var functionString = typeof value.code == 'string' ? value.code : value.code.toString(); - var codeSize = Buffer.byteLength(functionString) + 1; - // Index adjustment - index = index + 4; - // Write the size of the string to buffer - buffer[index] = codeSize & 0xff; - buffer[index + 1] = (codeSize >> 8) & 0xff; - buffer[index + 2] = (codeSize >> 16) & 0xff; - buffer[index + 3] = (codeSize >> 24) & 0xff; - // Write string into buffer - buffer.write(functionString, index + 4, 'utf8'); - // Write end 0 - buffer[index + 4 + codeSize - 1] = 0; - // Write the - index = index + codeSize + 4; - - // - // Serialize the scope value - var endIndex = serializeInto(value.scope, checkKeys, index, depth + 1) - index = endIndex - 1; - - // Writ the total - var totalSize = endIndex - startIndex; - - // Write the total size of the object - buffer[startIndex++] = totalSize & 0xff; - buffer[startIndex++] = (totalSize >> 8) & 0xff; - buffer[startIndex++] = (totalSize >> 16) & 0xff; - buffer[startIndex++] = (totalSize >> 24) & 0xff; - // Write trailing zero - buffer[index++] = 0; - } else { - buffer[index++] = BSON.BSON_DATA_CODE; - // Number of written bytes - var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); - // Encode the name - index = index + numberOfWrittenBytes; - buffer[index++] = 0; - // Function string - var functionString = value.code.toString(); - // Function Size - var size = Buffer.byteLength(functionString) + 1; - // Write the size of the string to buffer - buffer[index++] = size & 0xff; - buffer[index++] = (size >> 8) & 0xff; - buffer[index++] = (size >> 16) & 0xff; - buffer[index++] = (size >> 24) & 0xff; - // Write the string - buffer.write(functionString, index, 'utf8'); - // Update index - index = index + size - 1; - // Write zero - buffer[index++] = 0; - } - - return index; -} - -var serializeBinary = function(key, value, index) { - // Write the type - buffer[index++] = BSON.BSON_DATA_BINARY; - // Number of written bytes - var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); - // Encode the name - index = index + numberOfWrittenBytes; - buffer[index++] = 0; - // Extract the buffer - var data = value.value(true); - // Calculate size - var size = value.position; - // Write the size of the string to buffer - buffer[index++] = size & 0xff; - buffer[index++] = (size >> 8) & 0xff; - buffer[index++] = (size >> 16) & 0xff; - buffer[index++] = (size >> 24) & 0xff; - // Write the subtype to the buffer - buffer[index++] = value.sub_type; - - // If we have binary type 2 the 4 first bytes are the size - if(value.sub_type == Binary.SUBTYPE_BYTE_ARRAY) { - buffer[index++] = size & 0xff; - buffer[index++] = (size >> 8) & 0xff; - buffer[index++] = (size >> 16) & 0xff; - buffer[index++] = (size >> 24) & 0xff; - } - - // Write the data to the object - data.copy(buffer, index, 0, value.position); - // Adjust the index - index = index + value.position; - return index; -} - -var serializeSymbol = function(key, value, index) { - // Write the type - buffer[index++] = BSON.BSON_DATA_SYMBOL; - // Number of written bytes - var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); - // Encode the name - index = index + numberOfWrittenBytes; - buffer[index++] = 0; - // Calculate size - var size = Buffer.byteLength(value.value) + 1; - // Write the size of the string to buffer - buffer[index++] = size & 0xff; - buffer[index++] = (size >> 8) & 0xff; - buffer[index++] = (size >> 16) & 0xff; - buffer[index++] = (size >> 24) & 0xff; - // Write the string - buffer.write(value.value, index, 'utf8'); - // Update index - index = index + size - 1; - // Write zero - buffer[index++] = 0x00; - return index; -} - -var serializeDBRef = function(key, value, index, depth) { - // Write the type - buffer[index++] = BSON.BSON_DATA_OBJECT; - // Number of written bytes - var numberOfWrittenBytes = buffer.write(key, index, 'utf8'); - - // Encode the name - index = index + numberOfWrittenBytes; - buffer[index++] = 0; - - var startIndex = index; - var endIndex; - - // Serialize object - if(null != value.db) { - endIndex = serializeInto({ - '$ref': value.namespace - , '$id' : value.oid - , '$db' : value.db - }, false, index, depth + 1); - } else { - endIndex = serializeInto({ - '$ref': value.namespace - , '$id' : value.oid - }, false, index, depth + 1); - } - - // Calculate object size - var size = endIndex - startIndex; - // Write the size - buffer[startIndex++] = size & 0xff; - buffer[startIndex++] = (size >> 8) & 0xff; - buffer[startIndex++] = (size >> 16) & 0xff; - buffer[startIndex++] = (size >> 24) & 0xff; - // Set index - return endIndex; -} - -var BSON = function() { - this.buffer = buffer; -} - -BSON.prototype.serialize = function serialize(object, checkKeys, index) { - var finishedBuffer = new Buffer(serializeInto(object, checkKeys, index || 0, 0)); - this.buffer.copy(finishedBuffer, 0, 0, finishedBuffer.length); - return finishedBuffer; -} - -var serializeInto = function serializeInto(object, checkKeys, startingIndex, depth) { - startingIndex = startingIndex || 0; - - // Start place to serialize into - var index = startingIndex + 4; - var self = this; - - // Special case isArray - if(Array.isArray(object)) { - // Get object keys - for(var i = 0; i < object.length; i++) { - var key = "" + i; - var type = typeof object[i]; - - // Check the key and throw error if it's illegal - if(key != '$db' && key != '$ref' && key != '$id') { - checkKey(key, !checkKeys); - } - - if(type == 'string') { - index = serializeString(key, object[i], index); - } else if(type == 'number') { - index = serializeNumber(key, object[i], index); - } else if(type == 'undefined') { - index = serializeUndefined(key, object[i], index); - } else if(type == 'boolean') { - index = serializeBoolean(key, object[i], index); - } else if(object[i] instanceof Date) { - index = serializeDate(key, object[i], index); - } else if(object[i] instanceof RegExp || Object.prototype.toString.call(object[i]) === '[object RegExp]') { - index = serializeRegExp(key, object[i], index); - } else if(object[i]['_bsontype'] == 'MinKey' || object[i]['_bsontype'] == 'MaxKey') { - index = serializeMinMax(key, object[i], index); - } else if(object[i]['_bsontype'] == 'ObjectID') { - index = serializeObjectId(key, object[i], index); - } else if(Buffer.isBuffer(object[i])) { - index = serializeBuffer(key, object[i], index); - } else if(type == 'object' && object[i]['_bsontype'] == null) { - index = serializeObject(key, object[i], index, checkKeys, depth); - } else if(object[i]['_bsontype'] == 'Long' || object[i]['_bsontype'] == 'Timestamp') { - index = serializeLong(key, object[i], index); - } else if(object[i]['_bsontype'] == 'Double') { - index = serializeDouble(key, object[i], index); - } else if(object[i]['_bsontype'] == 'Code') { - index = serializeCode(key, object[i], index, checkKeys, depth); - } else if(object[i]['_bsontype'] == 'Binary') { - index = serializeBinary(key, object[i], index); - } else if(object[i]['_bsontype'] == 'Symbol') { - index = serializeSymbol(key, object[i], index); - } else if(object[i]['_bsontype'] == 'DBRef') { - index = serializeDBRef(key, object[i], index, depth); - } - } - } else { - var keys = Object.keys(object); - for(var i = 0; i < keys.length; i++) { - var key = keys[i]; - var type = typeof object[key]; - - // Check the key and throw error if it's illegal - if(key != '$db' && key != '$ref' && key != '$id') { - checkKey(key, !checkKeys); - } - - if(type == 'string') { - index = serializeString(key, object[key], index); - } else if(type == 'number') { - index = serializeNumber(key, object[key], index); - } else if(type == 'undefined') { - index = serializeUndefined(key, object[key], index); - } else if(type == 'boolean') { - index = serializeBoolean(key, object[key], index); - } else if(object[key] instanceof Date) { - index = serializeDate(key, object[key], index); - } else if(object[key] instanceof RegExp || Object.prototype.toString.call(object[key]) === '[object RegExp]') { - index = serializeRegExp(key, object[key], index); - } else if(object[key]['_bsontype'] == 'MinKey' || object[key]['_bsontype'] == 'MaxKey') { - index = serializeMinMax(key, object[key], index); - } else if(object[key]['_bsontype'] == 'ObjectID') { - index = serializeObjectId(key, object[key], index); - } else if(Buffer.isBuffer(object[key])) { - index = serializeBuffer(key, object[key], index); - } else if(type == 'object' && object[key]['_bsontype'] == null) { - index = serializeObject(key, object[key], index, checkKeys, depth); - } else if(object[key]['_bsontype'] == 'Long' || object[key]['_bsontype'] == 'Timestamp') { - index = serializeLong(key, object[key], index); - } else if(object[key]['_bsontype'] == 'Double') { - index = serializeDouble(key, object[key], index); - } else if(object[key]['_bsontype'] == 'Code') { - index = serializeCode(key, object[key], index, checkKeys, depth); - } else if(object[key]['_bsontype'] == 'Binary') { - index = serializeBinary(key, object[key], index); - } else if(object[key]['_bsontype'] == 'Symbol') { - index = serializeSymbol(key, object[key], index); - } else if(object[key]['_bsontype'] == 'DBRef') { - index = serializeDBRef(key, object[key], index, depth); - } - } - } - - // Final padding byte for object - buffer[index++] = 0x00; - - // Final size - var size = index - startingIndex; - // Write the size of the object - buffer[startingIndex++] = size & 0xff; - buffer[startingIndex++] = (size >> 8) & 0xff; - buffer[startingIndex++] = (size >> 16) & 0xff; - buffer[startingIndex++] = (size >> 24) & 0xff; - return index; -} - -/** - * @ignore - * @api private - */ -// BSON MAX VALUES -BSON.BSON_INT32_MAX = 0x7FFFFFFF; -BSON.BSON_INT32_MIN = -0x80000000; - -BSON.BSON_INT64_MAX = Math.pow(2, 63) - 1; -BSON.BSON_INT64_MIN = -Math.pow(2, 63); - -// JS MAX PRECISE VALUES -BSON.JS_INT_MAX = 0x20000000000000; // Any integer up to 2^53 can be precisely represented by a double. -BSON.JS_INT_MIN = -0x20000000000000; // Any integer down to -2^53 can be precisely represented by a double. - -// Internal long versions -var JS_INT_MAX_LONG = Long.fromNumber(0x20000000000000); // Any integer up to 2^53 can be precisely represented by a double. -var JS_INT_MIN_LONG = Long.fromNumber(-0x20000000000000); // Any integer down to -2^53 can be precisely represented by a double. - -/** - * Number BSON Type - * - * @classconstant BSON_DATA_NUMBER - **/ -BSON.BSON_DATA_NUMBER = 1; -/** - * String BSON Type - * - * @classconstant BSON_DATA_STRING - **/ -BSON.BSON_DATA_STRING = 2; -/** - * Object BSON Type - * - * @classconstant BSON_DATA_OBJECT - **/ -BSON.BSON_DATA_OBJECT = 3; -/** - * Array BSON Type - * - * @classconstant BSON_DATA_ARRAY - **/ -BSON.BSON_DATA_ARRAY = 4; -/** - * Binary BSON Type - * - * @classconstant BSON_DATA_BINARY - **/ -BSON.BSON_DATA_BINARY = 5; -/** - * ObjectID BSON Type - * - * @classconstant BSON_DATA_OID - **/ -BSON.BSON_DATA_OID = 7; -/** - * Boolean BSON Type - * - * @classconstant BSON_DATA_BOOLEAN - **/ -BSON.BSON_DATA_BOOLEAN = 8; -/** - * Date BSON Type - * - * @classconstant BSON_DATA_DATE - **/ -BSON.BSON_DATA_DATE = 9; -/** - * null BSON Type - * - * @classconstant BSON_DATA_NULL - **/ -BSON.BSON_DATA_NULL = 10; -/** - * RegExp BSON Type - * - * @classconstant BSON_DATA_REGEXP - **/ -BSON.BSON_DATA_REGEXP = 11; -/** - * Code BSON Type - * - * @classconstant BSON_DATA_CODE - **/ -BSON.BSON_DATA_CODE = 13; -/** - * Symbol BSON Type - * - * @classconstant BSON_DATA_SYMBOL - **/ -BSON.BSON_DATA_SYMBOL = 14; -/** - * Code with Scope BSON Type - * - * @classconstant BSON_DATA_CODE_W_SCOPE - **/ -BSON.BSON_DATA_CODE_W_SCOPE = 15; -/** - * 32 bit Integer BSON Type - * - * @classconstant BSON_DATA_INT - **/ -BSON.BSON_DATA_INT = 16; -/** - * Timestamp BSON Type - * - * @classconstant BSON_DATA_TIMESTAMP - **/ -BSON.BSON_DATA_TIMESTAMP = 17; -/** - * Long BSON Type - * - * @classconstant BSON_DATA_LONG - **/ -BSON.BSON_DATA_LONG = 18; -/** - * MinKey BSON Type - * - * @classconstant BSON_DATA_MIN_KEY - **/ -BSON.BSON_DATA_MIN_KEY = 0xff; -/** - * MaxKey BSON Type - * - * @classconstant BSON_DATA_MAX_KEY - **/ -BSON.BSON_DATA_MAX_KEY = 0x7f; - -/** - * Binary Default Type - * - * @classconstant BSON_BINARY_SUBTYPE_DEFAULT - **/ -BSON.BSON_BINARY_SUBTYPE_DEFAULT = 0; -/** - * Binary Function Type - * - * @classconstant BSON_BINARY_SUBTYPE_FUNCTION - **/ -BSON.BSON_BINARY_SUBTYPE_FUNCTION = 1; -/** - * Binary Byte Array Type - * - * @classconstant BSON_BINARY_SUBTYPE_BYTE_ARRAY - **/ -BSON.BSON_BINARY_SUBTYPE_BYTE_ARRAY = 2; -/** - * Binary UUID Type - * - * @classconstant BSON_BINARY_SUBTYPE_UUID - **/ -BSON.BSON_BINARY_SUBTYPE_UUID = 3; -/** - * Binary MD5 Type - * - * @classconstant BSON_BINARY_SUBTYPE_MD5 - **/ -BSON.BSON_BINARY_SUBTYPE_MD5 = 4; -/** - * Binary User Defined Type - * - * @classconstant BSON_BINARY_SUBTYPE_USER_DEFINED - **/ -BSON.BSON_BINARY_SUBTYPE_USER_DEFINED = 128; - -// Return BSON -exports.BSON = BSON; \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/bson/lib/bson/code.js b/node_modules/mongodb/node_modules/bson/lib/bson/code.js deleted file mode 100644 index c534103..0000000 --- a/node_modules/mongodb/node_modules/bson/lib/bson/code.js +++ /dev/null @@ -1,24 +0,0 @@ -/** - * A class representation of the BSON Code type. - * - * @class Represents the BSON Code type. - * @param {String|Function} code a string or function. - * @param {Object} [scope] an optional scope for the function. - * @return {Code} - */ -var Code = function Code(code, scope) { - if(!(this instanceof Code)) return new Code(code, scope); - this._bsontype = 'Code'; - this.code = code; - this.scope = scope == null ? {} : scope; -}; - -/** - * @ignore - * @api private - */ -Code.prototype.toJSON = function() { - return {scope:this.scope, code:this.code}; -} - -exports.Code = Code; \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/bson/lib/bson/db_ref.js b/node_modules/mongodb/node_modules/bson/lib/bson/db_ref.js deleted file mode 100644 index 56b6510..0000000 --- a/node_modules/mongodb/node_modules/bson/lib/bson/db_ref.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * A class representation of the BSON DBRef type. - * - * @class Represents the BSON DBRef type. - * @param {String} namespace the collection name. - * @param {ObjectID} oid the reference ObjectID. - * @param {String} [db] optional db name, if omitted the reference is local to the current db. - * @return {DBRef} - */ -function DBRef(namespace, oid, db) { - if(!(this instanceof DBRef)) return new DBRef(namespace, oid, db); - - this._bsontype = 'DBRef'; - this.namespace = namespace; - this.oid = oid; - this.db = db; -}; - -/** - * @ignore - * @api private - */ -DBRef.prototype.toJSON = function() { - return { - '$ref':this.namespace, - '$id':this.oid, - '$db':this.db == null ? '' : this.db - }; -} - -exports.DBRef = DBRef; \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/bson/lib/bson/double.js b/node_modules/mongodb/node_modules/bson/lib/bson/double.js deleted file mode 100644 index ae51463..0000000 --- a/node_modules/mongodb/node_modules/bson/lib/bson/double.js +++ /dev/null @@ -1,33 +0,0 @@ -/** - * A class representation of the BSON Double type. - * - * @class Represents the BSON Double type. - * @param {Number} value the number we want to represent as a double. - * @return {Double} - */ -function Double(value) { - if(!(this instanceof Double)) return new Double(value); - - this._bsontype = 'Double'; - this.value = value; -} - -/** - * Access the number value. - * - * @return {Number} returns the wrapped double number. - * @api public - */ -Double.prototype.valueOf = function() { - return this.value; -}; - -/** - * @ignore - * @api private - */ -Double.prototype.toJSON = function() { - return this.value; -} - -exports.Double = Double; \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/bson/lib/bson/float_parser.js b/node_modules/mongodb/node_modules/bson/lib/bson/float_parser.js deleted file mode 100644 index 6fca392..0000000 --- a/node_modules/mongodb/node_modules/bson/lib/bson/float_parser.js +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (c) 2008, Fair Oaks Labs, Inc. -// All rights reserved. -// -// 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. -// -// * Neither the name of Fair Oaks Labs, Inc. nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 OWNER OR CONTRIBUTORS 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. -// -// -// Modifications to writeIEEE754 to support negative zeroes made by Brian White - -var readIEEE754 = function(buffer, offset, endian, mLen, nBytes) { - var e, m, - bBE = (endian === 'big'), - eLen = nBytes * 8 - mLen - 1, - eMax = (1 << eLen) - 1, - eBias = eMax >> 1, - nBits = -7, - i = bBE ? 0 : (nBytes - 1), - d = bBE ? 1 : -1, - s = buffer[offset + i]; - - i += d; - - e = s & ((1 << (-nBits)) - 1); - s >>= (-nBits); - nBits += eLen; - for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8); - - m = e & ((1 << (-nBits)) - 1); - e >>= (-nBits); - nBits += mLen; - for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8); - - if (e === 0) { - e = 1 - eBias; - } else if (e === eMax) { - return m ? NaN : ((s ? -1 : 1) * Infinity); - } else { - m = m + Math.pow(2, mLen); - e = e - eBias; - } - return (s ? -1 : 1) * m * Math.pow(2, e - mLen); -}; - -var writeIEEE754 = function(buffer, value, offset, endian, mLen, nBytes) { - var e, m, c, - bBE = (endian === 'big'), - eLen = nBytes * 8 - mLen - 1, - eMax = (1 << eLen) - 1, - eBias = eMax >> 1, - rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0), - i = bBE ? (nBytes-1) : 0, - d = bBE ? -1 : 1, - s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0; - - value = Math.abs(value); - - if (isNaN(value) || value === Infinity) { - m = isNaN(value) ? 1 : 0; - e = eMax; - } else { - e = Math.floor(Math.log(value) / Math.LN2); - if (value * (c = Math.pow(2, -e)) < 1) { - e--; - c *= 2; - } - if (e+eBias >= 1) { - value += rt / c; - } else { - value += rt * Math.pow(2, 1 - eBias); - } - if (value * c >= 2) { - e++; - c /= 2; - } - - if (e + eBias >= eMax) { - m = 0; - e = eMax; - } else if (e + eBias >= 1) { - m = (value * c - 1) * Math.pow(2, mLen); - e = e + eBias; - } else { - m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen); - e = 0; - } - } - - for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8); - - e = (e << mLen) | m; - eLen += mLen; - for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8); - - buffer[offset + i - d] |= s * 128; -}; - -exports.readIEEE754 = readIEEE754; -exports.writeIEEE754 = writeIEEE754; \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/bson/lib/bson/index.js b/node_modules/mongodb/node_modules/bson/lib/bson/index.js deleted file mode 100644 index 950fcad..0000000 --- a/node_modules/mongodb/node_modules/bson/lib/bson/index.js +++ /dev/null @@ -1,74 +0,0 @@ -try { - exports.BSONPure = require('./bson'); - exports.BSONNative = require('../../ext'); -} catch(err) { - // do nothing -} - -[ './binary_parser' - , './binary' - , './code' - , './db_ref' - , './double' - , './max_key' - , './min_key' - , './objectid' - , './symbol' - , './timestamp' - , './long'].forEach(function (path) { - var module = require('./' + path); - for (var i in module) { - exports[i] = module[i]; - } -}); - -// Exports all the classes for the NATIVE JS BSON Parser -exports.native = function() { - var classes = {}; - // Map all the classes - [ './binary_parser' - , './binary' - , './code' - , './db_ref' - , './double' - , './max_key' - , './min_key' - , './objectid' - , './symbol' - , './timestamp' - , './long' - , '../../ext' -].forEach(function (path) { - var module = require('./' + path); - for (var i in module) { - classes[i] = module[i]; - } - }); - // Return classes list - return classes; -} - -// Exports all the classes for the PURE JS BSON Parser -exports.pure = function() { - var classes = {}; - // Map all the classes - [ './binary_parser' - , './binary' - , './code' - , './db_ref' - , './double' - , './max_key' - , './min_key' - , './objectid' - , './symbol' - , './timestamp' - , './long' - , '././bson'].forEach(function (path) { - var module = require('./' + path); - for (var i in module) { - classes[i] = module[i]; - } - }); - // Return classes list - return classes; -} diff --git a/node_modules/mongodb/node_modules/bson/lib/bson/long.js b/node_modules/mongodb/node_modules/bson/lib/bson/long.js deleted file mode 100644 index f8f37a6..0000000 --- a/node_modules/mongodb/node_modules/bson/lib/bson/long.js +++ /dev/null @@ -1,854 +0,0 @@ -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Copyright 2009 Google Inc. All Rights Reserved - -/** - * Defines a Long class for representing a 64-bit two's-complement - * integer value, which faithfully simulates the behavior of a Java "Long". This - * implementation is derived from LongLib in GWT. - * - * Constructs a 64-bit two's-complement integer, given its low and high 32-bit - * values as *signed* integers. See the from* functions below for more - * convenient ways of constructing Longs. - * - * The internal representation of a Long is the two given signed, 32-bit values. - * We use 32-bit pieces because these are the size of integers on which - * Javascript performs bit-operations. For operations like addition and - * multiplication, we split each number into 16-bit pieces, which can easily be - * multiplied within Javascript's floating-point representation without overflow - * or change in sign. - * - * In the algorithms below, we frequently reduce the negative case to the - * positive case by negating the input(s) and then post-processing the result. - * Note that we must ALWAYS check specially whether those values are MIN_VALUE - * (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as - * a positive number, it overflows back into a negative). Not handling this - * case would often result in infinite recursion. - * - * @class Represents the BSON Long type. - * @param {Number} low the low (signed) 32 bits of the Long. - * @param {Number} high the high (signed) 32 bits of the Long. - */ -function Long(low, high) { - if(!(this instanceof Long)) return new Long(low, high); - - this._bsontype = 'Long'; - /** - * @type {number} - * @api private - */ - this.low_ = low | 0; // force into 32 signed bits. - - /** - * @type {number} - * @api private - */ - this.high_ = high | 0; // force into 32 signed bits. -}; - -/** - * Return the int value. - * - * @return {Number} the value, assuming it is a 32-bit integer. - * @api public - */ -Long.prototype.toInt = function() { - return this.low_; -}; - -/** - * Return the Number value. - * - * @return {Number} the closest floating-point representation to this value. - * @api public - */ -Long.prototype.toNumber = function() { - return this.high_ * Long.TWO_PWR_32_DBL_ + - this.getLowBitsUnsigned(); -}; - -/** - * Return the JSON value. - * - * @return {String} the JSON representation. - * @api public - */ -Long.prototype.toJSON = function() { - return this.toString(); -} - -/** - * Return the String value. - * - * @param {Number} [opt_radix] the radix in which the text should be written. - * @return {String} the textual representation of this value. - * @api public - */ -Long.prototype.toString = function(opt_radix) { - var radix = opt_radix || 10; - if (radix < 2 || 36 < radix) { - throw Error('radix out of range: ' + radix); - } - - if (this.isZero()) { - return '0'; - } - - if (this.isNegative()) { - if (this.equals(Long.MIN_VALUE)) { - // We need to change the Long value before it can be negated, so we remove - // the bottom-most digit in this base and then recurse to do the rest. - var radixLong = Long.fromNumber(radix); - var div = this.div(radixLong); - var rem = div.multiply(radixLong).subtract(this); - return div.toString(radix) + rem.toInt().toString(radix); - } else { - return '-' + this.negate().toString(radix); - } - } - - // Do several (6) digits each time through the loop, so as to - // minimize the calls to the very expensive emulated div. - var radixToPower = Long.fromNumber(Math.pow(radix, 6)); - - var rem = this; - var result = ''; - while (true) { - var remDiv = rem.div(radixToPower); - var intval = rem.subtract(remDiv.multiply(radixToPower)).toInt(); - var digits = intval.toString(radix); - - rem = remDiv; - if (rem.isZero()) { - return digits + result; - } else { - while (digits.length < 6) { - digits = '0' + digits; - } - result = '' + digits + result; - } - } -}; - -/** - * Return the high 32-bits value. - * - * @return {Number} the high 32-bits as a signed value. - * @api public - */ -Long.prototype.getHighBits = function() { - return this.high_; -}; - -/** - * Return the low 32-bits value. - * - * @return {Number} the low 32-bits as a signed value. - * @api public - */ -Long.prototype.getLowBits = function() { - return this.low_; -}; - -/** - * Return the low unsigned 32-bits value. - * - * @return {Number} the low 32-bits as an unsigned value. - * @api public - */ -Long.prototype.getLowBitsUnsigned = function() { - return (this.low_ >= 0) ? - this.low_ : Long.TWO_PWR_32_DBL_ + this.low_; -}; - -/** - * Returns the number of bits needed to represent the absolute value of this Long. - * - * @return {Number} Returns the number of bits needed to represent the absolute value of this Long. - * @api public - */ -Long.prototype.getNumBitsAbs = function() { - if (this.isNegative()) { - if (this.equals(Long.MIN_VALUE)) { - return 64; - } else { - return this.negate().getNumBitsAbs(); - } - } else { - var val = this.high_ != 0 ? this.high_ : this.low_; - for (var bit = 31; bit > 0; bit--) { - if ((val & (1 << bit)) != 0) { - break; - } - } - return this.high_ != 0 ? bit + 33 : bit + 1; - } -}; - -/** - * Return whether this value is zero. - * - * @return {Boolean} whether this value is zero. - * @api public - */ -Long.prototype.isZero = function() { - return this.high_ == 0 && this.low_ == 0; -}; - -/** - * Return whether this value is negative. - * - * @return {Boolean} whether this value is negative. - * @api public - */ -Long.prototype.isNegative = function() { - return this.high_ < 0; -}; - -/** - * Return whether this value is odd. - * - * @return {Boolean} whether this value is odd. - * @api public - */ -Long.prototype.isOdd = function() { - return (this.low_ & 1) == 1; -}; - -/** - * Return whether this Long equals the other - * - * @param {Long} other Long to compare against. - * @return {Boolean} whether this Long equals the other - * @api public - */ -Long.prototype.equals = function(other) { - return (this.high_ == other.high_) && (this.low_ == other.low_); -}; - -/** - * Return whether this Long does not equal the other. - * - * @param {Long} other Long to compare against. - * @return {Boolean} whether this Long does not equal the other. - * @api public - */ -Long.prototype.notEquals = function(other) { - return (this.high_ != other.high_) || (this.low_ != other.low_); -}; - -/** - * Return whether this Long is less than the other. - * - * @param {Long} other Long to compare against. - * @return {Boolean} whether this Long is less than the other. - * @api public - */ -Long.prototype.lessThan = function(other) { - return this.compare(other) < 0; -}; - -/** - * Return whether this Long is less than or equal to the other. - * - * @param {Long} other Long to compare against. - * @return {Boolean} whether this Long is less than or equal to the other. - * @api public - */ -Long.prototype.lessThanOrEqual = function(other) { - return this.compare(other) <= 0; -}; - -/** - * Return whether this Long is greater than the other. - * - * @param {Long} other Long to compare against. - * @return {Boolean} whether this Long is greater than the other. - * @api public - */ -Long.prototype.greaterThan = function(other) { - return this.compare(other) > 0; -}; - -/** - * Return whether this Long is greater than or equal to the other. - * - * @param {Long} other Long to compare against. - * @return {Boolean} whether this Long is greater than or equal to the other. - * @api public - */ -Long.prototype.greaterThanOrEqual = function(other) { - return this.compare(other) >= 0; -}; - -/** - * Compares this Long with the given one. - * - * @param {Long} other Long to compare against. - * @return {Boolean} 0 if they are the same, 1 if the this is greater, and -1 if the given one is greater. - * @api public - */ -Long.prototype.compare = function(other) { - if (this.equals(other)) { - return 0; - } - - var thisNeg = this.isNegative(); - var otherNeg = other.isNegative(); - if (thisNeg && !otherNeg) { - return -1; - } - if (!thisNeg && otherNeg) { - return 1; - } - - // at this point, the signs are the same, so subtraction will not overflow - if (this.subtract(other).isNegative()) { - return -1; - } else { - return 1; - } -}; - -/** - * The negation of this value. - * - * @return {Long} the negation of this value. - * @api public - */ -Long.prototype.negate = function() { - if (this.equals(Long.MIN_VALUE)) { - return Long.MIN_VALUE; - } else { - return this.not().add(Long.ONE); - } -}; - -/** - * Returns the sum of this and the given Long. - * - * @param {Long} other Long to add to this one. - * @return {Long} the sum of this and the given Long. - * @api public - */ -Long.prototype.add = function(other) { - // Divide each number into 4 chunks of 16 bits, and then sum the chunks. - - var a48 = this.high_ >>> 16; - var a32 = this.high_ & 0xFFFF; - var a16 = this.low_ >>> 16; - var a00 = this.low_ & 0xFFFF; - - var b48 = other.high_ >>> 16; - var b32 = other.high_ & 0xFFFF; - var b16 = other.low_ >>> 16; - var b00 = other.low_ & 0xFFFF; - - var c48 = 0, c32 = 0, c16 = 0, c00 = 0; - c00 += a00 + b00; - c16 += c00 >>> 16; - c00 &= 0xFFFF; - c16 += a16 + b16; - c32 += c16 >>> 16; - c16 &= 0xFFFF; - c32 += a32 + b32; - c48 += c32 >>> 16; - c32 &= 0xFFFF; - c48 += a48 + b48; - c48 &= 0xFFFF; - return Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32); -}; - -/** - * Returns the difference of this and the given Long. - * - * @param {Long} other Long to subtract from this. - * @return {Long} the difference of this and the given Long. - * @api public - */ -Long.prototype.subtract = function(other) { - return this.add(other.negate()); -}; - -/** - * Returns the product of this and the given Long. - * - * @param {Long} other Long to multiply with this. - * @return {Long} the product of this and the other. - * @api public - */ -Long.prototype.multiply = function(other) { - if (this.isZero()) { - return Long.ZERO; - } else if (other.isZero()) { - return Long.ZERO; - } - - if (this.equals(Long.MIN_VALUE)) { - return other.isOdd() ? Long.MIN_VALUE : Long.ZERO; - } else if (other.equals(Long.MIN_VALUE)) { - return this.isOdd() ? Long.MIN_VALUE : Long.ZERO; - } - - if (this.isNegative()) { - if (other.isNegative()) { - return this.negate().multiply(other.negate()); - } else { - return this.negate().multiply(other).negate(); - } - } else if (other.isNegative()) { - return this.multiply(other.negate()).negate(); - } - - // If both Longs are small, use float multiplication - if (this.lessThan(Long.TWO_PWR_24_) && - other.lessThan(Long.TWO_PWR_24_)) { - return Long.fromNumber(this.toNumber() * other.toNumber()); - } - - // Divide each Long into 4 chunks of 16 bits, and then add up 4x4 products. - // We can skip products that would overflow. - - var a48 = this.high_ >>> 16; - var a32 = this.high_ & 0xFFFF; - var a16 = this.low_ >>> 16; - var a00 = this.low_ & 0xFFFF; - - var b48 = other.high_ >>> 16; - var b32 = other.high_ & 0xFFFF; - var b16 = other.low_ >>> 16; - var b00 = other.low_ & 0xFFFF; - - var c48 = 0, c32 = 0, c16 = 0, c00 = 0; - c00 += a00 * b00; - c16 += c00 >>> 16; - c00 &= 0xFFFF; - c16 += a16 * b00; - c32 += c16 >>> 16; - c16 &= 0xFFFF; - c16 += a00 * b16; - c32 += c16 >>> 16; - c16 &= 0xFFFF; - c32 += a32 * b00; - c48 += c32 >>> 16; - c32 &= 0xFFFF; - c32 += a16 * b16; - c48 += c32 >>> 16; - c32 &= 0xFFFF; - c32 += a00 * b32; - c48 += c32 >>> 16; - c32 &= 0xFFFF; - c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48; - c48 &= 0xFFFF; - return Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32); -}; - -/** - * Returns this Long divided by the given one. - * - * @param {Long} other Long by which to divide. - * @return {Long} this Long divided by the given one. - * @api public - */ -Long.prototype.div = function(other) { - if (other.isZero()) { - throw Error('division by zero'); - } else if (this.isZero()) { - return Long.ZERO; - } - - if (this.equals(Long.MIN_VALUE)) { - if (other.equals(Long.ONE) || - other.equals(Long.NEG_ONE)) { - return Long.MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE - } else if (other.equals(Long.MIN_VALUE)) { - return Long.ONE; - } else { - // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|. - var halfThis = this.shiftRight(1); - var approx = halfThis.div(other).shiftLeft(1); - if (approx.equals(Long.ZERO)) { - return other.isNegative() ? Long.ONE : Long.NEG_ONE; - } else { - var rem = this.subtract(other.multiply(approx)); - var result = approx.add(rem.div(other)); - return result; - } - } - } else if (other.equals(Long.MIN_VALUE)) { - return Long.ZERO; - } - - if (this.isNegative()) { - if (other.isNegative()) { - return this.negate().div(other.negate()); - } else { - return this.negate().div(other).negate(); - } - } else if (other.isNegative()) { - return this.div(other.negate()).negate(); - } - - // Repeat the following until the remainder is less than other: find a - // floating-point that approximates remainder / other *from below*, add this - // into the result, and subtract it from the remainder. It is critical that - // the approximate value is less than or equal to the real value so that the - // remainder never becomes negative. - var res = Long.ZERO; - var rem = this; - while (rem.greaterThanOrEqual(other)) { - // Approximate the result of division. This may be a little greater or - // smaller than the actual value. - var approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber())); - - // We will tweak the approximate result by changing it in the 48-th digit or - // the smallest non-fractional digit, whichever is larger. - var log2 = Math.ceil(Math.log(approx) / Math.LN2); - var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48); - - // Decrease the approximation until it is smaller than the remainder. Note - // that if it is too large, the product overflows and is negative. - var approxRes = Long.fromNumber(approx); - var approxRem = approxRes.multiply(other); - while (approxRem.isNegative() || approxRem.greaterThan(rem)) { - approx -= delta; - approxRes = Long.fromNumber(approx); - approxRem = approxRes.multiply(other); - } - - // We know the answer can't be zero... and actually, zero would cause - // infinite recursion since we would make no progress. - if (approxRes.isZero()) { - approxRes = Long.ONE; - } - - res = res.add(approxRes); - rem = rem.subtract(approxRem); - } - return res; -}; - -/** - * Returns this Long modulo the given one. - * - * @param {Long} other Long by which to mod. - * @return {Long} this Long modulo the given one. - * @api public - */ -Long.prototype.modulo = function(other) { - return this.subtract(this.div(other).multiply(other)); -}; - -/** - * The bitwise-NOT of this value. - * - * @return {Long} the bitwise-NOT of this value. - * @api public - */ -Long.prototype.not = function() { - return Long.fromBits(~this.low_, ~this.high_); -}; - -/** - * Returns the bitwise-AND of this Long and the given one. - * - * @param {Long} other the Long with which to AND. - * @return {Long} the bitwise-AND of this and the other. - * @api public - */ -Long.prototype.and = function(other) { - return Long.fromBits(this.low_ & other.low_, this.high_ & other.high_); -}; - -/** - * Returns the bitwise-OR of this Long and the given one. - * - * @param {Long} other the Long with which to OR. - * @return {Long} the bitwise-OR of this and the other. - * @api public - */ -Long.prototype.or = function(other) { - return Long.fromBits(this.low_ | other.low_, this.high_ | other.high_); -}; - -/** - * Returns the bitwise-XOR of this Long and the given one. - * - * @param {Long} other the Long with which to XOR. - * @return {Long} the bitwise-XOR of this and the other. - * @api public - */ -Long.prototype.xor = function(other) { - return Long.fromBits(this.low_ ^ other.low_, this.high_ ^ other.high_); -}; - -/** - * Returns this Long with bits shifted to the left by the given amount. - * - * @param {Number} numBits the number of bits by which to shift. - * @return {Long} this shifted to the left by the given amount. - * @api public - */ -Long.prototype.shiftLeft = function(numBits) { - numBits &= 63; - if (numBits == 0) { - return this; - } else { - var low = this.low_; - if (numBits < 32) { - var high = this.high_; - return Long.fromBits( - low << numBits, - (high << numBits) | (low >>> (32 - numBits))); - } else { - return Long.fromBits(0, low << (numBits - 32)); - } - } -}; - -/** - * Returns this Long with bits shifted to the right by the given amount. - * - * @param {Number} numBits the number of bits by which to shift. - * @return {Long} this shifted to the right by the given amount. - * @api public - */ -Long.prototype.shiftRight = function(numBits) { - numBits &= 63; - if (numBits == 0) { - return this; - } else { - var high = this.high_; - if (numBits < 32) { - var low = this.low_; - return Long.fromBits( - (low >>> numBits) | (high << (32 - numBits)), - high >> numBits); - } else { - return Long.fromBits( - high >> (numBits - 32), - high >= 0 ? 0 : -1); - } - } -}; - -/** - * Returns this Long with bits shifted to the right by the given amount, with the new top bits matching the current sign bit. - * - * @param {Number} numBits the number of bits by which to shift. - * @return {Long} this shifted to the right by the given amount, with zeros placed into the new leading bits. - * @api public - */ -Long.prototype.shiftRightUnsigned = function(numBits) { - numBits &= 63; - if (numBits == 0) { - return this; - } else { - var high = this.high_; - if (numBits < 32) { - var low = this.low_; - return Long.fromBits( - (low >>> numBits) | (high << (32 - numBits)), - high >>> numBits); - } else if (numBits == 32) { - return Long.fromBits(high, 0); - } else { - return Long.fromBits(high >>> (numBits - 32), 0); - } - } -}; - -/** - * Returns a Long representing the given (32-bit) integer value. - * - * @param {Number} value the 32-bit integer in question. - * @return {Long} the corresponding Long value. - * @api public - */ -Long.fromInt = function(value) { - if (-128 <= value && value < 128) { - var cachedObj = Long.INT_CACHE_[value]; - if (cachedObj) { - return cachedObj; - } - } - - var obj = new Long(value | 0, value < 0 ? -1 : 0); - if (-128 <= value && value < 128) { - Long.INT_CACHE_[value] = obj; - } - return obj; -}; - -/** - * Returns a Long representing the given value, provided that it is a finite number. Otherwise, zero is returned. - * - * @param {Number} value the number in question. - * @return {Long} the corresponding Long value. - * @api public - */ -Long.fromNumber = function(value) { - if (isNaN(value) || !isFinite(value)) { - return Long.ZERO; - } else if (value <= -Long.TWO_PWR_63_DBL_) { - return Long.MIN_VALUE; - } else if (value + 1 >= Long.TWO_PWR_63_DBL_) { - return Long.MAX_VALUE; - } else if (value < 0) { - return Long.fromNumber(-value).negate(); - } else { - return new Long( - (value % Long.TWO_PWR_32_DBL_) | 0, - (value / Long.TWO_PWR_32_DBL_) | 0); - } -}; - -/** - * Returns a Long representing the 64-bit integer that comes by concatenating the given high and low bits. Each is assumed to use 32 bits. - * - * @param {Number} lowBits the low 32-bits. - * @param {Number} highBits the high 32-bits. - * @return {Long} the corresponding Long value. - * @api public - */ -Long.fromBits = function(lowBits, highBits) { - return new Long(lowBits, highBits); -}; - -/** - * Returns a Long representation of the given string, written using the given radix. - * - * @param {String} str the textual representation of the Long. - * @param {Number} opt_radix the radix in which the text is written. - * @return {Long} the corresponding Long value. - * @api public - */ -Long.fromString = function(str, opt_radix) { - if (str.length == 0) { - throw Error('number format error: empty string'); - } - - var radix = opt_radix || 10; - if (radix < 2 || 36 < radix) { - throw Error('radix out of range: ' + radix); - } - - if (str.charAt(0) == '-') { - return Long.fromString(str.substring(1), radix).negate(); - } else if (str.indexOf('-') >= 0) { - throw Error('number format error: interior "-" character: ' + str); - } - - // Do several (8) digits each time through the loop, so as to - // minimize the calls to the very expensive emulated div. - var radixToPower = Long.fromNumber(Math.pow(radix, 8)); - - var result = Long.ZERO; - for (var i = 0; i < str.length; i += 8) { - var size = Math.min(8, str.length - i); - var value = parseInt(str.substring(i, i + size), radix); - if (size < 8) { - var power = Long.fromNumber(Math.pow(radix, size)); - result = result.multiply(power).add(Long.fromNumber(value)); - } else { - result = result.multiply(radixToPower); - result = result.add(Long.fromNumber(value)); - } - } - return result; -}; - -// NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the -// from* methods on which they depend. - - -/** - * A cache of the Long representations of small integer values. - * @type {Object} - * @api private - */ -Long.INT_CACHE_ = {}; - -// NOTE: the compiler should inline these constant values below and then remove -// these variables, so there should be no runtime penalty for these. - -/** - * Number used repeated below in calculations. This must appear before the - * first call to any from* function below. - * @type {number} - * @api private - */ -Long.TWO_PWR_16_DBL_ = 1 << 16; - -/** - * @type {number} - * @api private - */ -Long.TWO_PWR_24_DBL_ = 1 << 24; - -/** - * @type {number} - * @api private - */ -Long.TWO_PWR_32_DBL_ = Long.TWO_PWR_16_DBL_ * Long.TWO_PWR_16_DBL_; - -/** - * @type {number} - * @api private - */ -Long.TWO_PWR_31_DBL_ = Long.TWO_PWR_32_DBL_ / 2; - -/** - * @type {number} - * @api private - */ -Long.TWO_PWR_48_DBL_ = Long.TWO_PWR_32_DBL_ * Long.TWO_PWR_16_DBL_; - -/** - * @type {number} - * @api private - */ -Long.TWO_PWR_64_DBL_ = Long.TWO_PWR_32_DBL_ * Long.TWO_PWR_32_DBL_; - -/** - * @type {number} - * @api private - */ -Long.TWO_PWR_63_DBL_ = Long.TWO_PWR_64_DBL_ / 2; - -/** @type {Long} */ -Long.ZERO = Long.fromInt(0); - -/** @type {Long} */ -Long.ONE = Long.fromInt(1); - -/** @type {Long} */ -Long.NEG_ONE = Long.fromInt(-1); - -/** @type {Long} */ -Long.MAX_VALUE = - Long.fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0); - -/** @type {Long} */ -Long.MIN_VALUE = Long.fromBits(0, 0x80000000 | 0); - -/** - * @type {Long} - * @api private - */ -Long.TWO_PWR_24_ = Long.fromInt(1 << 24); - -/** - * Expose. - */ -exports.Long = Long; \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/bson/lib/bson/max_key.js b/node_modules/mongodb/node_modules/bson/lib/bson/max_key.js deleted file mode 100644 index 0825408..0000000 --- a/node_modules/mongodb/node_modules/bson/lib/bson/max_key.js +++ /dev/null @@ -1,13 +0,0 @@ -/** - * A class representation of the BSON MaxKey type. - * - * @class Represents the BSON MaxKey type. - * @return {MaxKey} - */ -function MaxKey() { - if(!(this instanceof MaxKey)) return new MaxKey(); - - this._bsontype = 'MaxKey'; -} - -exports.MaxKey = MaxKey; \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/bson/lib/bson/min_key.js b/node_modules/mongodb/node_modules/bson/lib/bson/min_key.js deleted file mode 100644 index 230c2e6..0000000 --- a/node_modules/mongodb/node_modules/bson/lib/bson/min_key.js +++ /dev/null @@ -1,13 +0,0 @@ -/** - * A class representation of the BSON MinKey type. - * - * @class Represents the BSON MinKey type. - * @return {MinKey} - */ -function MinKey() { - if(!(this instanceof MinKey)) return new MinKey(); - - this._bsontype = 'MinKey'; -} - -exports.MinKey = MinKey; \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/bson/lib/bson/objectid.js b/node_modules/mongodb/node_modules/bson/lib/bson/objectid.js deleted file mode 100644 index 52e7197..0000000 --- a/node_modules/mongodb/node_modules/bson/lib/bson/objectid.js +++ /dev/null @@ -1,266 +0,0 @@ -/** - * Module dependencies. - */ -var BinaryParser = require('./binary_parser').BinaryParser; - -/** - * Machine id. - * - * Create a random 3-byte value (i.e. unique for this - * process). Other drivers use a md5 of the machine id here, but - * that would mean an asyc call to gethostname, so we don't bother. - */ -var MACHINE_ID = parseInt(Math.random() * 0xFFFFFF, 10); - -// Regular expression that checks for hex value -var checkForHexRegExp = new RegExp("^[0-9a-fA-F]{24}$"); - -/** -* Create a new ObjectID instance -* -* @class Represents the BSON ObjectID type -* @param {String|Number} id Can be a 24 byte hex string, 12 byte binary string or a Number. -* @return {Object} instance of ObjectID. -*/ -var ObjectID = function ObjectID(id) { - if(!(this instanceof ObjectID)) return new ObjectID(id); - if((id instanceof ObjectID)) return id; - - this._bsontype = 'ObjectID'; - var __id = null; - var valid = ObjectID.isValid(id); - - // Throw an error if it's not a valid setup - if(!valid && id != null){ - throw new Error("Argument passed in must be a single String of 12 bytes or a string of 24 hex characters"); - } else if(valid && typeof id == 'string' && id.length == 24) { - return ObjectID.createFromHexString(id); - } else if(id == null || typeof id == 'number') { - // convert to 12 byte binary string - this.id = this.generate(id); - } else if(id != null && id.length === 12) { - // assume 12 byte string - this.id = id; - } - - if(ObjectID.cacheHexString) this.__id = this.toHexString(); -}; - -// Allow usage of ObjectId as well as ObjectID -var ObjectId = ObjectID; - -// Precomputed hex table enables speedy hex string conversion -var hexTable = []; -for (var i = 0; i < 256; i++) { - hexTable[i] = (i <= 15 ? '0' : '') + i.toString(16); -} - -/** -* Return the ObjectID id as a 24 byte hex string representation -* -* @return {String} return the 24 byte hex string representation. -* @api public -*/ -ObjectID.prototype.toHexString = function() { - if(ObjectID.cacheHexString && this.__id) return this.__id; - - var hexString = ''; - - for (var i = 0; i < this.id.length; i++) { - hexString += hexTable[this.id.charCodeAt(i)]; - } - - if(ObjectID.cacheHexString) this.__id = hexString; - return hexString; -}; - -/** -* Update the ObjectID index used in generating new ObjectID's on the driver -* -* @return {Number} returns next index value. -* @api private -*/ -ObjectID.prototype.get_inc = function() { - return ObjectID.index = (ObjectID.index + 1) % 0xFFFFFF; -}; - -/** -* Update the ObjectID index used in generating new ObjectID's on the driver -* -* @return {Number} returns next index value. -* @api private -*/ -ObjectID.prototype.getInc = function() { - return this.get_inc(); -}; - -/** -* Generate a 12 byte id string used in ObjectID's -* -* @param {Number} [time] optional parameter allowing to pass in a second based timestamp. -* @return {String} return the 12 byte id binary string. -* @api private -*/ -ObjectID.prototype.generate = function(time) { - if ('number' != typeof time) { - time = parseInt(Date.now()/1000,10); - } - - var time4Bytes = BinaryParser.encodeInt(time, 32, true, true); - /* for time-based ObjectID the bytes following the time will be zeroed */ - var machine3Bytes = BinaryParser.encodeInt(MACHINE_ID, 24, false); - var pid2Bytes = BinaryParser.fromShort(typeof process === 'undefined' ? Math.floor(Math.random() * 100000) : process.pid); - var index3Bytes = BinaryParser.encodeInt(this.get_inc(), 24, false, true); - - return time4Bytes + machine3Bytes + pid2Bytes + index3Bytes; -}; - -/** -* Converts the id into a 24 byte hex string for printing -* -* @return {String} return the 24 byte hex string representation. -* @api private -*/ -ObjectID.prototype.toString = function() { - return this.toHexString(); -}; - -/** -* Converts to a string representation of this Id. -* -* @return {String} return the 24 byte hex string representation. -* @api private -*/ -ObjectID.prototype.inspect = ObjectID.prototype.toString; - -/** -* Converts to its JSON representation. -* -* @return {String} return the 24 byte hex string representation. -* @api private -*/ -ObjectID.prototype.toJSON = function() { - return this.toHexString(); -}; - -/** -* Compares the equality of this ObjectID with `otherID`. -* -* @param {Object} otherID ObjectID instance to compare against. -* @return {Bool} the result of comparing two ObjectID's -* @api public -*/ -ObjectID.prototype.equals = function equals (otherID) { - if(otherID == null) return false; - var id = (otherID instanceof ObjectID || otherID.toHexString) - ? otherID.id - : ObjectID.createFromHexString(otherID).id; - - return this.id === id; -} - -/** -* Returns the generation date (accurate up to the second) that this ID was generated. -* -* @return {Date} the generation date -* @api public -*/ -ObjectID.prototype.getTimestamp = function() { - var timestamp = new Date(); - timestamp.setTime(Math.floor(BinaryParser.decodeInt(this.id.substring(0,4), 32, true, true)) * 1000); - return timestamp; -} - -/** -* @ignore -* @api private -*/ -ObjectID.index = parseInt(Math.random() * 0xFFFFFF, 10); - -ObjectID.createPk = function createPk () { - return new ObjectID(); -}; - -/** -* Creates an ObjectID from a second based number, with the rest of the ObjectID zeroed out. Used for comparisons or sorting the ObjectID. -* -* @param {Number} time an integer number representing a number of seconds. -* @return {ObjectID} return the created ObjectID -* @api public -*/ -ObjectID.createFromTime = function createFromTime (time) { - var id = BinaryParser.encodeInt(time, 32, true, true) + - BinaryParser.encodeInt(0, 64, true, true); - return new ObjectID(id); -}; - -/** -* Creates an ObjectID from a hex string representation of an ObjectID. -* -* @param {String} hexString create a ObjectID from a passed in 24 byte hexstring. -* @return {ObjectID} return the created ObjectID -* @api public -*/ -ObjectID.createFromHexString = function createFromHexString (hexString) { - // Throw an error if it's not a valid setup - if(typeof hexString === 'undefined' || hexString != null && hexString.length != 24) - throw new Error("Argument passed in must be a single String of 12 bytes or a string of 24 hex characters"); - - var len = hexString.length; - - if(len > 12*2) { - throw new Error('Id cannot be longer than 12 bytes'); - } - - var result = '' - , string - , number; - - for (var index = 0; index < len; index += 2) { - string = hexString.substr(index, 2); - number = parseInt(string, 16); - result += BinaryParser.fromByte(number); - } - - return new ObjectID(result, hexString); -}; - -/** -* Checks if a value is a valid bson ObjectId -* -* @return {Boolean} return true if the value is a valid bson ObjectId, return false otherwise. -* @api public -*/ -ObjectID.isValid = function isValid(id) { - if(id == null) return false; - - if(id != null && 'number' != typeof id && (id.length != 12 && id.length != 24)) { - return false; - } else { - // Check specifically for hex correctness - if(typeof id == 'string' && id.length == 24) return checkForHexRegExp.test(id); - return true; - } -}; - -/** -* @ignore -*/ -Object.defineProperty(ObjectID.prototype, "generationTime", { - enumerable: true - , get: function () { - return Math.floor(BinaryParser.decodeInt(this.id.substring(0,4), 32, true, true)); - } - , set: function (value) { - var value = BinaryParser.encodeInt(value, 32, true, true); - this.id = value + this.id.substr(4); - // delete this.__id; - this.toHexString(); - } -}); - -/** - * Expose. - */ -exports.ObjectID = ObjectID; -exports.ObjectId = ObjectID; diff --git a/node_modules/mongodb/node_modules/bson/lib/bson/symbol.js b/node_modules/mongodb/node_modules/bson/lib/bson/symbol.js deleted file mode 100644 index 8e2838d..0000000 --- a/node_modules/mongodb/node_modules/bson/lib/bson/symbol.js +++ /dev/null @@ -1,48 +0,0 @@ -/** - * A class representation of the BSON Symbol type. - * - * @class Represents the BSON Symbol type. - * @param {String} value the string representing the symbol. - * @return {Symbol} - */ -function Symbol(value) { - if(!(this instanceof Symbol)) return new Symbol(value); - this._bsontype = 'Symbol'; - this.value = value; -} - -/** - * Access the wrapped string value. - * - * @return {String} returns the wrapped string. - * @api public - */ -Symbol.prototype.valueOf = function() { - return this.value; -}; - -/** - * @ignore - * @api private - */ -Symbol.prototype.toString = function() { - return this.value; -} - -/** - * @ignore - * @api private - */ -Symbol.prototype.inspect = function() { - return this.value; -} - -/** - * @ignore - * @api private - */ -Symbol.prototype.toJSON = function() { - return this.value; -} - -exports.Symbol = Symbol; \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/bson/lib/bson/timestamp.js b/node_modules/mongodb/node_modules/bson/lib/bson/timestamp.js deleted file mode 100644 index c650d15..0000000 --- a/node_modules/mongodb/node_modules/bson/lib/bson/timestamp.js +++ /dev/null @@ -1,853 +0,0 @@ -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Copyright 2009 Google Inc. All Rights Reserved - -/** - * Defines a Timestamp class for representing a 64-bit two's-complement - * integer value, which faithfully simulates the behavior of a Java "Timestamp". This - * implementation is derived from TimestampLib in GWT. - * - * Constructs a 64-bit two's-complement integer, given its low and high 32-bit - * values as *signed* integers. See the from* functions below for more - * convenient ways of constructing Timestamps. - * - * The internal representation of a Timestamp is the two given signed, 32-bit values. - * We use 32-bit pieces because these are the size of integers on which - * Javascript performs bit-operations. For operations like addition and - * multiplication, we split each number into 16-bit pieces, which can easily be - * multiplied within Javascript's floating-point representation without overflow - * or change in sign. - * - * In the algorithms below, we frequently reduce the negative case to the - * positive case by negating the input(s) and then post-processing the result. - * Note that we must ALWAYS check specially whether those values are MIN_VALUE - * (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as - * a positive number, it overflows back into a negative). Not handling this - * case would often result in infinite recursion. - * - * @class Represents the BSON Timestamp type. - * @param {Number} low the low (signed) 32 bits of the Timestamp. - * @param {Number} high the high (signed) 32 bits of the Timestamp. - */ -function Timestamp(low, high) { - if(!(this instanceof Timestamp)) return new Timestamp(low, high); - this._bsontype = 'Timestamp'; - /** - * @type {number} - * @api private - */ - this.low_ = low | 0; // force into 32 signed bits. - - /** - * @type {number} - * @api private - */ - this.high_ = high | 0; // force into 32 signed bits. -}; - -/** - * Return the int value. - * - * @return {Number} the value, assuming it is a 32-bit integer. - * @api public - */ -Timestamp.prototype.toInt = function() { - return this.low_; -}; - -/** - * Return the Number value. - * - * @return {Number} the closest floating-point representation to this value. - * @api public - */ -Timestamp.prototype.toNumber = function() { - return this.high_ * Timestamp.TWO_PWR_32_DBL_ + - this.getLowBitsUnsigned(); -}; - -/** - * Return the JSON value. - * - * @return {String} the JSON representation. - * @api public - */ -Timestamp.prototype.toJSON = function() { - return this.toString(); -} - -/** - * Return the String value. - * - * @param {Number} [opt_radix] the radix in which the text should be written. - * @return {String} the textual representation of this value. - * @api public - */ -Timestamp.prototype.toString = function(opt_radix) { - var radix = opt_radix || 10; - if (radix < 2 || 36 < radix) { - throw Error('radix out of range: ' + radix); - } - - if (this.isZero()) { - return '0'; - } - - if (this.isNegative()) { - if (this.equals(Timestamp.MIN_VALUE)) { - // We need to change the Timestamp value before it can be negated, so we remove - // the bottom-most digit in this base and then recurse to do the rest. - var radixTimestamp = Timestamp.fromNumber(radix); - var div = this.div(radixTimestamp); - var rem = div.multiply(radixTimestamp).subtract(this); - return div.toString(radix) + rem.toInt().toString(radix); - } else { - return '-' + this.negate().toString(radix); - } - } - - // Do several (6) digits each time through the loop, so as to - // minimize the calls to the very expensive emulated div. - var radixToPower = Timestamp.fromNumber(Math.pow(radix, 6)); - - var rem = this; - var result = ''; - while (true) { - var remDiv = rem.div(radixToPower); - var intval = rem.subtract(remDiv.multiply(radixToPower)).toInt(); - var digits = intval.toString(radix); - - rem = remDiv; - if (rem.isZero()) { - return digits + result; - } else { - while (digits.length < 6) { - digits = '0' + digits; - } - result = '' + digits + result; - } - } -}; - -/** - * Return the high 32-bits value. - * - * @return {Number} the high 32-bits as a signed value. - * @api public - */ -Timestamp.prototype.getHighBits = function() { - return this.high_; -}; - -/** - * Return the low 32-bits value. - * - * @return {Number} the low 32-bits as a signed value. - * @api public - */ -Timestamp.prototype.getLowBits = function() { - return this.low_; -}; - -/** - * Return the low unsigned 32-bits value. - * - * @return {Number} the low 32-bits as an unsigned value. - * @api public - */ -Timestamp.prototype.getLowBitsUnsigned = function() { - return (this.low_ >= 0) ? - this.low_ : Timestamp.TWO_PWR_32_DBL_ + this.low_; -}; - -/** - * Returns the number of bits needed to represent the absolute value of this Timestamp. - * - * @return {Number} Returns the number of bits needed to represent the absolute value of this Timestamp. - * @api public - */ -Timestamp.prototype.getNumBitsAbs = function() { - if (this.isNegative()) { - if (this.equals(Timestamp.MIN_VALUE)) { - return 64; - } else { - return this.negate().getNumBitsAbs(); - } - } else { - var val = this.high_ != 0 ? this.high_ : this.low_; - for (var bit = 31; bit > 0; bit--) { - if ((val & (1 << bit)) != 0) { - break; - } - } - return this.high_ != 0 ? bit + 33 : bit + 1; - } -}; - -/** - * Return whether this value is zero. - * - * @return {Boolean} whether this value is zero. - * @api public - */ -Timestamp.prototype.isZero = function() { - return this.high_ == 0 && this.low_ == 0; -}; - -/** - * Return whether this value is negative. - * - * @return {Boolean} whether this value is negative. - * @api public - */ -Timestamp.prototype.isNegative = function() { - return this.high_ < 0; -}; - -/** - * Return whether this value is odd. - * - * @return {Boolean} whether this value is odd. - * @api public - */ -Timestamp.prototype.isOdd = function() { - return (this.low_ & 1) == 1; -}; - -/** - * Return whether this Timestamp equals the other - * - * @param {Timestamp} other Timestamp to compare against. - * @return {Boolean} whether this Timestamp equals the other - * @api public - */ -Timestamp.prototype.equals = function(other) { - return (this.high_ == other.high_) && (this.low_ == other.low_); -}; - -/** - * Return whether this Timestamp does not equal the other. - * - * @param {Timestamp} other Timestamp to compare against. - * @return {Boolean} whether this Timestamp does not equal the other. - * @api public - */ -Timestamp.prototype.notEquals = function(other) { - return (this.high_ != other.high_) || (this.low_ != other.low_); -}; - -/** - * Return whether this Timestamp is less than the other. - * - * @param {Timestamp} other Timestamp to compare against. - * @return {Boolean} whether this Timestamp is less than the other. - * @api public - */ -Timestamp.prototype.lessThan = function(other) { - return this.compare(other) < 0; -}; - -/** - * Return whether this Timestamp is less than or equal to the other. - * - * @param {Timestamp} other Timestamp to compare against. - * @return {Boolean} whether this Timestamp is less than or equal to the other. - * @api public - */ -Timestamp.prototype.lessThanOrEqual = function(other) { - return this.compare(other) <= 0; -}; - -/** - * Return whether this Timestamp is greater than the other. - * - * @param {Timestamp} other Timestamp to compare against. - * @return {Boolean} whether this Timestamp is greater than the other. - * @api public - */ -Timestamp.prototype.greaterThan = function(other) { - return this.compare(other) > 0; -}; - -/** - * Return whether this Timestamp is greater than or equal to the other. - * - * @param {Timestamp} other Timestamp to compare against. - * @return {Boolean} whether this Timestamp is greater than or equal to the other. - * @api public - */ -Timestamp.prototype.greaterThanOrEqual = function(other) { - return this.compare(other) >= 0; -}; - -/** - * Compares this Timestamp with the given one. - * - * @param {Timestamp} other Timestamp to compare against. - * @return {Boolean} 0 if they are the same, 1 if the this is greater, and -1 if the given one is greater. - * @api public - */ -Timestamp.prototype.compare = function(other) { - if (this.equals(other)) { - return 0; - } - - var thisNeg = this.isNegative(); - var otherNeg = other.isNegative(); - if (thisNeg && !otherNeg) { - return -1; - } - if (!thisNeg && otherNeg) { - return 1; - } - - // at this point, the signs are the same, so subtraction will not overflow - if (this.subtract(other).isNegative()) { - return -1; - } else { - return 1; - } -}; - -/** - * The negation of this value. - * - * @return {Timestamp} the negation of this value. - * @api public - */ -Timestamp.prototype.negate = function() { - if (this.equals(Timestamp.MIN_VALUE)) { - return Timestamp.MIN_VALUE; - } else { - return this.not().add(Timestamp.ONE); - } -}; - -/** - * Returns the sum of this and the given Timestamp. - * - * @param {Timestamp} other Timestamp to add to this one. - * @return {Timestamp} the sum of this and the given Timestamp. - * @api public - */ -Timestamp.prototype.add = function(other) { - // Divide each number into 4 chunks of 16 bits, and then sum the chunks. - - var a48 = this.high_ >>> 16; - var a32 = this.high_ & 0xFFFF; - var a16 = this.low_ >>> 16; - var a00 = this.low_ & 0xFFFF; - - var b48 = other.high_ >>> 16; - var b32 = other.high_ & 0xFFFF; - var b16 = other.low_ >>> 16; - var b00 = other.low_ & 0xFFFF; - - var c48 = 0, c32 = 0, c16 = 0, c00 = 0; - c00 += a00 + b00; - c16 += c00 >>> 16; - c00 &= 0xFFFF; - c16 += a16 + b16; - c32 += c16 >>> 16; - c16 &= 0xFFFF; - c32 += a32 + b32; - c48 += c32 >>> 16; - c32 &= 0xFFFF; - c48 += a48 + b48; - c48 &= 0xFFFF; - return Timestamp.fromBits((c16 << 16) | c00, (c48 << 16) | c32); -}; - -/** - * Returns the difference of this and the given Timestamp. - * - * @param {Timestamp} other Timestamp to subtract from this. - * @return {Timestamp} the difference of this and the given Timestamp. - * @api public - */ -Timestamp.prototype.subtract = function(other) { - return this.add(other.negate()); -}; - -/** - * Returns the product of this and the given Timestamp. - * - * @param {Timestamp} other Timestamp to multiply with this. - * @return {Timestamp} the product of this and the other. - * @api public - */ -Timestamp.prototype.multiply = function(other) { - if (this.isZero()) { - return Timestamp.ZERO; - } else if (other.isZero()) { - return Timestamp.ZERO; - } - - if (this.equals(Timestamp.MIN_VALUE)) { - return other.isOdd() ? Timestamp.MIN_VALUE : Timestamp.ZERO; - } else if (other.equals(Timestamp.MIN_VALUE)) { - return this.isOdd() ? Timestamp.MIN_VALUE : Timestamp.ZERO; - } - - if (this.isNegative()) { - if (other.isNegative()) { - return this.negate().multiply(other.negate()); - } else { - return this.negate().multiply(other).negate(); - } - } else if (other.isNegative()) { - return this.multiply(other.negate()).negate(); - } - - // If both Timestamps are small, use float multiplication - if (this.lessThan(Timestamp.TWO_PWR_24_) && - other.lessThan(Timestamp.TWO_PWR_24_)) { - return Timestamp.fromNumber(this.toNumber() * other.toNumber()); - } - - // Divide each Timestamp into 4 chunks of 16 bits, and then add up 4x4 products. - // We can skip products that would overflow. - - var a48 = this.high_ >>> 16; - var a32 = this.high_ & 0xFFFF; - var a16 = this.low_ >>> 16; - var a00 = this.low_ & 0xFFFF; - - var b48 = other.high_ >>> 16; - var b32 = other.high_ & 0xFFFF; - var b16 = other.low_ >>> 16; - var b00 = other.low_ & 0xFFFF; - - var c48 = 0, c32 = 0, c16 = 0, c00 = 0; - c00 += a00 * b00; - c16 += c00 >>> 16; - c00 &= 0xFFFF; - c16 += a16 * b00; - c32 += c16 >>> 16; - c16 &= 0xFFFF; - c16 += a00 * b16; - c32 += c16 >>> 16; - c16 &= 0xFFFF; - c32 += a32 * b00; - c48 += c32 >>> 16; - c32 &= 0xFFFF; - c32 += a16 * b16; - c48 += c32 >>> 16; - c32 &= 0xFFFF; - c32 += a00 * b32; - c48 += c32 >>> 16; - c32 &= 0xFFFF; - c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48; - c48 &= 0xFFFF; - return Timestamp.fromBits((c16 << 16) | c00, (c48 << 16) | c32); -}; - -/** - * Returns this Timestamp divided by the given one. - * - * @param {Timestamp} other Timestamp by which to divide. - * @return {Timestamp} this Timestamp divided by the given one. - * @api public - */ -Timestamp.prototype.div = function(other) { - if (other.isZero()) { - throw Error('division by zero'); - } else if (this.isZero()) { - return Timestamp.ZERO; - } - - if (this.equals(Timestamp.MIN_VALUE)) { - if (other.equals(Timestamp.ONE) || - other.equals(Timestamp.NEG_ONE)) { - return Timestamp.MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE - } else if (other.equals(Timestamp.MIN_VALUE)) { - return Timestamp.ONE; - } else { - // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|. - var halfThis = this.shiftRight(1); - var approx = halfThis.div(other).shiftLeft(1); - if (approx.equals(Timestamp.ZERO)) { - return other.isNegative() ? Timestamp.ONE : Timestamp.NEG_ONE; - } else { - var rem = this.subtract(other.multiply(approx)); - var result = approx.add(rem.div(other)); - return result; - } - } - } else if (other.equals(Timestamp.MIN_VALUE)) { - return Timestamp.ZERO; - } - - if (this.isNegative()) { - if (other.isNegative()) { - return this.negate().div(other.negate()); - } else { - return this.negate().div(other).negate(); - } - } else if (other.isNegative()) { - return this.div(other.negate()).negate(); - } - - // Repeat the following until the remainder is less than other: find a - // floating-point that approximates remainder / other *from below*, add this - // into the result, and subtract it from the remainder. It is critical that - // the approximate value is less than or equal to the real value so that the - // remainder never becomes negative. - var res = Timestamp.ZERO; - var rem = this; - while (rem.greaterThanOrEqual(other)) { - // Approximate the result of division. This may be a little greater or - // smaller than the actual value. - var approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber())); - - // We will tweak the approximate result by changing it in the 48-th digit or - // the smallest non-fractional digit, whichever is larger. - var log2 = Math.ceil(Math.log(approx) / Math.LN2); - var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48); - - // Decrease the approximation until it is smaller than the remainder. Note - // that if it is too large, the product overflows and is negative. - var approxRes = Timestamp.fromNumber(approx); - var approxRem = approxRes.multiply(other); - while (approxRem.isNegative() || approxRem.greaterThan(rem)) { - approx -= delta; - approxRes = Timestamp.fromNumber(approx); - approxRem = approxRes.multiply(other); - } - - // We know the answer can't be zero... and actually, zero would cause - // infinite recursion since we would make no progress. - if (approxRes.isZero()) { - approxRes = Timestamp.ONE; - } - - res = res.add(approxRes); - rem = rem.subtract(approxRem); - } - return res; -}; - -/** - * Returns this Timestamp modulo the given one. - * - * @param {Timestamp} other Timestamp by which to mod. - * @return {Timestamp} this Timestamp modulo the given one. - * @api public - */ -Timestamp.prototype.modulo = function(other) { - return this.subtract(this.div(other).multiply(other)); -}; - -/** - * The bitwise-NOT of this value. - * - * @return {Timestamp} the bitwise-NOT of this value. - * @api public - */ -Timestamp.prototype.not = function() { - return Timestamp.fromBits(~this.low_, ~this.high_); -}; - -/** - * Returns the bitwise-AND of this Timestamp and the given one. - * - * @param {Timestamp} other the Timestamp with which to AND. - * @return {Timestamp} the bitwise-AND of this and the other. - * @api public - */ -Timestamp.prototype.and = function(other) { - return Timestamp.fromBits(this.low_ & other.low_, this.high_ & other.high_); -}; - -/** - * Returns the bitwise-OR of this Timestamp and the given one. - * - * @param {Timestamp} other the Timestamp with which to OR. - * @return {Timestamp} the bitwise-OR of this and the other. - * @api public - */ -Timestamp.prototype.or = function(other) { - return Timestamp.fromBits(this.low_ | other.low_, this.high_ | other.high_); -}; - -/** - * Returns the bitwise-XOR of this Timestamp and the given one. - * - * @param {Timestamp} other the Timestamp with which to XOR. - * @return {Timestamp} the bitwise-XOR of this and the other. - * @api public - */ -Timestamp.prototype.xor = function(other) { - return Timestamp.fromBits(this.low_ ^ other.low_, this.high_ ^ other.high_); -}; - -/** - * Returns this Timestamp with bits shifted to the left by the given amount. - * - * @param {Number} numBits the number of bits by which to shift. - * @return {Timestamp} this shifted to the left by the given amount. - * @api public - */ -Timestamp.prototype.shiftLeft = function(numBits) { - numBits &= 63; - if (numBits == 0) { - return this; - } else { - var low = this.low_; - if (numBits < 32) { - var high = this.high_; - return Timestamp.fromBits( - low << numBits, - (high << numBits) | (low >>> (32 - numBits))); - } else { - return Timestamp.fromBits(0, low << (numBits - 32)); - } - } -}; - -/** - * Returns this Timestamp with bits shifted to the right by the given amount. - * - * @param {Number} numBits the number of bits by which to shift. - * @return {Timestamp} this shifted to the right by the given amount. - * @api public - */ -Timestamp.prototype.shiftRight = function(numBits) { - numBits &= 63; - if (numBits == 0) { - return this; - } else { - var high = this.high_; - if (numBits < 32) { - var low = this.low_; - return Timestamp.fromBits( - (low >>> numBits) | (high << (32 - numBits)), - high >> numBits); - } else { - return Timestamp.fromBits( - high >> (numBits - 32), - high >= 0 ? 0 : -1); - } - } -}; - -/** - * Returns this Timestamp with bits shifted to the right by the given amount, with the new top bits matching the current sign bit. - * - * @param {Number} numBits the number of bits by which to shift. - * @return {Timestamp} this shifted to the right by the given amount, with zeros placed into the new leading bits. - * @api public - */ -Timestamp.prototype.shiftRightUnsigned = function(numBits) { - numBits &= 63; - if (numBits == 0) { - return this; - } else { - var high = this.high_; - if (numBits < 32) { - var low = this.low_; - return Timestamp.fromBits( - (low >>> numBits) | (high << (32 - numBits)), - high >>> numBits); - } else if (numBits == 32) { - return Timestamp.fromBits(high, 0); - } else { - return Timestamp.fromBits(high >>> (numBits - 32), 0); - } - } -}; - -/** - * Returns a Timestamp representing the given (32-bit) integer value. - * - * @param {Number} value the 32-bit integer in question. - * @return {Timestamp} the corresponding Timestamp value. - * @api public - */ -Timestamp.fromInt = function(value) { - if (-128 <= value && value < 128) { - var cachedObj = Timestamp.INT_CACHE_[value]; - if (cachedObj) { - return cachedObj; - } - } - - var obj = new Timestamp(value | 0, value < 0 ? -1 : 0); - if (-128 <= value && value < 128) { - Timestamp.INT_CACHE_[value] = obj; - } - return obj; -}; - -/** - * Returns a Timestamp representing the given value, provided that it is a finite number. Otherwise, zero is returned. - * - * @param {Number} value the number in question. - * @return {Timestamp} the corresponding Timestamp value. - * @api public - */ -Timestamp.fromNumber = function(value) { - if (isNaN(value) || !isFinite(value)) { - return Timestamp.ZERO; - } else if (value <= -Timestamp.TWO_PWR_63_DBL_) { - return Timestamp.MIN_VALUE; - } else if (value + 1 >= Timestamp.TWO_PWR_63_DBL_) { - return Timestamp.MAX_VALUE; - } else if (value < 0) { - return Timestamp.fromNumber(-value).negate(); - } else { - return new Timestamp( - (value % Timestamp.TWO_PWR_32_DBL_) | 0, - (value / Timestamp.TWO_PWR_32_DBL_) | 0); - } -}; - -/** - * Returns a Timestamp representing the 64-bit integer that comes by concatenating the given high and low bits. Each is assumed to use 32 bits. - * - * @param {Number} lowBits the low 32-bits. - * @param {Number} highBits the high 32-bits. - * @return {Timestamp} the corresponding Timestamp value. - * @api public - */ -Timestamp.fromBits = function(lowBits, highBits) { - return new Timestamp(lowBits, highBits); -}; - -/** - * Returns a Timestamp representation of the given string, written using the given radix. - * - * @param {String} str the textual representation of the Timestamp. - * @param {Number} opt_radix the radix in which the text is written. - * @return {Timestamp} the corresponding Timestamp value. - * @api public - */ -Timestamp.fromString = function(str, opt_radix) { - if (str.length == 0) { - throw Error('number format error: empty string'); - } - - var radix = opt_radix || 10; - if (radix < 2 || 36 < radix) { - throw Error('radix out of range: ' + radix); - } - - if (str.charAt(0) == '-') { - return Timestamp.fromString(str.substring(1), radix).negate(); - } else if (str.indexOf('-') >= 0) { - throw Error('number format error: interior "-" character: ' + str); - } - - // Do several (8) digits each time through the loop, so as to - // minimize the calls to the very expensive emulated div. - var radixToPower = Timestamp.fromNumber(Math.pow(radix, 8)); - - var result = Timestamp.ZERO; - for (var i = 0; i < str.length; i += 8) { - var size = Math.min(8, str.length - i); - var value = parseInt(str.substring(i, i + size), radix); - if (size < 8) { - var power = Timestamp.fromNumber(Math.pow(radix, size)); - result = result.multiply(power).add(Timestamp.fromNumber(value)); - } else { - result = result.multiply(radixToPower); - result = result.add(Timestamp.fromNumber(value)); - } - } - return result; -}; - -// NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the -// from* methods on which they depend. - - -/** - * A cache of the Timestamp representations of small integer values. - * @type {Object} - * @api private - */ -Timestamp.INT_CACHE_ = {}; - -// NOTE: the compiler should inline these constant values below and then remove -// these variables, so there should be no runtime penalty for these. - -/** - * Number used repeated below in calculations. This must appear before the - * first call to any from* function below. - * @type {number} - * @api private - */ -Timestamp.TWO_PWR_16_DBL_ = 1 << 16; - -/** - * @type {number} - * @api private - */ -Timestamp.TWO_PWR_24_DBL_ = 1 << 24; - -/** - * @type {number} - * @api private - */ -Timestamp.TWO_PWR_32_DBL_ = Timestamp.TWO_PWR_16_DBL_ * Timestamp.TWO_PWR_16_DBL_; - -/** - * @type {number} - * @api private - */ -Timestamp.TWO_PWR_31_DBL_ = Timestamp.TWO_PWR_32_DBL_ / 2; - -/** - * @type {number} - * @api private - */ -Timestamp.TWO_PWR_48_DBL_ = Timestamp.TWO_PWR_32_DBL_ * Timestamp.TWO_PWR_16_DBL_; - -/** - * @type {number} - * @api private - */ -Timestamp.TWO_PWR_64_DBL_ = Timestamp.TWO_PWR_32_DBL_ * Timestamp.TWO_PWR_32_DBL_; - -/** - * @type {number} - * @api private - */ -Timestamp.TWO_PWR_63_DBL_ = Timestamp.TWO_PWR_64_DBL_ / 2; - -/** @type {Timestamp} */ -Timestamp.ZERO = Timestamp.fromInt(0); - -/** @type {Timestamp} */ -Timestamp.ONE = Timestamp.fromInt(1); - -/** @type {Timestamp} */ -Timestamp.NEG_ONE = Timestamp.fromInt(-1); - -/** @type {Timestamp} */ -Timestamp.MAX_VALUE = - Timestamp.fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0); - -/** @type {Timestamp} */ -Timestamp.MIN_VALUE = Timestamp.fromBits(0, 0x80000000 | 0); - -/** - * @type {Timestamp} - * @api private - */ -Timestamp.TWO_PWR_24_ = Timestamp.fromInt(1 << 24); - -/** - * Expose. - */ -exports.Timestamp = Timestamp; \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/bson/node_modules/nan/.dntrc b/node_modules/mongodb/node_modules/bson/node_modules/nan/.dntrc deleted file mode 100644 index 47971da..0000000 --- a/node_modules/mongodb/node_modules/bson/node_modules/nan/.dntrc +++ /dev/null @@ -1,30 +0,0 @@ -## DNT config file -## see https://github.com/rvagg/dnt - -NODE_VERSIONS="\ - master \ - v0.11.13 \ - v0.10.30 \ - v0.10.29 \ - v0.10.28 \ - v0.10.26 \ - v0.10.25 \ - v0.10.24 \ - v0.10.23 \ - v0.10.22 \ - v0.10.21 \ - v0.10.20 \ - v0.10.19 \ - v0.8.28 \ - v0.8.27 \ - v0.8.26 \ - v0.8.24 \ -" -OUTPUT_PREFIX="nan-" -TEST_CMD=" \ - cd /dnt/ && \ - npm install && \ - node_modules/.bin/node-gyp --nodedir /usr/src/node/ rebuild --directory test && \ - node_modules/.bin/tap --gc test/js/*-test.js \ -" - diff --git a/node_modules/mongodb/node_modules/bson/node_modules/nan/CHANGELOG.md b/node_modules/mongodb/node_modules/bson/node_modules/nan/CHANGELOG.md deleted file mode 100644 index 146cbb5..0000000 --- a/node_modules/mongodb/node_modules/bson/node_modules/nan/CHANGELOG.md +++ /dev/null @@ -1,200 +0,0 @@ -# NAN ChangeLog - -### Version 1.3.0: current Node unstable: 0.11.13, Node stable: 0.10.30 - - -**1.3.0 Aug 2 2014** - - - Added NanNew(std::string) - - Added NanNew(std::string&) - - Added NanAsciiString helper class - - Added NanUtf8String helper class - - Added NanUcs2String helper class - - Deprecated NanRawString() - - Deprecated NanCString() - - Added NanGetIsolateData(v8::Isolate *isolate) - - Added NanMakeCallback(v8::Handle target, v8::Handle func, int argc, v8::Handle* argv) - - Added NanMakeCallback(v8::Handle target, v8::Handle symbol, int argc, v8::Handle* argv) - - Added NanMakeCallback(v8::Handle target, const char* method, int argc, v8::Handle* argv) - - Added NanSetTemplate(v8::Handle templ, v8::Handle name , v8::Handle value, v8::PropertyAttribute attributes) - - Added NanSetPrototypeTemplate(v8::Local templ, v8::Handle name, v8::Handle value, v8::PropertyAttribute attributes) - - Added NanSetInstanceTemplate(v8::Local templ, const char *name, v8::Handle value) - - Added NanSetInstanceTemplate(v8::Local templ, v8::Handle name, v8::Handle value, v8::PropertyAttribute attributes) - -**1.2.0 Jun 5 2014** - - - Add NanSetPrototypeTemplate - - Changed NAN_WEAK_CALLBACK internals, switched _NanWeakCallbackData to class, - introduced _NanWeakCallbackDispatcher - - Removed -Wno-unused-local-typedefs from test builds - - Made test builds Windows compatible ('Sleep()') - -**1.1.2 May 28 2014** - - - Release to fix more stuff-ups in 1.1.1 - -**1.1.1 May 28 2014** - - - Release to fix version mismatch in nan.h and lack of changelog entry for 1.1.0 - -**1.1.0 May 25 2014** - - - Remove nan_isolate, use v8::Isolate::GetCurrent() internally instead - - Additional explicit overloads for NanNew(): (char*,int), (uint8_t*[,int]), - (uint16_t*[,int), double, int, unsigned int, bool, v8::String::ExternalStringResource*, - v8::String::ExternalAsciiStringResource* - - Deprecate NanSymbol() - - Added SetErrorMessage() and ErrorMessage() to NanAsyncWorker - -**1.0.0 May 4 2014** - - - Heavy API changes for V8 3.25 / Node 0.11.13 - - Use cpplint.py - - Removed NanInitPersistent - - Removed NanPersistentToLocal - - Removed NanFromV8String - - Removed NanMakeWeak - - Removed NanNewLocal - - Removed NAN_WEAK_CALLBACK_OBJECT - - Removed NAN_WEAK_CALLBACK_DATA - - Introduce NanNew, replaces NanNewLocal, NanPersistentToLocal, adds many overloaded typed versions - - Introduce NanUndefined, NanNull, NanTrue and NanFalse - - Introduce NanEscapableScope and NanEscapeScope - - Introduce NanMakeWeakPersistent (requires a special callback to work on both old and new node) - - Introduce NanMakeCallback for node::MakeCallback - - Introduce NanSetTemplate - - Introduce NanGetCurrentContext - - Introduce NanCompileScript and NanRunScript - - Introduce NanAdjustExternalMemory - - Introduce NanAddGCEpilogueCallback, NanAddGCPrologueCallback, NanRemoveGCEpilogueCallback, NanRemoveGCPrologueCallback - - Introduce NanGetHeapStatistics - - Rename NanAsyncWorker#SavePersistent() to SaveToPersistent() - -**0.8.0 Jan 9 2014** - - - NanDispose -> NanDisposePersistent, deprecate NanDispose - - Extract _NAN_*_RETURN_TYPE, pull up NAN_*() - -**0.7.1 Jan 9 2014** - - - Fixes to work against debug builds of Node - - Safer NanPersistentToLocal (avoid reinterpret_cast) - - Speed up common NanRawString case by only extracting flattened string when necessary - -**0.7.0 Dec 17 2013** - - - New no-arg form of NanCallback() constructor. - - NanCallback#Call takes Handle rather than Local - - Removed deprecated NanCallback#Run method, use NanCallback#Call instead - - Split off _NAN_*_ARGS_TYPE from _NAN_*_ARGS - - Restore (unofficial) Node 0.6 compatibility at NanCallback#Call() - - Introduce NanRawString() for char* (or appropriate void*) from v8::String - (replacement for NanFromV8String) - - Introduce NanCString() for null-terminated char* from v8::String - -**0.6.0 Nov 21 2013** - - - Introduce NanNewLocal(v8::Handle value) for use in place of - v8::Local::New(...) since v8 started requiring isolate in Node 0.11.9 - -**0.5.2 Nov 16 2013** - - - Convert SavePersistent and GetFromPersistent in NanAsyncWorker from protected and public - -**0.5.1 Nov 12 2013** - - - Use node::MakeCallback() instead of direct v8::Function::Call() - -**0.5.0 Nov 11 2013** - - - Added @TooTallNate as collaborator - - New, much simpler, "include_dirs" for binding.gyp - - Added full range of NAN_INDEX_* macros to match NAN_PROPERTY_* macros - -**0.4.4 Nov 2 2013** - - - Isolate argument from v8::Persistent::MakeWeak removed for 0.11.8+ - -**0.4.3 Nov 2 2013** - - - Include node_object_wrap.h, removed from node.h for Node 0.11.8. - -**0.4.2 Nov 2 2013** - - - Handle deprecation of v8::Persistent::Dispose(v8::Isolate* isolate)) for - Node 0.11.8 release. - -**0.4.1 Sep 16 2013** - - - Added explicit `#include ` as it was removed from node.h for v0.11.8 - -**0.4.0 Sep 2 2013** - - - Added NAN_INLINE and NAN_DEPRECATED and made use of them - - Added NanError, NanTypeError and NanRangeError - - Cleaned up code - -**0.3.2 Aug 30 2013** - - - Fix missing scope declaration in GetFromPersistent() and SaveToPersistent - in NanAsyncWorker - -**0.3.1 Aug 20 2013** - - - fix "not all control paths return a value" compile warning on some platforms - -**0.3.0 Aug 19 2013** - - - Made NAN work with NPM - - Lots of fixes to NanFromV8String, pulling in features from new Node core - - Changed node::encoding to Nan::Encoding in NanFromV8String to unify the API - - Added optional error number argument for NanThrowError() - - Added NanInitPersistent() - - Added NanReturnNull() and NanReturnEmptyString() - - Added NanLocker and NanUnlocker - - Added missing scopes - - Made sure to clear disposed Persistent handles - - Changed NanAsyncWorker to allocate error messages on the heap - - Changed NanThrowError(Local) to NanThrowError(Handle) - - Fixed leak in NanAsyncWorker when errmsg is used - -**0.2.2 Aug 5 2013** - - - Fixed usage of undefined variable with node::BASE64 in NanFromV8String() - -**0.2.1 Aug 5 2013** - - - Fixed 0.8 breakage, node::BUFFER encoding type not available in 0.8 for - NanFromV8String() - -**0.2.0 Aug 5 2013** - - - Added NAN_PROPERTY_GETTER, NAN_PROPERTY_SETTER, NAN_PROPERTY_ENUMERATOR, - NAN_PROPERTY_DELETER, NAN_PROPERTY_QUERY - - Extracted _NAN_METHOD_ARGS, _NAN_GETTER_ARGS, _NAN_SETTER_ARGS, - _NAN_PROPERTY_GETTER_ARGS, _NAN_PROPERTY_SETTER_ARGS, - _NAN_PROPERTY_ENUMERATOR_ARGS, _NAN_PROPERTY_DELETER_ARGS, - _NAN_PROPERTY_QUERY_ARGS - - Added NanGetInternalFieldPointer, NanSetInternalFieldPointer - - Added NAN_WEAK_CALLBACK, NAN_WEAK_CALLBACK_OBJECT, - NAN_WEAK_CALLBACK_DATA, NanMakeWeak - - Renamed THROW_ERROR to _NAN_THROW_ERROR - - Added NanNewBufferHandle(char*, size_t, node::smalloc::FreeCallback, void*) - - Added NanBufferUse(char*, uint32_t) - - Added NanNewContextHandle(v8::ExtensionConfiguration*, - v8::Handle, v8::Handle) - - Fixed broken NanCallback#GetFunction() - - Added optional encoding and size arguments to NanFromV8String() - - Added NanGetPointerSafe() and NanSetPointerSafe() - - Added initial test suite (to be expanded) - - Allow NanUInt32OptionValue to convert any Number object - -**0.1.0 Jul 21 2013** - - - Added `NAN_GETTER`, `NAN_SETTER` - - Added `NanThrowError` with single Local argument - - Added `NanNewBufferHandle` with single uint32_t argument - - Added `NanHasInstance(Persistent&, Handle)` - - Added `Local NanCallback#GetFunction()` - - Added `NanCallback#Call(int, Local[])` - - Deprecated `NanCallback#Run(int, Local[])` in favour of Call diff --git a/node_modules/mongodb/node_modules/bson/node_modules/nan/LICENSE b/node_modules/mongodb/node_modules/bson/node_modules/nan/LICENSE deleted file mode 100644 index d502e18..0000000 --- a/node_modules/mongodb/node_modules/bson/node_modules/nan/LICENSE +++ /dev/null @@ -1,46 +0,0 @@ -Copyright 2013, NAN contributors: - - Rod Vagg - - Benjamin Byholm - - Trevor Norris - - Nathan Rajlich - - Brett Lawson - - Ben Noordhuis -(the "Original Author") -All rights reserved. - -MIT +no-false-attribs 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. - -Distributions of all or part of the Software intended to be used -by the recipients as they would use the unmodified Software, -containing modifications that substantially alter, remove, or -disable functionality of the Software, outside of the documented -configuration mechanisms provided by the Software, shall be -modified such that the Original Author's bug reporting email -addresses and urls are either replaced with the contact information -of the parties responsible for the changes, or removed entirely. - -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. - - -Except where noted, this license applies to any and all software -programs and associated documentation files created by the -Original Author, when distributed with the Software. diff --git a/node_modules/mongodb/node_modules/bson/node_modules/nan/README.md b/node_modules/mongodb/node_modules/bson/node_modules/nan/README.md deleted file mode 100644 index 2904a38..0000000 --- a/node_modules/mongodb/node_modules/bson/node_modules/nan/README.md +++ /dev/null @@ -1,1054 +0,0 @@ -Native Abstractions for Node.js -=============================== - -**A header file filled with macro and utility goodness for making add-on development for Node.js easier across versions 0.8, 0.10 and 0.11, and eventually 0.12.** - -***Current version: 1.3.0*** - -*(See [nan.h](https://github.com/rvagg/nan/blob/master/CHANGELOG.md) for complete ChangeLog)* - -[![NPM](https://nodei.co/npm/nan.png?downloads=true)](https://nodei.co/npm/nan/) [![NPM](https://nodei.co/npm-dl/nan.png?months=6)](https://nodei.co/npm/nan/) - -[![Build Status](https://secure.travis-ci.org/rvagg/nan.png)](http://travis-ci.org/rvagg/nan) -[![Build status](https://ci.appveyor.com/api/projects/status/kh73pbm9dsju7fgh)](https://ci.appveyor.com/project/RodVagg/nan) - -Thanks to the crazy changes in V8 (and some in Node core), keeping native addons compiling happily across versions, particularly 0.10 to 0.11/0.12, is a minor nightmare. The goal of this project is to store all logic necessary to develop native Node.js addons without having to inspect `NODE_MODULE_VERSION` and get yourself into a macro-tangle. - -This project also contains some helper utilities that make addon development a bit more pleasant. - - * **[News & Updates](#news)** - * **[Usage](#usage)** - * **[Example](#example)** - * **[API](#api)** - - -## News & Updates - -### Aug-2014: 1.3.0 release - -* `NanCString()` and `NanRawString()` have been deprecated in favour of new NanAsciiString, NanUtf8String and NanUcs2String. These classes manage the underlying memory for you in a safer way than just handing off an allocated array. You should now `*NanAsciiString(handle)` to access the raw `char` data, you can also allocate on the heap if you need to keep a reference. -* Two more NanMakeCallback overloads have been added to for parity with Node core. -* You can now `NanNew(std::string)` (use `NanNew(std::string&)` to pass by reference) -* NanSetTemplate, NanSetPrototypeTemplate and NanSetInstanceTemplate have been added. - -### May-2014: 1.1.0 release - -* We've deprecated `NanSymbol()`, you should just use `NanNew()` now. -* `NanNull()`, `NanUndefined()`, `NanTrue()`, `NanFalse()` all return `Local`s now. -* `nan_isolate` is gone, it was intended to be internal-only but if you were using it then you should switch to `v8::Isolate::GetCurrent()`. -* `NanNew()` has received some additional overload-love so you should be able to give it many kinds of values without specifying the ``. -* Lots of small fixes and additions to expand the V8 API coverage, *use the source, Luke*. - - -### May-2014: Major changes for V8 3.25 / Node 0.11.13 - -Node 0.11.11 and 0.11.12 were both broken releases for native add-ons, you simply can't properly compile against either of them for different reasons. But we now have a 0.11.13 release that jumps a couple of versions of V8 ahead and includes some more, major (traumatic) API changes. - -Because we are now nearing Node 0.12 and estimate that the version of V8 we are using in Node 0.11.13 will be close to the API we get for 0.12, we have taken the opportunity to not only *fix* NAN for 0.11.13 but make some major changes to improve the NAN API. - -We have **removed support for Node 0.11 versions prior to 0.11.13**. As usual, our tests are run against (and pass) the last 5 versions of Node 0.8 and Node 0.10. We also include Node 0.11.13 obviously. - -The major change is something that [Benjamin Byholm](kkoopa) has put many hours in to. We now have a fantastic new `NanNew(args)` interface for creating new `Local`s, this replaces `NanNewLocal()` and much more. If you look in [./nan.h](nan.h) you'll see a large number of overloaded versions of this method. In general you should be able to `NanNew(arguments)` for any type you want to make a `Local` from. This includes `Persistent` types, so we now have a `Local NanNew(const Persistent arg)` to replace `NanPersistentToLocal()`. - -We also now have `NanUndefined()`, `NanNull()`, `NanTrue()` and `NanFalse()`. Mainly because of the new requirement for an `Isolate` argument for each of the native V8 versions of this. - -V8 has now introduced an `EscapableHandleScope` from which you `scope.Escape(Local value)` to *return* a value from a one scope to another. This replaces the standard `HandleScope` and `scope.Close(Local value)`, although `HandleScope` still exists for when you don't need to return a handle to the caller. For NAN we are exposing it as `NanEscapableScope()` and `NanEscapeScope()`, while `NanScope()` is still how you create a new scope that doesn't need to return handles. For older versions of Node/V8, it'll still map to the older `HandleScope` functionality. - -`NanFromV8String()` was deprecated and has now been removed. You should use `NanCString()` or `NanRawString()` instead. - -Because `node::MakeCallback()` now takes an `Isolate`, and because it doesn't exist in older versions of Node, we've introduced `NanMakeCallback()`. You should *always* use this when calling a JavaScript function from C++. - -There's lots more, check out the Changelog in nan.h or look through [#86](https://github.com/rvagg/nan/pull/86) for all the gory details. - -### Dec-2013: NanCString and NanRawString - -Two new functions have been introduced to replace the functionality that's been provided by `NanFromV8String` until now. NanCString has sensible defaults so it's super easy to fetch a null-terminated c-style string out of a `v8::String`. `NanFromV8String` is still around and has defaults that allow you to pass a single handle to fetch a `char*` while `NanRawString` requires a little more attention to arguments. - -### Nov-2013: Node 0.11.9+ breaking V8 change - -The version of V8 that's shipping with Node 0.11.9+ has changed the signature for new `Local`s to: `v8::Local::New(isolate, value)`, i.e. introducing the `isolate` argument and therefore breaking all new `Local` declarations for previous versions. NAN 0.6+ now includes a `NanNewLocal(value)` that can be used in place to work around this incompatibility and maintain compatibility with 0.8->0.11.9+ (minus a few early 0.11 releases). - -For example, if you wanted to return a `null` on a callback you will have to change the argument from `v8::Local::New(v8::Null())` to `NanNewLocal(v8::Null())`. - -### Nov-2013: Change to binding.gyp `"include_dirs"` for NAN - -Inclusion of NAN in a project's binding.gyp is now greatly simplified. You can now just use `" -## Usage - -Simply add **NAN** as a dependency in the *package.json* of your Node addon: - -``` bash -$ npm install --save nan -``` - -Pull in the path to **NAN** in your *binding.gyp* so that you can use `#include ` in your *.cpp* files: - -``` python -"include_dirs" : [ - "` when compiling your addon. - - -## Example - -See **[LevelDOWN](https://github.com/rvagg/node-leveldown/pull/48)** for a full example of **NAN** in use. - -For a simpler example, see the **[async pi estimation example](https://github.com/rvagg/nan/tree/master/examples/async_pi_estimate)** in the examples directory for full code and an explanation of what this Monte Carlo Pi estimation example does. Below are just some parts of the full example that illustrate the use of **NAN**. - -Compare to the current 0.10 version of this example, found in the [node-addon-examples](https://github.com/rvagg/node-addon-examples/tree/master/9_async_work) repository and also a 0.11 version of the same found [here](https://github.com/kkoopa/node-addon-examples/tree/5c01f58fc993377a567812597e54a83af69686d7/9_async_work). - -Note that there is no embedded version sniffing going on here and also the async work is made much simpler, see below for details on the `NanAsyncWorker` class. - -```c++ -// addon.cc -#include -#include -// ... - -using v8::FunctionTemplate; -using v8::Handle; -using v8::Object; -using v8::String; - -void InitAll(Handle exports) { - exports->Set(NanNew("calculateSync"), - NanNew(CalculateSync)->GetFunction()); - - exports->Set(NanNew("calculateAsync"), - NanNew(CalculateAsync)->GetFunction()); -} - -NODE_MODULE(addon, InitAll) -``` - -```c++ -// sync.h -#include -#include - -NAN_METHOD(CalculateSync); -``` - -```c++ -// sync.cc -#include -#include -#include "./sync.h" -// ... - -using v8::Number; - -// Simple synchronous access to the `Estimate()` function -NAN_METHOD(CalculateSync) { - NanScope(); - - // expect a number as the first argument - int points = args[0]->Uint32Value(); - double est = Estimate(points); - - NanReturnValue(NanNew(est)); -} -``` - -```c++ -// async.h -#include -#include - -NAN_METHOD(CalculateAsync); -``` - -```c++ -// async.cc -#include -#include -#include "./async.h" - -// ... - -using v8::Function; -using v8::Local; -using v8::Null; -using v8::Number; -using v8::Value; - -class PiWorker : public NanAsyncWorker { - public: - PiWorker(NanCallback *callback, int points) - : NanAsyncWorker(callback), points(points) {} - ~PiWorker() {} - - // Executed inside the worker-thread. - // It is not safe to access V8, or V8 data structures - // here, so everything we need for input and output - // should go on `this`. - void Execute () { - estimate = Estimate(points); - } - - // Executed when the async work is complete - // this function will be run inside the main event loop - // so it is safe to use V8 again - void HandleOKCallback () { - NanScope(); - - Local argv[] = { - NanNull() - , NanNew(estimate) - }; - - callback->Call(2, argv); - }; - - private: - int points; - double estimate; -}; - -// Asynchronous access to the `Estimate()` function -NAN_METHOD(CalculateAsync) { - NanScope(); - - int points = args[0]->Uint32Value(); - NanCallback *callback = new NanCallback(args[1].As()); - - NanAsyncQueueWorker(new PiWorker(callback, points)); - NanReturnUndefined(); -} -``` - - -## API - - * NAN_METHOD - * NAN_GETTER - * NAN_SETTER - * NAN_PROPERTY_GETTER - * NAN_PROPERTY_SETTER - * NAN_PROPERTY_ENUMERATOR - * NAN_PROPERTY_DELETER - * NAN_PROPERTY_QUERY - * NAN_INDEX_GETTER - * NAN_INDEX_SETTER - * NAN_INDEX_ENUMERATOR - * NAN_INDEX_DELETER - * NAN_INDEX_QUERY - * NAN_WEAK_CALLBACK - * NAN_DEPRECATED - * NAN_INLINE - * NanNew - * NanUndefined - * NanNull - * NanTrue - * NanFalse - * NanReturnValue - * NanReturnUndefined - * NanReturnNull - * NanReturnEmptyString - * NanScope - * NanEscapableScope - * NanEscapeScope - * NanLocker - * NanUnlocker - * NanGetInternalFieldPointer - * NanSetInternalFieldPointer - * NanObjectWrapHandle - * NanSymbol - * NanGetPointerSafe - * NanSetPointerSafe - * NanRawString - * NanCString - * NanAsciiString - * NanUtf8String - * NanUcs2String - * NanBooleanOptionValue - * NanUInt32OptionValue - * NanError, NanTypeError, NanRangeError - * NanThrowError, NanThrowTypeError, NanThrowRangeError, NanThrowError(Handle), NanThrowError(Handle, int) - * NanNewBufferHandle(char *, size_t, FreeCallback, void *), NanNewBufferHandle(char *, uint32_t), NanNewBufferHandle(uint32_t) - * NanBufferUse(char *, uint32_t) - * NanNewContextHandle - * NanGetCurrentContext - * NanHasInstance - * NanDisposePersistent - * NanAssignPersistent - * NanMakeWeakPersistent - * NanSetTemplate - * NanSetPrototypeTemplate - * NanSetInstanceTemplate - * NanMakeCallback - * NanCompileScript - * NanRunScript - * NanAdjustExternalMemory - * NanAddGCEpilogueCallback - * NanAddGCPrologueCallback - * NanRemoveGCEpilogueCallback - * NanRemoveGCPrologueCallback - * NanGetHeapStatistics - * NanCallback - * NanAsyncWorker - * NanAsyncQueueWorker - - -### NAN_METHOD(methodname) - -Use `NAN_METHOD` to define your V8 accessible methods: - -```c++ -// .h: -class Foo : public node::ObjectWrap { - ... - - static NAN_METHOD(Bar); - static NAN_METHOD(Baz); -} - - -// .cc: -NAN_METHOD(Foo::Bar) { - ... -} - -NAN_METHOD(Foo::Baz) { - ... -} -``` - -The reason for this macro is because of the method signature change in 0.11: - -```c++ -// 0.10 and below: -Handle name(const Arguments& args) - -// 0.11 and above -void name(const FunctionCallbackInfo& args) -``` - -The introduction of `FunctionCallbackInfo` brings additional complications: - - -### NAN_GETTER(methodname) - -Use `NAN_GETTER` to declare your V8 accessible getters. You get a `Local` `property` and an appropriately typed `args` object that can act like the `args` argument to a `NAN_METHOD` call. - -You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_GETTER`. - - -### NAN_SETTER(methodname) - -Use `NAN_SETTER` to declare your V8 accessible setters. Same as `NAN_GETTER` but you also get a `Local` `value` object to work with. - - -### NAN_PROPERTY_GETTER(cbname) -Use `NAN_PROPERTY_GETTER` to declare your V8 accessible property getters. You get a `Local` `property` and an appropriately typed `args` object that can act similar to the `args` argument to a `NAN_METHOD` call. - -You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_PROPERTY_GETTER`. - - -### NAN_PROPERTY_SETTER(cbname) -Use `NAN_PROPERTY_SETTER` to declare your V8 accessible property setters. Same as `NAN_PROPERTY_GETTER` but you also get a `Local` `value` object to work with. - - -### NAN_PROPERTY_ENUMERATOR(cbname) -Use `NAN_PROPERTY_ENUMERATOR` to declare your V8 accessible property enumerators. You get an appropriately typed `args` object like the `args` argument to a `NAN_PROPERTY_GETTER` call. - -You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_PROPERTY_ENUMERATOR`. - - -### NAN_PROPERTY_DELETER(cbname) -Use `NAN_PROPERTY_DELETER` to declare your V8 accessible property deleters. Same as `NAN_PROPERTY_GETTER`. - -You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_PROPERTY_DELETER`. - - -### NAN_PROPERTY_QUERY(cbname) -Use `NAN_PROPERTY_QUERY` to declare your V8 accessible property queries. Same as `NAN_PROPERTY_GETTER`. - -You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_PROPERTY_QUERY`. - - -### NAN_INDEX_GETTER(cbname) -Use `NAN_INDEX_GETTER` to declare your V8 accessible index getters. You get a `uint32_t` `index` and an appropriately typed `args` object that can act similar to the `args` argument to a `NAN_METHOD` call. - -You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_INDEX_GETTER`. - - -### NAN_INDEX_SETTER(cbname) -Use `NAN_INDEX_SETTER` to declare your V8 accessible index setters. Same as `NAN_INDEX_GETTER` but you also get a `Local` `value` object to work with. - - -### NAN_INDEX_ENUMERATOR(cbname) -Use `NAN_INDEX_ENUMERATOR` to declare your V8 accessible index enumerators. You get an appropriately typed `args` object like the `args` argument to a `NAN_INDEX_GETTER` call. - -You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_INDEX_ENUMERATOR`. - - -### NAN_INDEX_DELETER(cbname) -Use `NAN_INDEX_DELETER` to declare your V8 accessible index deleters. Same as `NAN_INDEX_GETTER`. - -You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_INDEX_DELETER`. - - -### NAN_INDEX_QUERY(cbname) -Use `NAN_INDEX_QUERY` to declare your V8 accessible index queries. Same as `NAN_INDEX_GETTER`. - -You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_INDEX_QUERY`. - - -### NAN_WEAK_CALLBACK(cbname) - -Use `NAN_WEAK_CALLBACK` to define your V8 WeakReference callbacks. There is an argument object `const _NanWeakCallbackData &data` allowing access to the weak object and the supplied parameter through its `GetValue` and `GetParameter` methods. You can even access the weak callback info object through the `GetCallbackInfo()`method, but you probably should not. `Revive()` keeps the weak object alive until the next GC round. - -```c++ -NAN_WEAK_CALLBACK(weakCallback) { - int *parameter = data.GetParameter(); - NanMakeCallback(NanGetCurrentContext()->Global(), data.GetValue(), 0, NULL); - if ((*parameter)++ == 0) { - data.Revive(); - } else { - delete parameter; - } -} -``` - - -### NAN_DEPRECATED -Declares a function as deprecated. - -```c++ -static NAN_DEPRECATED NAN_METHOD(foo) { - ... -} -``` - - -### NAN_INLINE -Inlines a function. - -```c++ -NAN_INLINE int foo(int bar) { - ... -} -``` - - -### Local<T> NanNew<T>( ... ) - -Use `NanNew` to construct almost all v8 objects and make new local handles. - -Note: Using NanNew with an std::string is possible, however, you should ensure -to use the overload version (`NanNew(stdString)`) rather than the template -version (`NanNew(stdString)`) as there is an unnecessary -performance penalty to using the template version because of the inability for -compilers to appropriately deduce to reference types on template specialization. - -```c++ -Local s = NanNew("value"); - -... - -Persistent o; - -... - -Local lo = NanNew(o); - -``` - - -### Local<Primitive> NanUndefined() - -Use instead of `Undefined()` - - -### Local<Primitive> NanNull() - -Use instead of `Null()` - - -### Local<Boolean> NanTrue() - -Use instead of `True()` - - -### Local<Boolean> NanFalse() - -Use instead of `False()` - - -### NanReturnValue(Handle<Value>) - -Use `NanReturnValue` when you want to return a value from your V8 accessible method: - -```c++ -NAN_METHOD(Foo::Bar) { - ... - - NanReturnValue(NanNew("FooBar!")); -} -``` - -No `return` statement required. - - -### NanReturnUndefined() - -Use `NanReturnUndefined` when you don't want to return anything from your V8 accessible method: - -```c++ -NAN_METHOD(Foo::Baz) { - ... - - NanReturnUndefined(); -} -``` - - -### NanReturnNull() - -Use `NanReturnNull` when you want to return `Null` from your V8 accessible method: - -```c++ -NAN_METHOD(Foo::Baz) { - ... - - NanReturnNull(); -} -``` - - -### NanReturnEmptyString() - -Use `NanReturnEmptyString` when you want to return an empty `String` from your V8 accessible method: - -```c++ -NAN_METHOD(Foo::Baz) { - ... - - NanReturnEmptyString(); -} -``` - - -### NanScope() - -The introduction of `isolate` references for many V8 calls in Node 0.11 makes `NanScope()` necessary, use it in place of `HandleScope scope` when you do not wish to return handles (`Handle` or `Local`) to the surrounding scope (or in functions directly exposed to V8, as they do not return values in the normal sense): - -```c++ -NAN_METHOD(Foo::Bar) { - NanScope(); - - NanReturnValue(NanNew("FooBar!")); -} -``` - -This method is not directly exposed to V8, nor does it return a handle, so it uses an unescapable scope: - -```c++ -bool Foo::Bar() { - NanScope(); - - Local val = NanFalse(); - ... - return val->Value(); -} -``` - - -### NanEscapableScope() - -The separation of handle scopes into escapable and inescapable scopes makes `NanEscapableScope()` necessary, use it in place of `HandleScope scope` when you later wish to return a handle (`Handle` or `Local`) from the scope, this is for internal functions not directly exposed to V8: - -```c++ -Handle Foo::Bar() { - NanEscapableScope(); - - return NanEscapeScope(NanNew("FooBar!")); -} -``` - - -### Local<T> NanEscapeScope(Handle<T> value); -Use together with `NanEscapableScope` to escape the scope. Corresponds to `HandleScope::Close` or `EscapableHandleScope::Escape`. - - -### NanLocker() - -The introduction of `isolate` references for many V8 calls in Node 0.11 makes `NanLocker()` necessary, use it in place of `Locker locker`: - -```c++ -NAN_METHOD(Foo::Bar) { - NanLocker(); - ... - NanUnlocker(); -} -``` - - -### NanUnlocker() - -The introduction of `isolate` references for many V8 calls in Node 0.11 makes `NanUnlocker()` necessary, use it in place of `Unlocker unlocker`: - -```c++ -NAN_METHOD(Foo::Bar) { - NanLocker(); - ... - NanUnlocker(); -} -``` - - -### void * NanGetInternalFieldPointer(Handle<Object>, int) - -Gets a pointer to the internal field with at `index` from a V8 `Object` handle. - -```c++ -Local obj; -... -NanGetInternalFieldPointer(obj, 0); -``` - -### void NanSetInternalFieldPointer(Handle<Object>, int, void *) - -Sets the value of the internal field at `index` on a V8 `Object` handle. - -```c++ -static Persistent dataWrapperCtor; -... -Local wrapper = NanNew(dataWrapperCtor)->NewInstance(); -NanSetInternalFieldPointer(wrapper, 0, this); -``` - - -### Local<Object> NanObjectWrapHandle(Object) - -When you want to fetch the V8 object handle from a native object you've wrapped with Node's `ObjectWrap`, you should use `NanObjectWrapHandle`: - -```c++ -NanObjectWrapHandle(iterator)->Get(NanNew("end")) -``` - - -### Local<String> NanSymbol(const char *) - -Deprecated. Use `NanNew` instead. -Use to create string symbol objects (i.e. `v8::String::NewSymbol(x)`), for getting and setting object properties, or names of objects. - -```c++ -bool foo = false; -if (obj->Has(NanNew("foo"))) - foo = optionsObj->Get(NanNew("foo"))->BooleanValue() -``` - - -### Type NanGetPointerSafe(Type *[, Type]) - -A helper for getting values from optional pointers. If the pointer is `NULL`, the function returns the optional default value, which defaults to `0`. Otherwise, the function returns the value the pointer points to. - -```c++ -char *plugh(uint32_t *optional) { - char res[] = "xyzzy"; - uint32_t param = NanGetPointerSafe(optional, 0x1337); - switch (param) { - ... - } - NanSetPointerSafe(optional, 0xDEADBEEF); -} -``` - - -### bool NanSetPointerSafe(Type *, Type) - -A helper for setting optional argument pointers. If the pointer is `NULL`, the function simply returns `false`. Otherwise, the value is assigned to the variable the pointer points to. - -```c++ -const char *plugh(size_t *outputsize) { - char res[] = "xyzzy"; - if !(NanSetPointerSafe(outputsize, strlen(res) + 1)) { - ... - } - - ... -} -``` - - -### void* NanRawString(Handle<Value>, enum Nan::Encoding, size_t *, void *, size_t, int) - -Deprecated. Use something else. - -When you want to convert a V8 `String` to a `char*` buffer, use `NanRawString`. You have to supply an encoding as well as a pointer to a variable that will be assigned the number of bytes in the returned string. It is also possible to supply a buffer and its length to the function in order not to have a new buffer allocated. The final argument allows setting `String::WriteOptions`. -Just remember that you'll end up with an object that you'll need to `delete[]` at some point unless you supply your own buffer: - -```c++ -size_t count; -void* decoded = NanRawString(args[1], Nan::BASE64, &count, NULL, 0, String::HINT_MANY_WRITES_EXPECTED); -... -delete[] reinterpret_cast(decoded); -``` - - -### char* NanCString(Handle<Value>, size_t *[, char *, size_t, int]) - -Deprecated. Use `NanUtf8String` instead. - -When you want to convert a V8 `String` to a null-terminated C `char*` use `NanCString`. The resulting `char*` will be UTF-8-encoded, and you need to supply a pointer to a variable that will be assigned the number of bytes in the returned string. It is also possible to supply a buffer and its length to the function in order not to have a new buffer allocated. The final argument allows optionally setting `String::WriteOptions`, which default to `v8::String::NO_OPTIONS`. -Just remember that you'll end up with an object that you'll need to `delete[]` at some point unless you supply your own buffer: - -```c++ -size_t count; -char* name = NanCString(args[0], &count); -... -delete[] name; -``` - - -### NanAsciiString - -Convert a `String` to zero-terminated, Ascii-encoded `char *`. - -```c++ -NAN_METHOD(foo) { - NanScope(); - NanReturnValue(NanNew(*NanAsciiString(arg[0]))); -} -``` - - -### NanUtf8String - -Convert a `String` to zero-terminated, Utf8-encoded `char *`. - -```c++ -NAN_METHOD(foo) { - NanScope(); - NanReturnValue(NanNew(*NanUtf8String(arg[0]))); -} -``` - - -### NanUcs2String - -Convert a `String` to zero-terminated, Ucs2-encoded `uint16_t *`. - -```c++ -NAN_METHOD(foo) { - NanScope(); - NanReturnValue(NanNew(*NanUcs2String(arg[0]))); -} -``` - - -### bool NanBooleanOptionValue(Handle<Value>, Handle<String>[, bool]) - -When you have an "options" object that you need to fetch properties from, boolean options can be fetched with this pair. They check first if the object exists (`IsEmpty`), then if the object has the given property (`Has`) then they get and convert/coerce the property to a `bool`. - -The optional last parameter is the *default* value, which is `false` if left off: - -```c++ -// `foo` is false unless the user supplies a truthy value for it -bool foo = NanBooleanOptionValue(optionsObj, NanNew("foo")); -// `bar` is true unless the user supplies a falsy value for it -bool bar = NanBooleanOptionValueDefTrue(optionsObj, NanNew("bar"), true); -``` - - -### uint32_t NanUInt32OptionValue(Handle<Value>, Handle<String>, uint32_t) - -Similar to `NanBooleanOptionValue`, use `NanUInt32OptionValue` to fetch an integer option from your options object. Can be any kind of JavaScript `Number` and it will be coerced to an unsigned 32-bit integer. - -Requires all 3 arguments as a default is not optional: - -```c++ -uint32_t count = NanUInt32OptionValue(optionsObj, NanNew("count"), 1024); -``` - - -### NanError(message), NanTypeError(message), NanRangeError(message) - -For making `Error`, `TypeError` and `RangeError` objects. - -```c++ -Local res = NanError("you must supply a callback argument"); -``` - - -### NanThrowError(message), NanThrowTypeError(message), NanThrowRangeError(message), NanThrowError(Local<Value>), NanThrowError(Local<Value>, int) - -For throwing `Error`, `TypeError` and `RangeError` objects. - -```c++ -NanThrowError("you must supply a callback argument"); -``` - -Can also handle any custom object you may want to throw. If used with the error code argument, it will add the supplied error code to the error object as a property called `code`. - - -### Local<Object> NanNewBufferHandle(char *, uint32_t), Local<Object> NanNewBufferHandle(uint32_t) - -The `Buffer` API has changed a little in Node 0.11, this helper provides consistent access to `Buffer` creation: - -```c++ -NanNewBufferHandle((char*)value.data(), value.size()); -``` - -Can also be used to initialize a `Buffer` with just a `size` argument. - -Can also be supplied with a `NanFreeCallback` and a hint for the garbage collector. - - -### Local<Object> NanBufferUse(char*, uint32_t) - -`Buffer::New(char*, uint32_t)` prior to 0.11 would make a copy of the data. -While it was possible to get around this, it required a shim by passing a -callback. So the new API `Buffer::Use(char*, uint32_t)` was introduced to remove -needing to use this shim. - -`NanBufferUse` uses the `char*` passed as the backing data, and will free the -memory automatically when the weak callback is called. Keep this in mind, as -careless use can lead to "double free or corruption" and other cryptic failures. - - -### bool NanHasInstance(Persistent<FunctionTemplate>&, Handle<Value>) - -Can be used to check the type of an object to determine it is of a particular class you have already defined and have a `Persistent` handle for. - - -### Local<Context> NanNewContextHandle([ExtensionConfiguration*, Handle<ObjectTemplate>, Handle<Value>]) -Creates a new `Local` handle. - -```c++ -Local ftmpl = NanNew(); -Local otmpl = ftmpl->InstanceTemplate(); -Local ctx = NanNewContextHandle(NULL, otmpl); -``` - - -### Local<Context> NanGetCurrentContext() - -Gets the current context. - -```c++ -Local ctx = NanGetCurrentContext(); -``` - - -### void NanDisposePersistent(Persistent<T> &) - -Use `NanDisposePersistent` to dispose a `Persistent` handle. - -```c++ -NanDisposePersistent(persistentHandle); -``` - - -### NanAssignPersistent(handle, object) - -Use `NanAssignPersistent` to assign a non-`Persistent` handle to a `Persistent` one. You can no longer just declare a `Persistent` handle and assign directly to it later, you have to `Reset` it in Node 0.11, so this makes it easier. - -In general it is now better to place anything you want to protect from V8's garbage collector as properties of a generic `Object` and then assign that to a `Persistent`. This works in older versions of Node also if you use `NanAssignPersistent`: - -```c++ -Persistent persistentHandle; - -... - -Local obj = NanNew(); -obj->Set(NanNew("key"), keyHandle); // where keyHandle might be a Local -NanAssignPersistent(persistentHandle, obj) -``` - - -### _NanWeakCallbackInfo<T, P>* NanMakeWeakPersistent(Handle<T>, P*, _NanWeakCallbackInfo<T, P>::Callback) - -Creates a weak persistent handle with the supplied parameter and `NAN_WEAK_CALLBACK`. - -```c++ -NAN_WEAK_CALLBACK(weakCallback) { - -... - -} - -Local func; - -... - -int *parameter = new int(0); -NanMakeWeakPersistent(func, parameter, &weakCallback); -``` - - -### NanSetTemplate(templ, name, value [, attributes]) - -Use to add properties on object and function templates. - - -### NanSetPrototypeTemplate(templ, name, value [, attributes]) - -Use to add prototype properties on function templates. - - -### NanSetInstanceTemplate(templ, name, value [, attributes]) - -Use to add instance properties on function templates. - - -### NanMakeCallback(target, func, argc, argv) - -Use instead of `node::MakeCallback` to call javascript functions. This is the only proper way of calling functions. - - -### NanCompileScript(Handle s [, const ScriptOrigin& origin]) - -Use to create new scripts bound to the current context. - - -### NanRunScript(script) - -Use to run both bound and unbound scripts. - - -### NanAdjustExternalMemory(int change_in_bytes) - -Simply does `AdjustAmountOfExternalAllocatedMemory`, note that the argument and returned value have type `int`. - - -### NanAddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type_filter=kGCTypeAll) - -Simply does `AddGCEpilogueCallback` - - -### NanAddGCPrologueCallback(GCPrologueCallback callback, GCType gc_type_filter=kGCTypeAll) - -Simply does `AddGCPrologueCallback` - - -### NanRemoveGCEpilogueCallback(GCEpilogueCallback callback) - -Simply does `RemoveGCEpilogueCallback` - - -### NanRemoveGCPrologueCallback(GCPrologueCallback callback) - -Simply does `RemoveGCPrologueCallback` - - -### NanGetHeapStatistics(HeapStatistics *heap_statistics) - -Simply does `GetHeapStatistics` - - -### NanCallback - -Because of the difficulties imposed by the changes to `Persistent` handles in V8 in Node 0.11, creating `Persistent` versions of your `Handle` is annoyingly tricky. `NanCallback` makes it easier by taking your handle, making it persistent until the `NanCallback` is deleted and even providing a handy `Call()` method to fetch and execute the callback `Function`. - -```c++ -Local callbackHandle = args[0].As(); -NanCallback *callback = new NanCallback(callbackHandle); -// pass `callback` around and it's safe from GC until you: -delete callback; -``` - -You can execute the callback like so: - -```c++ -// no arguments: -callback->Call(0, NULL); - -// an error argument: -Handle argv[] = { - NanError(NanNew("fail!")) -}; -callback->Call(1, argv); - -// a success argument: -Handle argv[] = { - NanNull(), - NanNew("w00t!") -}; -callback->Call(2, argv); -``` - -`NanCallback` also has a `Local GetCallback()` method that you can use -to fetch a local handle to the underlying callback function, as well as a -`void SetFunction(Handle)` for setting the callback on the -`NanCallback`. You can check if a `NanCallback` is empty with the `bool IsEmpty()` method. Additionally a generic constructor is available for using -`NanCallback` without performing heap allocations. - - -### NanAsyncWorker - -`NanAsyncWorker` is an abstract class that you can subclass to have much of the annoying async queuing and handling taken care of for you. It can even store arbitrary V8 objects for you and have them persist while the async work is in progress. - -See a rough outline of the implementation: - -```c++ -class NanAsyncWorker { -public: - NanAsyncWorker (NanCallback *callback); - - // Clean up persistent handles and delete the *callback - virtual ~NanAsyncWorker (); - - // Check the `ErrorMessage()` and call HandleOKCallback() - // or HandleErrorCallback depending on whether it has been set or not - virtual void WorkComplete (); - - // You must implement this to do some async work. If there is an - // error then use `SetErrorMessage()` to set an error message and the callback will - // be passed that string in an Error object - virtual void Execute (); - - // Save a V8 object in a Persistent handle to protect it from GC - void SaveToPersistent(const char *key, Local &obj); - - // Fetch a stored V8 object (don't call from within `Execute()`) - Local GetFromPersistent(const char *key); - - // Get the error message (or NULL) - const char *ErrorMessage(); - - // Set an error message - void SetErrorMessage(const char *msg); - -protected: - // Default implementation calls the callback function with no arguments. - // Override this to return meaningful data - virtual void HandleOKCallback (); - - // Default implementation calls the callback function with an Error object - // wrapping the `errmsg` string - virtual void HandleErrorCallback (); -}; -``` - - -### NanAsyncQueueWorker(NanAsyncWorker *) - -`NanAsyncQueueWorker` will run a `NanAsyncWorker` asynchronously via libuv. Both the *execute* and *after_work* steps are taken care of for you—most of the logic for this is embedded in `NanAsyncWorker`. - -### Contributors - -NAN is only possible due to the excellent work of the following contributors: - - - - - - - - -
Rod VaggGitHub/rvaggTwitter/@rvagg
Benjamin ByholmGitHub/kkoopa-
Trevor NorrisGitHub/trevnorrisTwitter/@trevnorris
Nathan RajlichGitHub/TooTallNateTwitter/@TooTallNate
Brett LawsonGitHub/brett19Twitter/@brett19x
Ben NoordhuisGitHub/bnoordhuisTwitter/@bnoordhuis
- -Licence & copyright ------------------------ - -Copyright (c) 2014 NAN contributors (listed above). - -Native Abstractions for Node.js is licensed under an MIT +no-false-attribs license. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE file for more details. diff --git a/node_modules/mongodb/node_modules/bson/node_modules/nan/appveyor.yml b/node_modules/mongodb/node_modules/bson/node_modules/nan/appveyor.yml deleted file mode 100644 index 657eed6..0000000 --- a/node_modules/mongodb/node_modules/bson/node_modules/nan/appveyor.yml +++ /dev/null @@ -1,32 +0,0 @@ -# http://www.appveyor.com/docs/appveyor-yml - -# Test against these versions of Node.js. -environment: - matrix: - - nodejs_version: "0.8" - - nodejs_version: "0.10" - - nodejs_version: "0.11" - -# Install scripts. (runs after repo cloning) -install: - # Get the latest stable version of Node 0.STABLE.latest - - npm install npm - - move node_modules npm - - ps: Update-NodeJsInstallation (Get-NodeJsLatestBuild $env:nodejs_version) - # Typical npm stuff. - - npm/.bin/npm install - - npm/.bin/npm run rebuild-tests - -# Post-install test scripts. -test_script: - # Output useful info for debugging. - - node --version - - npm --version - - cmd: npm test - -# Don't actually build. -build: off - -# Set build version format here instead of in the admin panel. -version: "{build}" - diff --git a/node_modules/mongodb/node_modules/bson/node_modules/nan/include_dirs.js b/node_modules/mongodb/node_modules/bson/node_modules/nan/include_dirs.js deleted file mode 100644 index 4f1dfb4..0000000 --- a/node_modules/mongodb/node_modules/bson/node_modules/nan/include_dirs.js +++ /dev/null @@ -1 +0,0 @@ -console.log(require('path').relative('.', __dirname)); diff --git a/node_modules/mongodb/node_modules/bson/node_modules/nan/nan.h b/node_modules/mongodb/node_modules/bson/node_modules/nan/nan.h deleted file mode 100644 index 063de4e..0000000 --- a/node_modules/mongodb/node_modules/bson/node_modules/nan/nan.h +++ /dev/null @@ -1,2331 +0,0 @@ -/********************************************************************************** - * NAN - Native Abstractions for Node.js - * - * Copyright (c) 2014 NAN contributors: - * - Rod Vagg - * - Benjamin Byholm - * - Trevor Norris - * - Nathan Rajlich - * - Brett Lawson - * - Ben Noordhuis - * - * MIT +no-false-attribs License - * - * Version 1.3.0: current Node unstable: 0.11.13, Node stable: 0.10.30 - * - * See https://github.com/rvagg/nan for the latest update to this file - **********************************************************************************/ - -#ifndef NAN_H_ -#define NAN_H_ - -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(__GNUC__) && !defined(DEBUG) -# define NAN_INLINE inline __attribute__((always_inline)) -#elif defined(_MSC_VER) && !defined(DEBUG) -# define NAN_INLINE __forceinline -#else -# define NAN_INLINE inline -#endif - -#if defined(__GNUC__) && !V8_DISABLE_DEPRECATIONS -# define NAN_DEPRECATED __attribute__((deprecated)) -#elif defined(_MSC_VER) && !V8_DISABLE_DEPRECATIONS -# define NAN_DEPRECATED __declspec(deprecated) -#else -# define NAN_DEPRECATED -#endif - -// some generic helpers - -template NAN_INLINE bool NanSetPointerSafe( - T *var - , T val -) { - if (var) { - *var = val; - return true; - } else { - return false; - } -} - -template NAN_INLINE T NanGetPointerSafe( - T *var - , T fallback = reinterpret_cast(0) -) { - if (var) { - return *var; - } else { - return fallback; - } -} - -NAN_INLINE bool NanBooleanOptionValue( - v8::Local optionsObj - , v8::Handle opt, bool def -) { - if (def) { - return optionsObj.IsEmpty() - || !optionsObj->Has(opt) - || optionsObj->Get(opt)->BooleanValue(); - } else { - return !optionsObj.IsEmpty() - && optionsObj->Has(opt) - && optionsObj->Get(opt)->BooleanValue(); - } -} - -NAN_INLINE bool NanBooleanOptionValue( - v8::Local optionsObj - , v8::Handle opt -) { - return NanBooleanOptionValue(optionsObj, opt, false); -} - -NAN_INLINE uint32_t NanUInt32OptionValue( - v8::Local optionsObj - , v8::Handle opt - , uint32_t def -) { - return !optionsObj.IsEmpty() - && optionsObj->Has(opt) - && optionsObj->Get(opt)->IsNumber() - ? optionsObj->Get(opt)->Uint32Value() - : def; -} - -#if (NODE_MODULE_VERSION > 0x000B) -// Node 0.11+ (0.11.3 and below won't compile with these) - -# define _NAN_METHOD_ARGS_TYPE const v8::FunctionCallbackInfo& -# define _NAN_METHOD_ARGS _NAN_METHOD_ARGS_TYPE args -# define _NAN_METHOD_RETURN_TYPE void - -# define _NAN_GETTER_ARGS_TYPE const v8::PropertyCallbackInfo& -# define _NAN_GETTER_ARGS _NAN_GETTER_ARGS_TYPE args -# define _NAN_GETTER_RETURN_TYPE void - -# define _NAN_SETTER_ARGS_TYPE const v8::PropertyCallbackInfo& -# define _NAN_SETTER_ARGS _NAN_SETTER_ARGS_TYPE args -# define _NAN_SETTER_RETURN_TYPE void - -# define _NAN_PROPERTY_GETTER_ARGS_TYPE \ - const v8::PropertyCallbackInfo& -# define _NAN_PROPERTY_GETTER_ARGS _NAN_PROPERTY_GETTER_ARGS_TYPE args -# define _NAN_PROPERTY_GETTER_RETURN_TYPE void - -# define _NAN_PROPERTY_SETTER_ARGS_TYPE \ - const v8::PropertyCallbackInfo& -# define _NAN_PROPERTY_SETTER_ARGS _NAN_PROPERTY_SETTER_ARGS_TYPE args -# define _NAN_PROPERTY_SETTER_RETURN_TYPE void - -# define _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE \ - const v8::PropertyCallbackInfo& -# define _NAN_PROPERTY_ENUMERATOR_ARGS _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE args -# define _NAN_PROPERTY_ENUMERATOR_RETURN_TYPE void - -# define _NAN_PROPERTY_DELETER_ARGS_TYPE \ - const v8::PropertyCallbackInfo& -# define _NAN_PROPERTY_DELETER_ARGS \ - _NAN_PROPERTY_DELETER_ARGS_TYPE args -# define _NAN_PROPERTY_DELETER_RETURN_TYPE void - -# define _NAN_PROPERTY_QUERY_ARGS_TYPE \ - const v8::PropertyCallbackInfo& -# define _NAN_PROPERTY_QUERY_ARGS _NAN_PROPERTY_QUERY_ARGS_TYPE args -# define _NAN_PROPERTY_QUERY_RETURN_TYPE void - -# define _NAN_INDEX_GETTER_ARGS_TYPE \ - const v8::PropertyCallbackInfo& -# define _NAN_INDEX_GETTER_ARGS _NAN_INDEX_GETTER_ARGS_TYPE args -# define _NAN_INDEX_GETTER_RETURN_TYPE void - -# define _NAN_INDEX_SETTER_ARGS_TYPE \ - const v8::PropertyCallbackInfo& -# define _NAN_INDEX_SETTER_ARGS _NAN_INDEX_SETTER_ARGS_TYPE args -# define _NAN_INDEX_SETTER_RETURN_TYPE void - -# define _NAN_INDEX_ENUMERATOR_ARGS_TYPE \ - const v8::PropertyCallbackInfo& -# define _NAN_INDEX_ENUMERATOR_ARGS _NAN_INDEX_ENUMERATOR_ARGS_TYPE args -# define _NAN_INDEX_ENUMERATOR_RETURN_TYPE void - -# define _NAN_INDEX_DELETER_ARGS_TYPE \ - const v8::PropertyCallbackInfo& -# define _NAN_INDEX_DELETER_ARGS _NAN_INDEX_DELETER_ARGS_TYPE args -# define _NAN_INDEX_DELETER_RETURN_TYPE void - -# define _NAN_INDEX_QUERY_ARGS_TYPE \ - const v8::PropertyCallbackInfo& -# define _NAN_INDEX_QUERY_ARGS _NAN_INDEX_QUERY_ARGS_TYPE args -# define _NAN_INDEX_QUERY_RETURN_TYPE void - - typedef v8::FunctionCallback NanFunctionCallback; - - template - NAN_INLINE v8::Local NanNew() { - return T::New(v8::Isolate::GetCurrent()); - } - - template - NAN_INLINE v8::Local NanNew(P arg1) { - return T::New(v8::Isolate::GetCurrent(), arg1); - } - - template - NAN_INLINE v8::Local NanNew( - v8::Handle receiver - , int argc - , v8::Handle argv[] = 0) { - return v8::Signature::New(v8::Isolate::GetCurrent(), receiver, argc, argv); - } - - template - NAN_INLINE v8::Local NanNew( - NanFunctionCallback callback - , v8::Handle data = v8::Handle() - , v8::Handle signature = v8::Handle()) { - return T::New(v8::Isolate::GetCurrent(), callback, data, signature); - } - - template - NAN_INLINE v8::Local NanNew(v8::Handle arg1) { - return v8::Local::New(v8::Isolate::GetCurrent(), arg1); - } - - template - NAN_INLINE v8::Local NanNew(const v8::Persistent &arg1) { - return v8::Local::New(v8::Isolate::GetCurrent(), arg1); - } - - template - NAN_INLINE v8::Local NanNew(P arg1, int arg2) { - return T::New(v8::Isolate::GetCurrent(), arg1, arg2); - } - - template<> - NAN_INLINE v8::Local NanNew() { - return v8::Array::New(v8::Isolate::GetCurrent()); - } - - template<> - NAN_INLINE v8::Local NanNew(int length) { - return v8::Array::New(v8::Isolate::GetCurrent(), length); - } - - template<> - NAN_INLINE v8::Local NanNew(double time) { - return v8::Date::New(v8::Isolate::GetCurrent(), time).As(); - } - - template<> - NAN_INLINE v8::Local NanNew(int time) { - return v8::Date::New(v8::Isolate::GetCurrent(), time).As(); - } - - typedef v8::UnboundScript NanUnboundScript; - typedef v8::Script NanBoundScript; - - template - NAN_INLINE v8::Local NanNew( - P s - , const v8::ScriptOrigin& origin - ) { - v8::ScriptCompiler::Source source(s, origin); - return v8::ScriptCompiler::CompileUnbound( - v8::Isolate::GetCurrent(), &source); - } - - template<> - NAN_INLINE v8::Local NanNew( - v8::Local s - ) { - v8::ScriptCompiler::Source source(s); - return v8::ScriptCompiler::CompileUnbound( - v8::Isolate::GetCurrent(), &source); - } - - template<> - NAN_INLINE v8::Local NanNew(bool value) { - return v8::BooleanObject::New(value).As(); - } - - template<> - NAN_INLINE v8::Local - NanNew >( - v8::Local value) { - return v8::StringObject::New(value).As(); - } - - template<> - NAN_INLINE v8::Local - NanNew >( - v8::Handle value) { - return v8::StringObject::New(value).As(); - } - - template<> - NAN_INLINE v8::Local NanNew(double val) { - return v8::NumberObject::New( - v8::Isolate::GetCurrent(), val).As(); - } - - template - NAN_INLINE v8::Local NanNew( - v8::Handle pattern, v8::RegExp::Flags flags) { - return v8::RegExp::New(pattern, flags); - } - - template - NAN_INLINE v8::Local NanNew( - v8::Local pattern, v8::RegExp::Flags flags) { - return v8::RegExp::New(pattern, flags); - } - - template - NAN_INLINE v8::Local NanNew( - v8::Handle pattern, v8::RegExp::Flags flags) { - return v8::RegExp::New(pattern, flags); - } - - template - NAN_INLINE v8::Local NanNew( - v8::Local pattern, v8::RegExp::Flags flags) { - return v8::RegExp::New(pattern, flags); - } - - template<> - NAN_INLINE v8::Local NanNew(int32_t val) { - return v8::Uint32::NewFromUnsigned( - v8::Isolate::GetCurrent(), val)->ToUint32(); - } - - template<> - NAN_INLINE v8::Local NanNew(uint32_t val) { - return v8::Uint32::NewFromUnsigned( - v8::Isolate::GetCurrent(), val)->ToUint32(); - } - - template<> - NAN_INLINE v8::Local NanNew(int32_t val) { - return v8::Int32::New(v8::Isolate::GetCurrent(), val)->ToInt32(); - } - - template<> - NAN_INLINE v8::Local NanNew(uint32_t val) { - return v8::Int32::New(v8::Isolate::GetCurrent(), val)->ToInt32(); - } - - template<> - NAN_INLINE v8::Local NanNew( - char *arg - , int length) { - return v8::String::NewFromUtf8( - v8::Isolate::GetCurrent() - , arg - , v8::String::kNormalString - , length); - } - - template<> - NAN_INLINE v8::Local NanNew( - const char *arg - , int length) { - return v8::String::NewFromUtf8( - v8::Isolate::GetCurrent() - , arg - , v8::String::kNormalString - , length); - } - - template<> - NAN_INLINE v8::Local NanNew(char *arg) { - return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), arg); - } - - template<> - NAN_INLINE v8::Local NanNew( - const char *arg) { - return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), arg); - } - - template<> - NAN_INLINE v8::Local NanNew( - uint8_t *arg - , int length) { - return v8::String::NewFromOneByte( - v8::Isolate::GetCurrent() - , arg - , v8::String::kNormalString - , length); - } - - template<> - NAN_INLINE v8::Local NanNew( - const uint8_t *arg - , int length) { - return v8::String::NewFromOneByte( - v8::Isolate::GetCurrent() - , arg - , v8::String::kNormalString - , length); - } - - template<> - NAN_INLINE v8::Local NanNew(uint8_t *arg) { - return v8::String::NewFromOneByte(v8::Isolate::GetCurrent(), arg); - } - - template<> - NAN_INLINE v8::Local NanNew( - const uint8_t *arg) { - return v8::String::NewFromOneByte(v8::Isolate::GetCurrent(), arg); - } - - template<> - NAN_INLINE v8::Local NanNew( - uint16_t *arg - , int length) { - return v8::String::NewFromTwoByte( - v8::Isolate::GetCurrent() - , arg - , v8::String::kNormalString - , length); - } - - template<> - NAN_INLINE v8::Local NanNew( - const uint16_t *arg - , int length) { - return v8::String::NewFromTwoByte( - v8::Isolate::GetCurrent() - , arg - , v8::String::kNormalString - , length); - } - template<> - NAN_INLINE v8::Local NanNew( - uint16_t *arg) { - return v8::String::NewFromTwoByte(v8::Isolate::GetCurrent(), arg); - } - - template<> - NAN_INLINE v8::Local NanNew( - const uint16_t *arg) { - return v8::String::NewFromTwoByte(v8::Isolate::GetCurrent(), arg); - } - - template<> - NAN_INLINE v8::Local NanNew( - std::string arg) { - return NanNew(arg.c_str(), arg.size()); - } - - template<> - NAN_INLINE v8::Local NanNew() { - return v8::String::Empty(v8::Isolate::GetCurrent()); - } - - NAN_INLINE v8::Local NanNew(const char* arg, int length = -1) { - return NanNew(arg, length); - } - - NAN_INLINE v8::Local NanNew( - const uint8_t* arg - , int length = -1) { - return NanNew(arg, length); - } - - NAN_INLINE v8::Local NanNew( - const uint16_t* arg - , int length = -1) { - return NanNew(arg, length); - } - - NAN_INLINE v8::Local NanNew( - const std::string& arg) { - return NanNew(arg.c_str(), arg.size()); - } - - NAN_INLINE v8::Local NanNew(double val) { - return NanNew(val); - } - - NAN_INLINE v8::Local NanNew(int val) { - return NanNew(val); - } - - NAN_INLINE v8::Local NanNew(unsigned int val) { - return NanNew(val); - } - - NAN_INLINE v8::Local NanNew(bool val) { - return NanNew(val); - } - - NAN_INLINE v8::Local NanNew( - v8::String::ExternalStringResource *resource) { - return v8::String::NewExternal(v8::Isolate::GetCurrent(), resource); - } - - NAN_INLINE v8::Local NanNew( - v8::String::ExternalAsciiStringResource *resource) { - return v8::String::NewExternal(v8::Isolate::GetCurrent(), resource); - } - -# define NanScope() v8::HandleScope scope(v8::Isolate::GetCurrent()) -# define NanEscapableScope() \ - v8::EscapableHandleScope scope(v8::Isolate::GetCurrent()) - - template - NAN_INLINE v8::Local _NanEscapeScopeHelper(v8::Handle val) { - return NanNew(val); - } - - template - NAN_INLINE v8::Local _NanEscapeScopeHelper(v8::Local val) { - return val; - } - -# define NanEscapeScope(val) scope.Escape(_NanEscapeScopeHelper(val)) -# define NanLocker() v8::Locker locker(v8::Isolate::GetCurrent()) -# define NanUnlocker() v8::Unlocker unlocker(v8::Isolate::GetCurrent()) -# define NanReturnValue(value) return args.GetReturnValue().Set(value) -# define NanReturnUndefined() return -# define NanReturnNull() return args.GetReturnValue().SetNull() -# define NanReturnEmptyString() return args.GetReturnValue().SetEmptyString() - -# define NanObjectWrapHandle(obj) obj->handle() - - NAN_INLINE v8::Local NanUndefined() { - NanEscapableScope(); - return NanEscapeScope(NanNew(v8::Undefined(v8::Isolate::GetCurrent()))); - } - - NAN_INLINE v8::Local NanNull() { - NanEscapableScope(); - return NanEscapeScope(NanNew(v8::Null(v8::Isolate::GetCurrent()))); - } - - NAN_INLINE v8::Local NanTrue() { - NanEscapableScope(); - return NanEscapeScope(NanNew(v8::True(v8::Isolate::GetCurrent()))); - } - - NAN_INLINE v8::Local NanFalse() { - NanEscapableScope(); - return NanEscapeScope(NanNew(v8::False(v8::Isolate::GetCurrent()))); - } - - NAN_INLINE int NanAdjustExternalMemory(int bc) { - return static_cast( - v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(bc)); - } - - NAN_INLINE void NanSetTemplate( - v8::Handle templ - , const char *name - , v8::Handle value) { - templ->Set(v8::Isolate::GetCurrent(), name, value); - } - - NAN_INLINE void NanSetTemplate( - v8::Handle templ - , v8::Handle name - , v8::Handle value - , v8::PropertyAttribute attributes) { - templ->Set(name, value, attributes); - } - - NAN_INLINE v8::Local NanGetCurrentContext() { - return v8::Isolate::GetCurrent()->GetCurrentContext(); - } - - NAN_INLINE void* NanGetInternalFieldPointer( - v8::Handle object - , int index) { - return object->GetAlignedPointerFromInternalField(index); - } - - NAN_INLINE void NanSetInternalFieldPointer( - v8::Handle object - , int index - , void* value) { - object->SetAlignedPointerInInternalField(index, value); - } - - NAN_INLINE void NanAddGCEpilogueCallback( - v8::Isolate::GCEpilogueCallback callback - , v8::GCType gc_type_filter = v8::kGCTypeAll) { - v8::Isolate::GetCurrent()->AddGCEpilogueCallback(callback, gc_type_filter); - } - - NAN_INLINE void NanRemoveGCEpilogueCallback( - v8::Isolate::GCEpilogueCallback callback) { - v8::Isolate::GetCurrent()->RemoveGCEpilogueCallback(callback); - } - - NAN_INLINE void NanAddGCPrologueCallback( - v8::Isolate::GCPrologueCallback callback - , v8::GCType gc_type_filter = v8::kGCTypeAll) { - v8::Isolate::GetCurrent()->AddGCPrologueCallback(callback, gc_type_filter); - } - - NAN_INLINE void NanRemoveGCPrologueCallback( - v8::Isolate::GCPrologueCallback callback) { - v8::Isolate::GetCurrent()->RemoveGCPrologueCallback(callback); - } - - NAN_INLINE void NanGetHeapStatistics( - v8::HeapStatistics *heap_statistics) { - v8::Isolate::GetCurrent()->GetHeapStatistics(heap_statistics); - } - - NAN_DEPRECATED NAN_INLINE v8::Local NanSymbol( - const char* data, int length = -1) { - return NanNew(data, length); - } - - template - NAN_INLINE void NanAssignPersistent( - v8::Persistent& handle - , v8::Handle obj) { - handle.Reset(v8::Isolate::GetCurrent(), obj); - } - - template - NAN_INLINE void NanAssignPersistent( - v8::Persistent& handle - , const v8::Persistent& obj) { - handle.Reset(v8::Isolate::GetCurrent(), obj); - } - - template - class _NanWeakCallbackData; - - template - struct _NanWeakCallbackInfo { - typedef void (*Callback)(const _NanWeakCallbackData& data); - NAN_INLINE _NanWeakCallbackInfo(v8::Handle handle, P* param, Callback cb) - : parameter(param), callback(cb) { - NanAssignPersistent(persistent, handle); - } - - NAN_INLINE ~_NanWeakCallbackInfo() { - persistent.Reset(); - } - - P* const parameter; - Callback const callback; - v8::Persistent persistent; - }; - - template - class _NanWeakCallbackData { - public: - NAN_INLINE _NanWeakCallbackData(_NanWeakCallbackInfo *info) - : info_(info) { } - - NAN_INLINE v8::Local GetValue() const { - return NanNew(info_->persistent); - } - - NAN_INLINE P* GetParameter() const { return info_->parameter; } - - NAN_INLINE bool IsNearDeath() const { - return info_->persistent.IsNearDeath(); - } - - NAN_INLINE void Revive() const; - - NAN_INLINE _NanWeakCallbackInfo* GetCallbackInfo() const { - return info_; - } - - NAN_DEPRECATED NAN_INLINE void Dispose() const { - } - - private: - _NanWeakCallbackInfo* info_; - }; - - template - static void _NanWeakCallbackDispatcher( - const v8::WeakCallbackData > &data) { - _NanWeakCallbackInfo *info = data.GetParameter(); - _NanWeakCallbackData wcbd(info); - info->callback(wcbd); - if (wcbd.IsNearDeath()) { - delete wcbd.GetCallbackInfo(); - } - } - - template - NAN_INLINE void _NanWeakCallbackData::Revive() const { - info_->persistent.SetWeak(info_, &_NanWeakCallbackDispatcher); - } - -template -NAN_INLINE _NanWeakCallbackInfo* NanMakeWeakPersistent( - v8::Handle handle - , P* parameter - , typename _NanWeakCallbackInfo::Callback callback) { - _NanWeakCallbackInfo *cbinfo = - new _NanWeakCallbackInfo(handle, parameter, callback); - cbinfo->persistent.SetWeak(cbinfo, &_NanWeakCallbackDispatcher); - return cbinfo; -} - -# define NAN_WEAK_CALLBACK(name) \ - template \ - static void name(const _NanWeakCallbackData &data) - -# define _NAN_ERROR(fun, errmsg) fun(NanNew(errmsg)) - -# define _NAN_THROW_ERROR(fun, errmsg) \ - do { \ - NanScope(); \ - v8::Isolate::GetCurrent()->ThrowException(_NAN_ERROR(fun, errmsg)); \ - } while (0); - - NAN_INLINE v8::Local NanError(const char* errmsg) { - return _NAN_ERROR(v8::Exception::Error, errmsg); - } - - NAN_INLINE void NanThrowError(const char* errmsg) { - _NAN_THROW_ERROR(v8::Exception::Error, errmsg); - } - - NAN_INLINE void NanThrowError(v8::Handle error) { - NanScope(); - v8::Isolate::GetCurrent()->ThrowException(error); - } - - NAN_INLINE v8::Local NanError( - const char *msg - , const int errorNumber - ) { - v8::Local err = v8::Exception::Error(NanNew(msg)); - v8::Local obj = err.As(); - obj->Set(NanNew("code"), NanNew(errorNumber)); - return err; - } - - NAN_INLINE void NanThrowError( - const char *msg - , const int errorNumber - ) { - NanThrowError(NanError(msg, errorNumber)); - } - - NAN_INLINE v8::Local NanTypeError(const char* errmsg) { - return _NAN_ERROR(v8::Exception::TypeError, errmsg); - } - - NAN_INLINE void NanThrowTypeError(const char* errmsg) { - _NAN_THROW_ERROR(v8::Exception::TypeError, errmsg); - } - - NAN_INLINE v8::Local NanRangeError(const char* errmsg) { - return _NAN_ERROR(v8::Exception::RangeError, errmsg); - } - - NAN_INLINE void NanThrowRangeError(const char* errmsg) { - _NAN_THROW_ERROR(v8::Exception::RangeError, errmsg); - } - - template NAN_INLINE void NanDisposePersistent( - v8::Persistent &handle - ) { - handle.Reset(); - } - - NAN_INLINE v8::Local NanNewBufferHandle ( - char *data - , size_t length - , node::smalloc::FreeCallback callback - , void *hint - ) { - return node::Buffer::New( - v8::Isolate::GetCurrent(), data, length, callback, hint); - } - - NAN_INLINE v8::Local NanNewBufferHandle ( - const char *data - , uint32_t size - ) { - return node::Buffer::New(v8::Isolate::GetCurrent(), data, size); - } - - NAN_INLINE v8::Local NanNewBufferHandle (uint32_t size) { - return node::Buffer::New(v8::Isolate::GetCurrent(), size); - } - - NAN_INLINE v8::Local NanBufferUse( - char* data - , uint32_t size - ) { - return node::Buffer::Use(v8::Isolate::GetCurrent(), data, size); - } - - NAN_INLINE bool NanHasInstance( - v8::Persistent& function_template - , v8::Handle value - ) { - return NanNew(function_template)->HasInstance(value); - } - - NAN_INLINE v8::Local NanNewContextHandle( - v8::ExtensionConfiguration* extensions = NULL - , v8::Handle tmpl = v8::Handle() - , v8::Handle obj = v8::Handle() - ) { - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - return v8::Local::New( - isolate - , v8::Context::New(isolate, extensions, tmpl, obj) - ); - } - - NAN_INLINE v8::Local NanCompileScript( - v8::Local s - , const v8::ScriptOrigin& origin - ) { - v8::ScriptCompiler::Source source(s, origin); - return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &source); - } - - NAN_INLINE v8::Local NanCompileScript( - v8::Local s - ) { - v8::ScriptCompiler::Source source(s); - return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &source); - } - - NAN_INLINE v8::Local NanRunScript( - v8::Handle script - ) { - return script->BindToCurrentContext()->Run(); - } - - NAN_INLINE v8::Local NanRunScript( - v8::Handle script - ) { - return script->Run(); - } - - NAN_INLINE v8::Local NanMakeCallback( - v8::Handle target - , v8::Handle func - , int argc - , v8::Handle* argv) { - return NanNew(node::MakeCallback( - v8::Isolate::GetCurrent(), target, func, argc, argv)); - } - - NAN_INLINE v8::Local NanMakeCallback( - v8::Handle target - , v8::Handle symbol - , int argc - , v8::Handle* argv) { - return NanNew(node::MakeCallback( - v8::Isolate::GetCurrent(), target, symbol, argc, argv)); - } - - NAN_INLINE v8::Local NanMakeCallback( - v8::Handle target - , const char* method - , int argc - , v8::Handle* argv) { - return NanNew(node::MakeCallback( - v8::Isolate::GetCurrent(), target, method, argc, argv)); - } - - template - NAN_INLINE void NanSetIsolateData( - v8::Isolate *isolate - , T *data - ) { - isolate->SetData(0, data); - } - - template - NAN_INLINE T *NanGetIsolateData( - v8::Isolate *isolate - ) { - return static_cast(isolate->GetData(0)); - } - - class NanAsciiString { - public: - NAN_INLINE explicit NanAsciiString(v8::Handle from) { - v8::Local toStr = from->ToString(); - int buf_size = toStr->Length() + 1; - buf = new char[buf_size]; - size = toStr->WriteOneByte( - reinterpret_cast(buf), 0, buf_size); - } - - NAN_INLINE int Size() const { - return size; - } - - NAN_INLINE char* operator*() { return buf; } - - NAN_INLINE ~NanAsciiString() { - delete[] buf; - } - - private: - char *buf; - int size; - }; - - class NanUtf8String { - public: - NAN_INLINE explicit NanUtf8String(v8::Handle from) { - v8::Local toStr = from->ToString(); - int buf_size = toStr->Utf8Length() + 1; - buf = new char[buf_size]; - size = toStr->WriteUtf8(buf, buf_size); - } - - NAN_INLINE int Size() const { - return size; - } - - NAN_INLINE char* operator*() { return buf; } - - NAN_INLINE ~NanUtf8String() { - delete[] buf; - } - - private: - char *buf; - int size; - }; - - class NanUcs2String { - public: - NAN_INLINE explicit NanUcs2String(v8::Handle from) { - v8::Local toStr = from->ToString(); - int buf_size = toStr->Length() + 1; - buf = new uint16_t[buf_size]; - size = toStr->Write(buf, 0, buf_size); - } - - NAN_INLINE int Size() const { - return size; - } - - NAN_INLINE uint16_t* operator*() { return buf; } - - NAN_INLINE ~NanUcs2String() { - delete[] buf; - } - - private: - uint16_t *buf; - int size; - }; - -#else -// Node 0.8 and 0.10 - -# define _NAN_METHOD_ARGS_TYPE const v8::Arguments& -# define _NAN_METHOD_ARGS _NAN_METHOD_ARGS_TYPE args -# define _NAN_METHOD_RETURN_TYPE v8::Handle - -# define _NAN_GETTER_ARGS_TYPE const v8::AccessorInfo & -# define _NAN_GETTER_ARGS _NAN_GETTER_ARGS_TYPE args -# define _NAN_GETTER_RETURN_TYPE v8::Handle - -# define _NAN_SETTER_ARGS_TYPE const v8::AccessorInfo & -# define _NAN_SETTER_ARGS _NAN_SETTER_ARGS_TYPE args -# define _NAN_SETTER_RETURN_TYPE void - -# define _NAN_PROPERTY_GETTER_ARGS_TYPE const v8::AccessorInfo& -# define _NAN_PROPERTY_GETTER_ARGS _NAN_PROPERTY_GETTER_ARGS_TYPE args -# define _NAN_PROPERTY_GETTER_RETURN_TYPE v8::Handle - -# define _NAN_PROPERTY_SETTER_ARGS_TYPE const v8::AccessorInfo& -# define _NAN_PROPERTY_SETTER_ARGS _NAN_PROPERTY_SETTER_ARGS_TYPE args -# define _NAN_PROPERTY_SETTER_RETURN_TYPE v8::Handle - -# define _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE const v8::AccessorInfo& -# define _NAN_PROPERTY_ENUMERATOR_ARGS _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE args -# define _NAN_PROPERTY_ENUMERATOR_RETURN_TYPE v8::Handle - -# define _NAN_PROPERTY_DELETER_ARGS_TYPE const v8::AccessorInfo& -# define _NAN_PROPERTY_DELETER_ARGS _NAN_PROPERTY_DELETER_ARGS_TYPE args -# define _NAN_PROPERTY_DELETER_RETURN_TYPE v8::Handle - -# define _NAN_PROPERTY_QUERY_ARGS_TYPE const v8::AccessorInfo& -# define _NAN_PROPERTY_QUERY_ARGS _NAN_PROPERTY_QUERY_ARGS_TYPE args -# define _NAN_PROPERTY_QUERY_RETURN_TYPE v8::Handle - -# define _NAN_INDEX_GETTER_ARGS_TYPE const v8::AccessorInfo& -# define _NAN_INDEX_GETTER_ARGS _NAN_INDEX_GETTER_ARGS_TYPE args -# define _NAN_INDEX_GETTER_RETURN_TYPE v8::Handle - -# define _NAN_INDEX_SETTER_ARGS_TYPE const v8::AccessorInfo& -# define _NAN_INDEX_SETTER_ARGS _NAN_INDEX_SETTER_ARGS_TYPE args -# define _NAN_INDEX_SETTER_RETURN_TYPE v8::Handle - -# define _NAN_INDEX_ENUMERATOR_ARGS_TYPE const v8::AccessorInfo& -# define _NAN_INDEX_ENUMERATOR_ARGS _NAN_INDEX_ENUMERATOR_ARGS_TYPE args -# define _NAN_INDEX_ENUMERATOR_RETURN_TYPE v8::Handle - -# define _NAN_INDEX_DELETER_ARGS_TYPE const v8::AccessorInfo& -# define _NAN_INDEX_DELETER_ARGS _NAN_INDEX_DELETER_ARGS_TYPE args -# define _NAN_INDEX_DELETER_RETURN_TYPE v8::Handle - -# define _NAN_INDEX_QUERY_ARGS_TYPE const v8::AccessorInfo& -# define _NAN_INDEX_QUERY_ARGS _NAN_INDEX_QUERY_ARGS_TYPE args -# define _NAN_INDEX_QUERY_RETURN_TYPE v8::Handle - - typedef v8::InvocationCallback NanFunctionCallback; - - NAN_DEPRECATED NAN_INLINE v8::Local NanSymbol( - const char* data, int length = -1) { - return v8::String::NewSymbol(data, length); - } - - template - NAN_INLINE v8::Local NanNew() { - return v8::Local::New(T::New()); - } - - template - NAN_INLINE v8::Local NanNew(v8::Handle arg) { - return v8::Local::New(arg); - } - - template - NAN_INLINE v8::Local NanNew( - v8::Handle receiver - , int argc - , v8::Handle argv[] = 0) { - return v8::Signature::New(receiver, argc, argv); - } - - template - NAN_INLINE v8::Local NanNew( - NanFunctionCallback callback - , v8::Handle data = v8::Handle() - , v8::Handle signature = v8::Handle()) { - return T::New(callback, data, signature); - } - - template - NAN_INLINE v8::Local NanNew(const v8::Persistent &arg) { - return v8::Local::New(arg); - } - - template - NAN_INLINE v8::Local NanNew(P arg) { - return v8::Local::New(T::New(arg)); - } - - template - NAN_INLINE v8::Local NanNew(P arg, int length) { - return v8::Local::New(T::New(arg, length)); - } - - template - NAN_INLINE v8::Local NanNew( - v8::Handle pattern, v8::RegExp::Flags flags) { - return v8::RegExp::New(pattern, flags); - } - - template - NAN_INLINE v8::Local NanNew( - v8::Local pattern, v8::RegExp::Flags flags) { - return v8::RegExp::New(pattern, flags); - } - - template - NAN_INLINE v8::Local NanNew( - v8::Handle pattern, v8::RegExp::Flags flags) { - return v8::RegExp::New(pattern, flags); - } - - template - NAN_INLINE v8::Local NanNew( - v8::Local pattern, v8::RegExp::Flags flags) { - return v8::RegExp::New(pattern, flags); - } - - template<> - NAN_INLINE v8::Local NanNew() { - return v8::Array::New(); - } - - template<> - NAN_INLINE v8::Local NanNew(int length) { - return v8::Array::New(length); - } - - template<> - NAN_INLINE v8::Local NanNew(double time) { - return v8::Date::New(time).As(); - } - - template<> - NAN_INLINE v8::Local NanNew(int time) { - return v8::Date::New(time).As(); - } - - typedef v8::Script NanUnboundScript; - typedef v8::Script NanBoundScript; - - template - NAN_INLINE v8::Local NanNew( - P s - , const v8::ScriptOrigin& origin - ) { - return v8::Script::New(s, const_cast(&origin)); - } - - template<> - NAN_INLINE v8::Local NanNew( - v8::Local s - ) { - return v8::Script::New(s); - } - - template<> - NAN_INLINE v8::Local NanNew(bool value) { - return v8::BooleanObject::New(value).As(); - } - - template<> - NAN_INLINE v8::Local - NanNew >( - v8::Local value) { - return v8::StringObject::New(value).As(); - } - - template<> - NAN_INLINE v8::Local - NanNew >( - v8::Handle value) { - return v8::StringObject::New(value).As(); - } - - template<> - NAN_INLINE v8::Local NanNew(double val) { - return v8::NumberObject::New(val).As(); - } - - template<> - NAN_INLINE v8::Local NanNew(int32_t val) { - return v8::Uint32::NewFromUnsigned(val)->ToUint32(); - } - - template<> - NAN_INLINE v8::Local NanNew(uint32_t val) { - return v8::Uint32::NewFromUnsigned(val)->ToUint32(); - } - - template<> - NAN_INLINE v8::Local NanNew(int32_t val) { - return v8::Int32::New(val)->ToInt32(); - } - - template<> - NAN_INLINE v8::Local NanNew(uint32_t val) { - return v8::Int32::New(val)->ToInt32(); - } - - template<> - NAN_INLINE v8::Local NanNew( - uint8_t *arg - , int length) { - int len = length; - if (len < 0) { - size_t temp = strlen(reinterpret_cast(arg)); - assert(temp <= INT_MAX && "too long string"); - len = static_cast(temp); - } - uint16_t *warg = new uint16_t[len]; - for (int i = 0; i < len; i++) { - warg[i] = arg[i]; - } - v8::Local retval = v8::String::New(warg, len); - delete[] warg; - return retval; - } - - template<> - NAN_INLINE v8::Local NanNew( - const uint8_t *arg - , int length) { - int len = length; - if (len < 0) { - size_t temp = strlen(reinterpret_cast(arg)); - assert(temp <= INT_MAX && "too long string"); - len = static_cast(temp); - } - uint16_t *warg = new uint16_t[len]; - for (int i = 0; i < len; i++) { - warg[i] = arg[i]; - } - v8::Local retval = v8::String::New(warg, len); - delete[] warg; - return retval; - } - - template<> - NAN_INLINE v8::Local NanNew(uint8_t *arg) { - size_t temp = strlen(reinterpret_cast(arg)); - assert(temp <= INT_MAX && "too long string"); - int length = static_cast(temp); - uint16_t *warg = new uint16_t[length]; - for (int i = 0; i < length; i++) { - warg[i] = arg[i]; - } - - v8::Local retval = v8::String::New(warg, length); - delete[] warg; - return retval; - } - - template<> - NAN_INLINE v8::Local NanNew( - const uint8_t *arg) { - size_t temp = strlen(reinterpret_cast(arg)); - assert(temp <= INT_MAX && "too long string"); - int length = static_cast(temp); - uint16_t *warg = new uint16_t[length]; - for (int i = 0; i < length; i++) { - warg[i] = arg[i]; - } - v8::Local retval = v8::String::New(warg, length); - delete[] warg; - return retval; - } - - template<> - NAN_INLINE v8::Local NanNew( - std::string arg) { - return NanNew(arg.c_str(), arg.size()); - } - - template<> - NAN_INLINE v8::Local NanNew() { - return v8::String::Empty(); - } - - NAN_INLINE v8::Local NanNew(const char* arg, int length = -1) { - return NanNew(arg, length); - } - - NAN_INLINE v8::Local NanNew( - const uint8_t* arg - , int length = -1) { - return NanNew(arg, length); - } - - NAN_INLINE v8::Local NanNew( - const uint16_t* arg - , int length = -1) { - return NanNew(arg, length); - } - - NAN_INLINE v8::Local NanNew( - std::string& arg) { - return NanNew(arg.c_str(), arg.size()); - } - - NAN_INLINE v8::Local NanNew(double val) { - return NanNew(val); - } - - NAN_INLINE v8::Local NanNew(int val) { - return NanNew(val); - } - - NAN_INLINE v8::Local NanNew(unsigned int val) { - return NanNew(val); - } - - NAN_INLINE v8::Local NanNew(bool val) { - return NanNew(val); - } - - NAN_INLINE v8::Local NanNew( - v8::String::ExternalStringResource *resource) { - return v8::String::NewExternal(resource); - } - - NAN_INLINE v8::Local NanNew( - v8::String::ExternalAsciiStringResource *resource) { - return v8::String::NewExternal(resource); - } - -# define NanScope() v8::HandleScope scope -# define NanEscapableScope() v8::HandleScope scope -# define NanEscapeScope(val) scope.Close(val) -# define NanLocker() v8::Locker locker -# define NanUnlocker() v8::Unlocker unlocker -# define NanReturnValue(value) return scope.Close(value) -# define NanReturnUndefined() return v8::Undefined() -# define NanReturnNull() return v8::Null() -# define NanReturnEmptyString() return v8::String::Empty() -# define NanObjectWrapHandle(obj) v8::Local::New(obj->handle_) - - NAN_INLINE v8::Local NanUndefined() { - NanEscapableScope(); - return NanEscapeScope(NanNew(v8::Undefined())); - } - - NAN_INLINE v8::Local NanNull() { - NanEscapableScope(); - return NanEscapeScope(NanNew(v8::Null())); - } - - NAN_INLINE v8::Local NanTrue() { - NanEscapableScope(); - return NanEscapeScope(NanNew(v8::True())); - } - - NAN_INLINE v8::Local NanFalse() { - NanEscapableScope(); - return NanEscapeScope(NanNew(v8::False())); - } - - NAN_INLINE int NanAdjustExternalMemory(int bc) { - return static_cast(v8::V8::AdjustAmountOfExternalAllocatedMemory(bc)); - } - - NAN_INLINE void NanSetTemplate( - v8::Handle templ - , const char *name - , v8::Handle value) { - templ->Set(name, value); - } - - NAN_INLINE void NanSetTemplate( - v8::Handle templ - , v8::Handle name - , v8::Handle value - , v8::PropertyAttribute attributes) { - templ->Set(name, value, attributes); - } - - NAN_INLINE v8::Local NanGetCurrentContext() { - return v8::Context::GetCurrent(); - } - - NAN_INLINE void* NanGetInternalFieldPointer( - v8::Handle object - , int index) { - return object->GetPointerFromInternalField(index); - } - - NAN_INLINE void NanSetInternalFieldPointer( - v8::Handle object - , int index - , void* value) { - object->SetPointerInInternalField(index, value); - } - - NAN_INLINE void NanAddGCEpilogueCallback( - v8::GCEpilogueCallback callback - , v8::GCType gc_type_filter = v8::kGCTypeAll) { - v8::V8::AddGCEpilogueCallback(callback, gc_type_filter); - } - NAN_INLINE void NanRemoveGCEpilogueCallback( - v8::GCEpilogueCallback callback) { - v8::V8::RemoveGCEpilogueCallback(callback); - } - NAN_INLINE void NanAddGCPrologueCallback( - v8::GCPrologueCallback callback - , v8::GCType gc_type_filter = v8::kGCTypeAll) { - v8::V8::AddGCPrologueCallback(callback, gc_type_filter); - } - NAN_INLINE void NanRemoveGCPrologueCallback( - v8::GCPrologueCallback callback) { - v8::V8::RemoveGCPrologueCallback(callback); - } - NAN_INLINE void NanGetHeapStatistics( - v8::HeapStatistics *heap_statistics) { - v8::V8::GetHeapStatistics(heap_statistics); - } - - template - NAN_INLINE void NanAssignPersistent( - v8::Persistent& handle - , v8::Handle obj) { - handle.Dispose(); - handle = v8::Persistent::New(obj); - } - - template - class _NanWeakCallbackData; - - template - struct _NanWeakCallbackInfo { - typedef void (*Callback)(const _NanWeakCallbackData &data); - NAN_INLINE _NanWeakCallbackInfo(v8::Handle handle, P* param, Callback cb) - : parameter(param) - , callback(cb) - , persistent(v8::Persistent::New(handle)) { } - - NAN_INLINE ~_NanWeakCallbackInfo() { - persistent.Dispose(); - persistent.Clear(); - } - - P* const parameter; - Callback const callback; - v8::Persistent persistent; - }; - - template - class _NanWeakCallbackData { - public: - NAN_INLINE _NanWeakCallbackData(_NanWeakCallbackInfo *info) - : info_(info) { } - - NAN_INLINE v8::Local GetValue() const { - return NanNew(info_->persistent); - } - - NAN_INLINE P* GetParameter() const { return info_->parameter; } - - NAN_INLINE bool IsNearDeath() const { - return info_->persistent.IsNearDeath(); - } - - NAN_INLINE void Revive() const; - - NAN_INLINE _NanWeakCallbackInfo* GetCallbackInfo() const { - return info_; - } - - NAN_DEPRECATED NAN_INLINE void Dispose() const { - } - - private: - _NanWeakCallbackInfo* info_; - }; - - template - static void _NanWeakPersistentDispatcher( - v8::Persistent object, void *data) { - _NanWeakCallbackInfo* info = - static_cast<_NanWeakCallbackInfo*>(data); - _NanWeakCallbackData wcbd(info); - info->callback(wcbd); - if (wcbd.IsNearDeath()) { - delete wcbd.GetCallbackInfo(); - } - } - - template - NAN_INLINE void _NanWeakCallbackData::Revive() const { - info_->persistent.MakeWeak( - info_ - , &_NanWeakPersistentDispatcher); - } - - template - NAN_INLINE _NanWeakCallbackInfo* NanMakeWeakPersistent( - v8::Handle handle - , P* parameter - , typename _NanWeakCallbackInfo::Callback callback) { - _NanWeakCallbackInfo *cbinfo = - new _NanWeakCallbackInfo(handle, parameter, callback); - cbinfo->persistent.MakeWeak( - cbinfo - , &_NanWeakPersistentDispatcher); - return cbinfo; - } - -# define NAN_WEAK_CALLBACK(name) \ - template \ - static void name(const _NanWeakCallbackData &data) - -# define _NAN_ERROR(fun, errmsg) \ - fun(v8::String::New(errmsg)) - -# define _NAN_THROW_ERROR(fun, errmsg) \ - do { \ - NanScope(); \ - return v8::Local::New( \ - v8::ThrowException(_NAN_ERROR(fun, errmsg))); \ - } while (0); - - NAN_INLINE v8::Local NanError(const char* errmsg) { - return _NAN_ERROR(v8::Exception::Error, errmsg); - } - - NAN_INLINE v8::Local NanThrowError(const char* errmsg) { - _NAN_THROW_ERROR(v8::Exception::Error, errmsg); - } - - NAN_INLINE v8::Local NanThrowError( - v8::Handle error - ) { - NanScope(); - return v8::Local::New(v8::ThrowException(error)); - } - - NAN_INLINE v8::Local NanError( - const char *msg - , const int errorNumber - ) { - v8::Local err = v8::Exception::Error(v8::String::New(msg)); - v8::Local obj = err.As(); - obj->Set(v8::String::New("code"), v8::Int32::New(errorNumber)); - return err; - } - - NAN_INLINE v8::Local NanThrowError( - const char *msg - , const int errorNumber - ) { - return NanThrowError(NanError(msg, errorNumber)); - } - - NAN_INLINE v8::Local NanTypeError(const char* errmsg) { - return _NAN_ERROR(v8::Exception::TypeError, errmsg); - } - - NAN_INLINE v8::Local NanThrowTypeError( - const char* errmsg - ) { - _NAN_THROW_ERROR(v8::Exception::TypeError, errmsg); - } - - NAN_INLINE v8::Local NanRangeError( - const char* errmsg - ) { - return _NAN_ERROR(v8::Exception::RangeError, errmsg); - } - - NAN_INLINE v8::Local NanThrowRangeError( - const char* errmsg - ) { - _NAN_THROW_ERROR(v8::Exception::RangeError, errmsg); - } - - template - NAN_INLINE void NanDisposePersistent( - v8::Persistent &handle) { // NOLINT(runtime/references) - handle.Dispose(); - handle.Clear(); - } - - NAN_INLINE v8::Local NanNewBufferHandle ( - char *data - , size_t length - , node::Buffer::free_callback callback - , void *hint - ) { - return NanNew( - node::Buffer::New(data, length, callback, hint)->handle_); - } - - NAN_INLINE v8::Local NanNewBufferHandle ( - const char *data - , uint32_t size - ) { -#if NODE_MODULE_VERSION >= 0x000B - return NanNew(node::Buffer::New(data, size)->handle_); -#else - return NanNew( - node::Buffer::New(const_cast(data), size)->handle_); -#endif - } - - NAN_INLINE v8::Local NanNewBufferHandle (uint32_t size) { - return NanNew(node::Buffer::New(size)->handle_); - } - - NAN_INLINE void FreeData(char *data, void *hint) { - delete[] data; - } - - NAN_INLINE v8::Local NanBufferUse( - char* data - , uint32_t size - ) { - return NanNew( - node::Buffer::New(data, size, FreeData, NULL)->handle_); - } - - NAN_INLINE bool NanHasInstance( - v8::Persistent& function_template - , v8::Handle value - ) { - return function_template->HasInstance(value); - } - - NAN_INLINE v8::Local NanNewContextHandle( - v8::ExtensionConfiguration* extensions = NULL - , v8::Handle tmpl = v8::Handle() - , v8::Handle obj = v8::Handle() - ) { - v8::Persistent ctx = v8::Context::New(extensions, tmpl, obj); - v8::Local lctx = NanNew(ctx); - ctx.Dispose(); - return lctx; - } - - NAN_INLINE v8::Local NanCompileScript( - v8::Local s - , const v8::ScriptOrigin& origin - ) { - return v8::Script::Compile(s, const_cast(&origin)); - } - - NAN_INLINE v8::Local NanCompileScript( - v8::Local s - ) { - return v8::Script::Compile(s); - } - - NAN_INLINE v8::Local NanRunScript(v8::Handle script) { - return script->Run(); - } - - NAN_INLINE v8::Local NanMakeCallback( - v8::Handle target - , v8::Handle func - , int argc - , v8::Handle* argv) { -# if NODE_VERSION_AT_LEAST(0, 8, 0) - return NanNew(node::MakeCallback(target, func, argc, argv)); -# else - v8::TryCatch try_catch; - v8::Local result = NanNew(func->Call(target, argc, argv)); - if (try_catch.HasCaught()) { - node::FatalException(try_catch); - } - return result; -# endif - } - - NAN_INLINE v8::Local NanMakeCallback( - v8::Handle target - , v8::Handle symbol - , int argc - , v8::Handle* argv) { -# if NODE_VERSION_AT_LEAST(0, 8, 0) - return NanNew(node::MakeCallback(target, symbol, argc, argv)); -# else - v8::Local callback = target->Get(symbol).As(); - return NanMakeCallback(target, callback, argc, argv); -# endif - } - - NAN_INLINE v8::Local NanMakeCallback( - v8::Handle target - , const char* method - , int argc - , v8::Handle* argv) { -# if NODE_VERSION_AT_LEAST(0, 8, 0) - return NanNew(node::MakeCallback(target, method, argc, argv)); -# else - return NanMakeCallback(target, NanNew(method), argc, argv); -# endif - } - - template - NAN_INLINE void NanSetIsolateData( - v8::Isolate *isolate - , T *data - ) { - isolate->SetData(data); - } - - template - NAN_INLINE T *NanGetIsolateData( - v8::Isolate *isolate - ) { - return static_cast(isolate->GetData()); - } - - class NanAsciiString { - public: - NAN_INLINE explicit NanAsciiString(v8::Handle from) { - v8::Local toStr = from->ToString(); - int buf_size = toStr->Length() + 1; - buf = new char[buf_size]; - size = toStr->WriteAscii(buf, 0, buf_size); - } - - NAN_INLINE int Size() const { - return size; - } - - NAN_INLINE char* operator*() { return buf; } - - NAN_INLINE ~NanAsciiString() { - delete[] buf; - } - - private: - char *buf; - int size; - }; - - class NanUtf8String { - public: - NAN_INLINE explicit NanUtf8String(v8::Handle from) { - v8::Local toStr = from->ToString(); - int buf_size = toStr->Utf8Length() + 1; - buf = new char[buf_size]; - size = toStr->WriteUtf8(buf, buf_size); - } - - NAN_INLINE int Size() const { - return size; - } - - NAN_INLINE char* operator*() { return buf; } - - NAN_INLINE ~NanUtf8String() { - delete[] buf; - } - - private: - char *buf; - int size; - }; - - class NanUcs2String { - public: - NAN_INLINE explicit NanUcs2String(v8::Handle from) { - v8::Local toStr = from->ToString(); - int buf_size = toStr->Length() + 1; - buf = new uint16_t[buf_size]; - size = toStr->Write(buf, 0, buf_size); - } - - NAN_INLINE int Size() const { - return size; - } - - NAN_INLINE uint16_t* operator*() { return buf; } - - NAN_INLINE ~NanUcs2String() { - delete[] buf; - } - - private: - uint16_t *buf; - int size; - }; - -#endif // NODE_MODULE_VERSION - -typedef void (*NanFreeCallback)(char *data, void *hint); - -#define NAN_METHOD(name) _NAN_METHOD_RETURN_TYPE name(_NAN_METHOD_ARGS) -#define NAN_GETTER(name) \ - _NAN_GETTER_RETURN_TYPE name( \ - v8::Local property \ - , _NAN_GETTER_ARGS) -#define NAN_SETTER(name) \ - _NAN_SETTER_RETURN_TYPE name( \ - v8::Local property \ - , v8::Local value \ - , _NAN_SETTER_ARGS) -#define NAN_PROPERTY_GETTER(name) \ - _NAN_PROPERTY_GETTER_RETURN_TYPE name( \ - v8::Local property \ - , _NAN_PROPERTY_GETTER_ARGS) -#define NAN_PROPERTY_SETTER(name) \ - _NAN_PROPERTY_SETTER_RETURN_TYPE name( \ - v8::Local property \ - , v8::Local value \ - , _NAN_PROPERTY_SETTER_ARGS) -#define NAN_PROPERTY_ENUMERATOR(name) \ - _NAN_PROPERTY_ENUMERATOR_RETURN_TYPE name(_NAN_PROPERTY_ENUMERATOR_ARGS) -#define NAN_PROPERTY_DELETER(name) \ - _NAN_PROPERTY_DELETER_RETURN_TYPE name( \ - v8::Local property \ - , _NAN_PROPERTY_DELETER_ARGS) -#define NAN_PROPERTY_QUERY(name) \ - _NAN_PROPERTY_QUERY_RETURN_TYPE name( \ - v8::Local property \ - , _NAN_PROPERTY_QUERY_ARGS) -# define NAN_INDEX_GETTER(name) \ - _NAN_INDEX_GETTER_RETURN_TYPE name(uint32_t index, _NAN_INDEX_GETTER_ARGS) -#define NAN_INDEX_SETTER(name) \ - _NAN_INDEX_SETTER_RETURN_TYPE name( \ - uint32_t index \ - , v8::Local value \ - , _NAN_INDEX_SETTER_ARGS) -#define NAN_INDEX_ENUMERATOR(name) \ - _NAN_INDEX_ENUMERATOR_RETURN_TYPE name(_NAN_INDEX_ENUMERATOR_ARGS) -#define NAN_INDEX_DELETER(name) \ - _NAN_INDEX_DELETER_RETURN_TYPE name( \ - uint32_t index \ - , _NAN_INDEX_DELETER_ARGS) -#define NAN_INDEX_QUERY(name) \ - _NAN_INDEX_QUERY_RETURN_TYPE name(uint32_t index, _NAN_INDEX_QUERY_ARGS) - -class NanCallback { - public: - NanCallback() { - NanScope(); - v8::Local obj = NanNew(); - NanAssignPersistent(handle, obj); - } - - explicit NanCallback(const v8::Handle &fn) { - NanScope(); - v8::Local obj = NanNew(); - NanAssignPersistent(handle, obj); - SetFunction(fn); - } - - ~NanCallback() { - if (handle.IsEmpty()) return; - NanDisposePersistent(handle); - } - - NAN_INLINE void SetFunction(const v8::Handle &fn) { - NanScope(); - NanNew(handle)->Set(kCallbackIndex, fn); - } - - NAN_INLINE v8::Local GetFunction() const { - NanEscapableScope(); - return NanEscapeScope(NanNew(handle)->Get(kCallbackIndex) - .As()); - } - - NAN_INLINE bool IsEmpty() const { - NanScope(); - return NanNew(handle)->Get(kCallbackIndex)->IsUndefined(); - } - - v8::Handle Call(int argc, v8::Handle argv[]) const { - NanEscapableScope(); -#if (NODE_MODULE_VERSION > 0x000B) // 0.11.12+ - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - v8::Local callback = NanNew(handle)-> - Get(kCallbackIndex).As(); - return NanEscapeScope(node::MakeCallback( - isolate - , isolate->GetCurrentContext()->Global() - , callback - , argc - , argv - )); -#else -#if NODE_VERSION_AT_LEAST(0, 8, 0) - v8::Local callback = handle-> - Get(kCallbackIndex).As(); - return NanEscapeScope(node::MakeCallback( - v8::Context::GetCurrent()->Global() - , callback - , argc - , argv - )); -#else - v8::Local callback = handle-> - Get(kCallbackIndex).As(); - return NanEscapeScope(NanMakeCallback( - v8::Context::GetCurrent()->Global(), callback, argc, argv)); -#endif -#endif - } - - private: - v8::Persistent handle; - static const uint32_t kCallbackIndex = 0; -}; - -/* abstract */ class NanAsyncWorker { - public: - explicit NanAsyncWorker(NanCallback *callback) - : callback(callback), errmsg_(NULL) { - request.data = this; - - NanScope(); - v8::Local obj = NanNew(); - NanAssignPersistent(persistentHandle, obj); - } - - virtual ~NanAsyncWorker() { - NanScope(); - - if (!persistentHandle.IsEmpty()) - NanDisposePersistent(persistentHandle); - if (callback) - delete callback; - if (errmsg_) - delete[] errmsg_; - } - - virtual void WorkComplete() { - NanScope(); - - if (errmsg_ == NULL) - HandleOKCallback(); - else - HandleErrorCallback(); - delete callback; - callback = NULL; - } - - NAN_INLINE void SaveToPersistent( - const char *key, const v8::Local &obj) { - v8::Local handle = NanNew(persistentHandle); - handle->Set(NanNew(key), obj); - } - - v8::Local GetFromPersistent(const char *key) const { - NanEscapableScope(); - v8::Local handle = NanNew(persistentHandle); - return NanEscapeScope(handle->Get(NanNew(key)).As()); - } - - virtual void Execute() = 0; - - uv_work_t request; - - protected: - v8::Persistent persistentHandle; - NanCallback *callback; - - virtual void HandleOKCallback() { - NanScope(); - - callback->Call(0, NULL); - } - - virtual void HandleErrorCallback() { - NanScope(); - - v8::Local argv[] = { - v8::Exception::Error(NanNew(ErrorMessage())) - }; - callback->Call(1, argv); - } - - void SetErrorMessage(const char *msg) { - if (errmsg_) { - delete[] errmsg_; - } - - size_t size = strlen(msg) + 1; - errmsg_ = new char[size]; - memcpy(errmsg_, msg, size); - } - - const char* ErrorMessage() const { - return errmsg_; - } - - private: - char *errmsg_; -}; - -NAN_INLINE void NanAsyncExecute (uv_work_t* req) { - NanAsyncWorker *worker = static_cast(req->data); - worker->Execute(); -} - -NAN_INLINE void NanAsyncExecuteComplete (uv_work_t* req) { - NanAsyncWorker* worker = static_cast(req->data); - worker->WorkComplete(); - delete worker; -} - -NAN_INLINE void NanAsyncQueueWorker (NanAsyncWorker* worker) { - uv_queue_work( - uv_default_loop() - , &worker->request - , NanAsyncExecute - , (uv_after_work_cb)NanAsyncExecuteComplete - ); -} - -//// Base 64 //// - -#define _nan_base64_encoded_size(size) ((size + 2 - ((size + 2) % 3)) / 3 * 4) - -// Doesn't check for padding at the end. Can be 1-2 bytes over. -NAN_INLINE size_t _nan_base64_decoded_size_fast(size_t size) { - size_t remainder = size % 4; - - size = (size / 4) * 3; - if (remainder) { - if (size == 0 && remainder == 1) { - // special case: 1-byte input cannot be decoded - size = 0; - } else { - // non-padded input, add 1 or 2 extra bytes - size += 1 + (remainder == 3); - } - } - - return size; -} - -template -NAN_INLINE size_t _nan_base64_decoded_size( - const T* src - , size_t size -) { - if (size == 0) - return 0; - - if (src[size - 1] == '=') - size--; - if (size > 0 && src[size - 1] == '=') - size--; - - return _nan_base64_decoded_size_fast(size); -} - -// supports regular and URL-safe base64 -static const int _nan_unbase64_table[] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -1, -1, -2, -1, -1 - , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 - , -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 62, -1, 63 - , 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1 - , -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 - , 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63 - , -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 - , 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 - , -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 - , -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 - , -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 -}; - -#define _nan_unbase64(x) _nan_unbase64_table[(uint8_t)(x)] - -template static size_t _nan_base64_decode( - char* buf - , size_t len - , const T* src - , const size_t srcLen -) { - char* dst = buf; - char* dstEnd = buf + len; - const T* srcEnd = src + srcLen; - - while (src < srcEnd && dst < dstEnd) { - ptrdiff_t remaining = srcEnd - src; - char a, b, c, d; - - while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--; - if (remaining == 0 || *src == '=') break; - a = _nan_unbase64(*src++); - - while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--; - if (remaining <= 1 || *src == '=') break; - b = _nan_unbase64(*src++); - - *dst++ = (a << 2) | ((b & 0x30) >> 4); - if (dst == dstEnd) break; - - while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--; - if (remaining <= 2 || *src == '=') break; - c = _nan_unbase64(*src++); - - *dst++ = ((b & 0x0F) << 4) | ((c & 0x3C) >> 2); - if (dst == dstEnd) break; - - while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--; - if (remaining <= 3 || *src == '=') break; - d = _nan_unbase64(*src++); - - *dst++ = ((c & 0x03) << 6) | (d & 0x3F); - } - - return dst - buf; -} - -//// HEX //// - -template unsigned _nan_hex2bin(T c) { - if (c >= '0' && c <= '9') return c - '0'; - if (c >= 'A' && c <= 'F') return 10 + (c - 'A'); - if (c >= 'a' && c <= 'f') return 10 + (c - 'a'); - return static_cast(-1); -} - -template static size_t _nan_hex_decode( - char* buf - , size_t len - , const T* src - , const size_t srcLen -) { - size_t i; - for (i = 0; i < len && i * 2 + 1 < srcLen; ++i) { - unsigned a = _nan_hex2bin(src[i * 2 + 0]); - unsigned b = _nan_hex2bin(src[i * 2 + 1]); - if (!~a || !~b) return i; - buf[i] = a * 16 + b; - } - - return i; -} - -static bool _NanGetExternalParts( - v8::Handle val - , const char** data - , size_t* len -) { - if (node::Buffer::HasInstance(val)) { - *data = node::Buffer::Data(val.As()); - *len = node::Buffer::Length(val.As()); - return true; - } - - assert(val->IsString()); - v8::Local str = NanNew(val.As()); - - if (str->IsExternalAscii()) { - const v8::String::ExternalAsciiStringResource* ext; - ext = str->GetExternalAsciiStringResource(); - *data = ext->data(); - *len = ext->length(); - return true; - - } else if (str->IsExternal()) { - const v8::String::ExternalStringResource* ext; - ext = str->GetExternalStringResource(); - *data = reinterpret_cast(ext->data()); - *len = ext->length(); - return true; - } - - return false; -} - -namespace Nan { - enum Encoding {ASCII, UTF8, BASE64, UCS2, BINARY, HEX, BUFFER}; -} - -/* NAN_DEPRECATED */ NAN_INLINE void* _NanRawString( - v8::Handle from - , enum Nan::Encoding encoding - , size_t *datalen - , void *buf - , size_t buflen - , int flags -) { - NanScope(); - - size_t sz_; - size_t term_len = !(flags & v8::String::NO_NULL_TERMINATION); - char *data = NULL; - size_t len; - bool is_extern = _NanGetExternalParts( - from - , const_cast(&data) - , &len); - - if (is_extern && !term_len) { - NanSetPointerSafe(datalen, len); - return data; - } - - v8::Local toStr = from->ToString(); - - char *to = static_cast(buf); - - switch (encoding) { - case Nan::ASCII: -#if NODE_MODULE_VERSION < 0x000C - sz_ = toStr->Length(); - if (to == NULL) { - to = new char[sz_ + term_len]; - } else { - assert(buflen >= sz_ + term_len && "too small buffer"); - } - NanSetPointerSafe( - datalen - , toStr->WriteAscii(to, 0, static_cast(sz_ + term_len), flags)); - return to; -#endif - case Nan::BINARY: - case Nan::BUFFER: - sz_ = toStr->Length(); - if (to == NULL) { - to = new char[sz_ + term_len]; - } else { - assert(buflen >= sz_ + term_len && "too small buffer"); - } -#if NODE_MODULE_VERSION < 0x000C - { - uint16_t* twobytebuf = new uint16_t[sz_ + term_len]; - - size_t len = toStr->Write(twobytebuf, 0, - static_cast(sz_ + term_len), flags); - - for (size_t i = 0; i < sz_ + term_len && i < len + term_len; i++) { - unsigned char *b = reinterpret_cast(&twobytebuf[i]); - to[i] = *b; - } - - NanSetPointerSafe(datalen, len); - - delete[] twobytebuf; - return to; - } -#else - NanSetPointerSafe( - datalen, - toStr->WriteOneByte( - reinterpret_cast(to) - , 0 - , static_cast(sz_ + term_len) - , flags)); - return to; -#endif - case Nan::UTF8: - sz_ = toStr->Utf8Length(); - if (to == NULL) { - to = new char[sz_ + term_len]; - } else { - assert(buflen >= sz_ + term_len && "too small buffer"); - } - NanSetPointerSafe( - datalen - , toStr->WriteUtf8(to, static_cast(sz_ + term_len) - , NULL, flags) - - term_len); - return to; - case Nan::BASE64: - { - v8::String::Value value(toStr); - sz_ = _nan_base64_decoded_size(*value, value.length()); - if (to == NULL) { - to = new char[sz_ + term_len]; - } else { - assert(buflen >= sz_ + term_len); - } - NanSetPointerSafe( - datalen - , _nan_base64_decode(to, sz_, *value, value.length())); - if (term_len) { - to[sz_] = '\0'; - } - return to; - } - case Nan::UCS2: - { - sz_ = toStr->Length(); - if (to == NULL) { - to = new char[(sz_ + term_len) * 2]; - } else { - assert(buflen >= (sz_ + term_len) * 2 && "too small buffer"); - } - - int bc = 2 * toStr->Write( - reinterpret_cast(to) - , 0 - , static_cast(sz_ + term_len) - , flags); - NanSetPointerSafe(datalen, bc); - return to; - } - case Nan::HEX: - { - v8::String::Value value(toStr); - sz_ = value.length(); - assert(!(sz_ & 1) && "bad hex data"); - if (to == NULL) { - to = new char[sz_ / 2 + term_len]; - } else { - assert(buflen >= sz_ / 2 + term_len && "too small buffer"); - } - NanSetPointerSafe( - datalen - , _nan_hex_decode(to, sz_ / 2, *value, value.length())); - } - if (term_len) { - to[sz_ / 2] = '\0'; - } - return to; - default: - assert(0 && "unknown encoding"); - } - return to; -} - -NAN_DEPRECATED NAN_INLINE void* NanRawString( - v8::Handle from - , enum Nan::Encoding encoding - , size_t *datalen - , void *buf - , size_t buflen - , int flags -) { - return _NanRawString(from, encoding, datalen, buf, buflen, flags); -} - - -NAN_DEPRECATED NAN_INLINE char* NanCString( - v8::Handle from - , size_t *datalen - , char *buf = NULL - , size_t buflen = 0 - , int flags = v8::String::NO_OPTIONS -) { - return static_cast( - _NanRawString(from, Nan::UTF8, datalen, buf, buflen, flags) - ); -} - -NAN_INLINE void NanSetPrototypeTemplate( - v8::Local templ - , const char *name - , v8::Handle value -) { - NanSetTemplate(templ->PrototypeTemplate(), name, value); -} - -NAN_INLINE void NanSetPrototypeTemplate( - v8::Local templ - , v8::Handle name - , v8::Handle value - , v8::PropertyAttribute attributes -) { - NanSetTemplate(templ->PrototypeTemplate(), name, value, attributes); -} - -NAN_INLINE void NanSetInstanceTemplate( - v8::Local templ - , const char *name - , v8::Handle value -) { - NanSetTemplate(templ->InstanceTemplate(), name, value); -} - -NAN_INLINE void NanSetInstanceTemplate( - v8::Local templ - , v8::Handle name - , v8::Handle value - , v8::PropertyAttribute attributes -) { - NanSetTemplate(templ->InstanceTemplate(), name, value, attributes); -} - -#endif // NAN_H_ diff --git a/node_modules/mongodb/node_modules/bson/node_modules/nan/package.json b/node_modules/mongodb/node_modules/bson/node_modules/nan/package.json deleted file mode 100644 index 25a90e8..0000000 --- a/node_modules/mongodb/node_modules/bson/node_modules/nan/package.json +++ /dev/null @@ -1,79 +0,0 @@ -{ - "name": "nan", - "version": "1.3.0", - "description": "Native Abstractions for Node.js: C++ header for Node 0.8->0.12 compatibility", - "main": "include_dirs.js", - "repository": { - "type": "git", - "url": "git://github.com/rvagg/nan.git" - }, - "scripts": { - "test": "tap --gc test/js/*-test.js", - "rebuild-tests": "node-gyp rebuild --directory test" - }, - "contributors": [ - { - "name": "Rod Vagg", - "email": "r@va.gg", - "url": "https://github.com/rvagg" - }, - { - "name": "Benjamin Byholm", - "email": "bbyholm@abo.fi", - "url": "https://github.com/kkoopa/" - }, - { - "name": "Trevor Norris", - "email": "trev.norris@gmail.com", - "url": "https://github.com/trevnorris" - }, - { - "name": "Nathan Rajlich", - "email": "nathan@tootallnate.net", - "url": "https://github.com/TooTallNate" - }, - { - "name": "Brett Lawson", - "email": "brett19@gmail.com", - "url": "https://github.com/brett19" - }, - { - "name": "Ben Noordhuis", - "email": "info@bnoordhuis.nl", - "url": "https://github.com/bnoordhuis" - } - ], - "devDependencies": { - "bindings": "~1.2.1", - "node-gyp": "~1.0.1", - "tap": "~0.4.12", - "xtend": "~4.0.0" - }, - "license": "MIT", - "gitHead": "e482fbe142e58373d5a24f4e5a60c61e22a13f83", - "bugs": { - "url": "https://github.com/rvagg/nan/issues" - }, - "homepage": "https://github.com/rvagg/nan", - "_id": "nan@1.3.0", - "_shasum": "9a5b8d5ef97a10df3050e59b2c362d3baf779742", - "_from": "nan@1.3.0", - "_npmVersion": "1.4.21", - "_npmUser": { - "name": "rvagg", - "email": "rod@vagg.org" - }, - "maintainers": [ - { - "name": "rvagg", - "email": "rod@vagg.org" - } - ], - "dist": { - "shasum": "9a5b8d5ef97a10df3050e59b2c362d3baf779742", - "tarball": "http://registry.npmjs.org/nan/-/nan-1.3.0.tgz" - }, - "directories": {}, - "_resolved": "https://registry.npmjs.org/nan/-/nan-1.3.0.tgz", - "readme": "ERROR: No README data found!" -} diff --git a/node_modules/mongodb/node_modules/bson/package.json b/node_modules/mongodb/node_modules/bson/package.json deleted file mode 100644 index b9c10be..0000000 --- a/node_modules/mongodb/node_modules/bson/package.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - "name": "bson", - "description": "A bson parser for node.js and the browser", - "keywords": [ - "mongodb", - "bson", - "parser" - ], - "version": "0.2.15", - "author": { - "name": "Christian Amor Kvalheim", - "email": "christkv@gmail.com" - }, - "contributors": [], - "repository": { - "type": "git", - "url": "git://github.com/mongodb/js-bson.git" - }, - "bugs": { - "url": "https://github.com/mongodb/js-bson/issues" - }, - "dependencies": { - "nan": "1.3.0" - }, - "devDependencies": { - "nodeunit": "0.9.0", - "gleak": "0.2.3", - "one": "2.X.X" - }, - "config": { - "native": false - }, - "main": "./lib/bson/index", - "directories": { - "lib": "./lib/bson" - }, - "engines": { - "node": ">=0.6.19" - }, - "scripts": { - "install": "(node-gyp rebuild 2> builderror.log) || (exit 0)", - "test": "nodeunit ./test/node && TEST_NATIVE=TRUE nodeunit ./test/node" - }, - "browser": "lib/bson/bson.js", - "licenses": [ - { - "type": "Apache License, Version 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0" - } - ], - "homepage": "https://github.com/mongodb/js-bson", - "_id": "bson@0.2.15", - "dist": { - "shasum": "556402c74bf33d8008122cc3091dc8b3b90e330c", - "tarball": "http://registry.npmjs.org/bson/-/bson-0.2.15.tgz" - }, - "_from": "bson@~0.2", - "_npmVersion": "1.4.3", - "_npmUser": { - "name": "christkv", - "email": "christkv@gmail.com" - }, - "maintainers": [ - { - "name": "octave", - "email": "chinsay@gmail.com" - }, - { - "name": "christkv", - "email": "christkv@gmail.com" - } - ], - "_shasum": "556402c74bf33d8008122cc3091dc8b3b90e330c", - "_resolved": "https://registry.npmjs.org/bson/-/bson-0.2.15.tgz", - "readme": "ERROR: No README data found!" -} diff --git a/node_modules/mongodb/node_modules/bson/tools/gleak.js b/node_modules/mongodb/node_modules/bson/tools/gleak.js deleted file mode 100644 index c707cfc..0000000 --- a/node_modules/mongodb/node_modules/bson/tools/gleak.js +++ /dev/null @@ -1,21 +0,0 @@ - -var gleak = require('gleak')(); -gleak.ignore('AssertionError'); -gleak.ignore('testFullSpec_param_found'); -gleak.ignore('events'); -gleak.ignore('Uint8Array'); -gleak.ignore('Uint8ClampedArray'); -gleak.ignore('TAP_Global_Harness'); -gleak.ignore('setImmediate'); -gleak.ignore('clearImmediate'); - -gleak.ignore('DTRACE_NET_SERVER_CONNECTION'); -gleak.ignore('DTRACE_NET_STREAM_END'); -gleak.ignore('DTRACE_NET_SOCKET_READ'); -gleak.ignore('DTRACE_NET_SOCKET_WRITE'); -gleak.ignore('DTRACE_HTTP_SERVER_REQUEST'); -gleak.ignore('DTRACE_HTTP_SERVER_RESPONSE'); -gleak.ignore('DTRACE_HTTP_CLIENT_REQUEST'); -gleak.ignore('DTRACE_HTTP_CLIENT_RESPONSE'); - -module.exports = gleak; diff --git a/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/MIT.LICENSE b/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/MIT.LICENSE deleted file mode 100644 index 7c435ba..0000000 --- a/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/MIT.LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2008-2011 Pivotal Labs - -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/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine-html.js b/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine-html.js deleted file mode 100644 index 7383401..0000000 --- a/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine-html.js +++ /dev/null @@ -1,190 +0,0 @@ -jasmine.TrivialReporter = function(doc) { - this.document = doc || document; - this.suiteDivs = {}; - this.logRunningSpecs = false; -}; - -jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) { - var el = document.createElement(type); - - for (var i = 2; i < arguments.length; i++) { - var child = arguments[i]; - - if (typeof child === 'string') { - el.appendChild(document.createTextNode(child)); - } else { - if (child) { el.appendChild(child); } - } - } - - for (var attr in attrs) { - if (attr == "className") { - el[attr] = attrs[attr]; - } else { - el.setAttribute(attr, attrs[attr]); - } - } - - return el; -}; - -jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) { - var showPassed, showSkipped; - - this.outerDiv = this.createDom('div', { className: 'jasmine_reporter' }, - this.createDom('div', { className: 'banner' }, - this.createDom('div', { className: 'logo' }, - this.createDom('span', { className: 'title' }, "Jasmine"), - this.createDom('span', { className: 'version' }, runner.env.versionString())), - this.createDom('div', { className: 'options' }, - "Show ", - showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }), - this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "), - showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }), - this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped") - ) - ), - - this.runnerDiv = this.createDom('div', { className: 'runner running' }, - this.createDom('a', { className: 'run_spec', href: '?' }, "run all"), - this.runnerMessageSpan = this.createDom('span', {}, "Running..."), - this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, "")) - ); - - this.document.body.appendChild(this.outerDiv); - - var suites = runner.suites(); - for (var i = 0; i < suites.length; i++) { - var suite = suites[i]; - var suiteDiv = this.createDom('div', { className: 'suite' }, - this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"), - this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description)); - this.suiteDivs[suite.id] = suiteDiv; - var parentDiv = this.outerDiv; - if (suite.parentSuite) { - parentDiv = this.suiteDivs[suite.parentSuite.id]; - } - parentDiv.appendChild(suiteDiv); - } - - this.startedAt = new Date(); - - var self = this; - showPassed.onclick = function(evt) { - if (showPassed.checked) { - self.outerDiv.className += ' show-passed'; - } else { - self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, ''); - } - }; - - showSkipped.onclick = function(evt) { - if (showSkipped.checked) { - self.outerDiv.className += ' show-skipped'; - } else { - self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, ''); - } - }; -}; - -jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) { - var results = runner.results(); - var className = (results.failedCount > 0) ? "runner failed" : "runner passed"; - this.runnerDiv.setAttribute("class", className); - //do it twice for IE - this.runnerDiv.setAttribute("className", className); - var specs = runner.specs(); - var specCount = 0; - for (var i = 0; i < specs.length; i++) { - if (this.specFilter(specs[i])) { - specCount++; - } - } - var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s"); - message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s"; - this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild); - - this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString())); -}; - -jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) { - var results = suite.results(); - var status = results.passed() ? 'passed' : 'failed'; - if (results.totalCount === 0) { // todo: change this to check results.skipped - status = 'skipped'; - } - this.suiteDivs[suite.id].className += " " + status; -}; - -jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) { - if (this.logRunningSpecs) { - this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...'); - } -}; - -jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) { - var results = spec.results(); - var status = results.passed() ? 'passed' : 'failed'; - if (results.skipped) { - status = 'skipped'; - } - var specDiv = this.createDom('div', { className: 'spec ' + status }, - this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"), - this.createDom('a', { - className: 'description', - href: '?spec=' + encodeURIComponent(spec.getFullName()), - title: spec.getFullName() - }, spec.description)); - - - var resultItems = results.getItems(); - var messagesDiv = this.createDom('div', { className: 'messages' }); - for (var i = 0; i < resultItems.length; i++) { - var result = resultItems[i]; - - if (result.type == 'log') { - messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString())); - } else if (result.type == 'expect' && result.passed && !result.passed()) { - messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message)); - - if (result.trace.stack) { - messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack)); - } - } - } - - if (messagesDiv.childNodes.length > 0) { - specDiv.appendChild(messagesDiv); - } - - this.suiteDivs[spec.suite.id].appendChild(specDiv); -}; - -jasmine.TrivialReporter.prototype.log = function() { - var console = jasmine.getGlobal().console; - if (console && console.log) { - if (console.log.apply) { - console.log.apply(console, arguments); - } else { - console.log(arguments); // ie fix: console.log.apply doesn't exist on ie - } - } -}; - -jasmine.TrivialReporter.prototype.getLocation = function() { - return this.document.location; -}; - -jasmine.TrivialReporter.prototype.specFilter = function(spec) { - var paramMap = {}; - var params = this.getLocation().search.substring(1).split('&'); - for (var i = 0; i < params.length; i++) { - var p = params[i].split('='); - paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]); - } - - if (!paramMap.spec) { - return true; - } - return spec.getFullName().indexOf(paramMap.spec) === 0; -}; diff --git a/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine.css b/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine.css deleted file mode 100644 index 6583fe7..0000000 --- a/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine.css +++ /dev/null @@ -1,166 +0,0 @@ -body { - font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; -} - - -.jasmine_reporter a:visited, .jasmine_reporter a { - color: #303; -} - -.jasmine_reporter a:hover, .jasmine_reporter a:active { - color: blue; -} - -.run_spec { - float:right; - padding-right: 5px; - font-size: .8em; - text-decoration: none; -} - -.jasmine_reporter { - margin: 0 5px; -} - -.banner { - color: #303; - background-color: #fef; - padding: 5px; -} - -.logo { - float: left; - font-size: 1.1em; - padding-left: 5px; -} - -.logo .version { - font-size: .6em; - padding-left: 1em; -} - -.runner.running { - background-color: yellow; -} - - -.options { - text-align: right; - font-size: .8em; -} - - - - -.suite { - border: 1px outset gray; - margin: 5px 0; - padding-left: 1em; -} - -.suite .suite { - margin: 5px; -} - -.suite.passed { - background-color: #dfd; -} - -.suite.failed { - background-color: #fdd; -} - -.spec { - margin: 5px; - padding-left: 1em; - clear: both; -} - -.spec.failed, .spec.passed, .spec.skipped { - padding-bottom: 5px; - border: 1px solid gray; -} - -.spec.failed { - background-color: #fbb; - border-color: red; -} - -.spec.passed { - background-color: #bfb; - border-color: green; -} - -.spec.skipped { - background-color: #bbb; -} - -.messages { - border-left: 1px dashed gray; - padding-left: 1em; - padding-right: 1em; -} - -.passed { - background-color: #cfc; - display: none; -} - -.failed { - background-color: #fbb; -} - -.skipped { - color: #777; - background-color: #eee; - display: none; -} - - -/*.resultMessage {*/ - /*white-space: pre;*/ -/*}*/ - -.resultMessage span.result { - display: block; - line-height: 2em; - color: black; -} - -.resultMessage .mismatch { - color: black; -} - -.stackTrace { - white-space: pre; - font-size: .8em; - margin-left: 10px; - max-height: 5em; - overflow: auto; - border: 1px inset red; - padding: 1em; - background: #eef; -} - -.finished-at { - padding-left: 1em; - font-size: .6em; -} - -.show-passed .passed, -.show-skipped .skipped { - display: block; -} - - -#jasmine_content { - position:fixed; - right: 100%; -} - -.runner { - border: 1px solid gray; - display: block; - margin: 5px 0; - padding: 2px 0 2px 10px; -} diff --git a/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine.js b/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine.js deleted file mode 100644 index c3d2dc7..0000000 --- a/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine.js +++ /dev/null @@ -1,2476 +0,0 @@ -var isCommonJS = typeof window == "undefined"; - -/** - * Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework. - * - * @namespace - */ -var jasmine = {}; -if (isCommonJS) exports.jasmine = jasmine; -/** - * @private - */ -jasmine.unimplementedMethod_ = function() { - throw new Error("unimplemented method"); -}; - -/** - * Use jasmine.undefined instead of undefined, since undefined is just - * a plain old variable and may be redefined by somebody else. - * - * @private - */ -jasmine.undefined = jasmine.___undefined___; - -/** - * Show diagnostic messages in the console if set to true - * - */ -jasmine.VERBOSE = false; - -/** - * Default interval in milliseconds for event loop yields (e.g. to allow network activity or to refresh the screen with the HTML-based runner). Small values here may result in slow test running. Zero means no updates until all tests have completed. - * - */ -jasmine.DEFAULT_UPDATE_INTERVAL = 250; - -/** - * Default timeout interval in milliseconds for waitsFor() blocks. - */ -jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000; - -jasmine.getGlobal = function() { - function getGlobal() { - return this; - } - - return getGlobal(); -}; - -/** - * Allows for bound functions to be compared. Internal use only. - * - * @ignore - * @private - * @param base {Object} bound 'this' for the function - * @param name {Function} function to find - */ -jasmine.bindOriginal_ = function(base, name) { - var original = base[name]; - if (original.apply) { - return function() { - return original.apply(base, arguments); - }; - } else { - // IE support - return jasmine.getGlobal()[name]; - } -}; - -jasmine.setTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'setTimeout'); -jasmine.clearTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearTimeout'); -jasmine.setInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'setInterval'); -jasmine.clearInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearInterval'); - -jasmine.MessageResult = function(values) { - this.type = 'log'; - this.values = values; - this.trace = new Error(); // todo: test better -}; - -jasmine.MessageResult.prototype.toString = function() { - var text = ""; - for (var i = 0; i < this.values.length; i++) { - if (i > 0) text += " "; - if (jasmine.isString_(this.values[i])) { - text += this.values[i]; - } else { - text += jasmine.pp(this.values[i]); - } - } - return text; -}; - -jasmine.ExpectationResult = function(params) { - this.type = 'expect'; - this.matcherName = params.matcherName; - this.passed_ = params.passed; - this.expected = params.expected; - this.actual = params.actual; - this.message = this.passed_ ? 'Passed.' : params.message; - - var trace = (params.trace || new Error(this.message)); - this.trace = this.passed_ ? '' : trace; -}; - -jasmine.ExpectationResult.prototype.toString = function () { - return this.message; -}; - -jasmine.ExpectationResult.prototype.passed = function () { - return this.passed_; -}; - -/** - * Getter for the Jasmine environment. Ensures one gets created - */ -jasmine.getEnv = function() { - var env = jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env(); - return env; -}; - -/** - * @ignore - * @private - * @param value - * @returns {Boolean} - */ -jasmine.isArray_ = function(value) { - return jasmine.isA_("Array", value); -}; - -/** - * @ignore - * @private - * @param value - * @returns {Boolean} - */ -jasmine.isString_ = function(value) { - return jasmine.isA_("String", value); -}; - -/** - * @ignore - * @private - * @param value - * @returns {Boolean} - */ -jasmine.isNumber_ = function(value) { - return jasmine.isA_("Number", value); -}; - -/** - * @ignore - * @private - * @param {String} typeName - * @param value - * @returns {Boolean} - */ -jasmine.isA_ = function(typeName, value) { - return Object.prototype.toString.apply(value) === '[object ' + typeName + ']'; -}; - -/** - * Pretty printer for expecations. Takes any object and turns it into a human-readable string. - * - * @param value {Object} an object to be outputted - * @returns {String} - */ -jasmine.pp = function(value) { - var stringPrettyPrinter = new jasmine.StringPrettyPrinter(); - stringPrettyPrinter.format(value); - return stringPrettyPrinter.string; -}; - -/** - * Returns true if the object is a DOM Node. - * - * @param {Object} obj object to check - * @returns {Boolean} - */ -jasmine.isDomNode = function(obj) { - return obj.nodeType > 0; -}; - -/** - * Returns a matchable 'generic' object of the class type. For use in expecations of type when values don't matter. - * - * @example - * // don't care about which function is passed in, as long as it's a function - * expect(mySpy).toHaveBeenCalledWith(jasmine.any(Function)); - * - * @param {Class} clazz - * @returns matchable object of the type clazz - */ -jasmine.any = function(clazz) { - return new jasmine.Matchers.Any(clazz); -}; - -/** - * Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks. - * - * Spies should be created in test setup, before expectations. They can then be checked, using the standard Jasmine - * expectation syntax. Spies can be checked if they were called or not and what the calling params were. - * - * A Spy has the following fields: wasCalled, callCount, mostRecentCall, and argsForCall (see docs). - * - * Spies are torn down at the end of every spec. - * - * Note: Do not call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj. - * - * @example - * // a stub - * var myStub = jasmine.createSpy('myStub'); // can be used anywhere - * - * // spy example - * var foo = { - * not: function(bool) { return !bool; } - * } - * - * // actual foo.not will not be called, execution stops - * spyOn(foo, 'not'); - - // foo.not spied upon, execution will continue to implementation - * spyOn(foo, 'not').andCallThrough(); - * - * // fake example - * var foo = { - * not: function(bool) { return !bool; } - * } - * - * // foo.not(val) will return val - * spyOn(foo, 'not').andCallFake(function(value) {return value;}); - * - * // mock example - * foo.not(7 == 7); - * expect(foo.not).toHaveBeenCalled(); - * expect(foo.not).toHaveBeenCalledWith(true); - * - * @constructor - * @see spyOn, jasmine.createSpy, jasmine.createSpyObj - * @param {String} name - */ -jasmine.Spy = function(name) { - /** - * The name of the spy, if provided. - */ - this.identity = name || 'unknown'; - /** - * Is this Object a spy? - */ - this.isSpy = true; - /** - * The actual function this spy stubs. - */ - this.plan = function() { - }; - /** - * Tracking of the most recent call to the spy. - * @example - * var mySpy = jasmine.createSpy('foo'); - * mySpy(1, 2); - * mySpy.mostRecentCall.args = [1, 2]; - */ - this.mostRecentCall = {}; - - /** - * Holds arguments for each call to the spy, indexed by call count - * @example - * var mySpy = jasmine.createSpy('foo'); - * mySpy(1, 2); - * mySpy(7, 8); - * mySpy.mostRecentCall.args = [7, 8]; - * mySpy.argsForCall[0] = [1, 2]; - * mySpy.argsForCall[1] = [7, 8]; - */ - this.argsForCall = []; - this.calls = []; -}; - -/** - * Tells a spy to call through to the actual implemenatation. - * - * @example - * var foo = { - * bar: function() { // do some stuff } - * } - * - * // defining a spy on an existing property: foo.bar - * spyOn(foo, 'bar').andCallThrough(); - */ -jasmine.Spy.prototype.andCallThrough = function() { - this.plan = this.originalValue; - return this; -}; - -/** - * For setting the return value of a spy. - * - * @example - * // defining a spy from scratch: foo() returns 'baz' - * var foo = jasmine.createSpy('spy on foo').andReturn('baz'); - * - * // defining a spy on an existing property: foo.bar() returns 'baz' - * spyOn(foo, 'bar').andReturn('baz'); - * - * @param {Object} value - */ -jasmine.Spy.prototype.andReturn = function(value) { - this.plan = function() { - return value; - }; - return this; -}; - -/** - * For throwing an exception when a spy is called. - * - * @example - * // defining a spy from scratch: foo() throws an exception w/ message 'ouch' - * var foo = jasmine.createSpy('spy on foo').andThrow('baz'); - * - * // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch' - * spyOn(foo, 'bar').andThrow('baz'); - * - * @param {String} exceptionMsg - */ -jasmine.Spy.prototype.andThrow = function(exceptionMsg) { - this.plan = function() { - throw exceptionMsg; - }; - return this; -}; - -/** - * Calls an alternate implementation when a spy is called. - * - * @example - * var baz = function() { - * // do some stuff, return something - * } - * // defining a spy from scratch: foo() calls the function baz - * var foo = jasmine.createSpy('spy on foo').andCall(baz); - * - * // defining a spy on an existing property: foo.bar() calls an anonymnous function - * spyOn(foo, 'bar').andCall(function() { return 'baz';} ); - * - * @param {Function} fakeFunc - */ -jasmine.Spy.prototype.andCallFake = function(fakeFunc) { - this.plan = fakeFunc; - return this; -}; - -/** - * Resets all of a spy's the tracking variables so that it can be used again. - * - * @example - * spyOn(foo, 'bar'); - * - * foo.bar(); - * - * expect(foo.bar.callCount).toEqual(1); - * - * foo.bar.reset(); - * - * expect(foo.bar.callCount).toEqual(0); - */ -jasmine.Spy.prototype.reset = function() { - this.wasCalled = false; - this.callCount = 0; - this.argsForCall = []; - this.calls = []; - this.mostRecentCall = {}; -}; - -jasmine.createSpy = function(name) { - - var spyObj = function() { - spyObj.wasCalled = true; - spyObj.callCount++; - var args = jasmine.util.argsToArray(arguments); - spyObj.mostRecentCall.object = this; - spyObj.mostRecentCall.args = args; - spyObj.argsForCall.push(args); - spyObj.calls.push({object: this, args: args}); - return spyObj.plan.apply(this, arguments); - }; - - var spy = new jasmine.Spy(name); - - for (var prop in spy) { - spyObj[prop] = spy[prop]; - } - - spyObj.reset(); - - return spyObj; -}; - -/** - * Determines whether an object is a spy. - * - * @param {jasmine.Spy|Object} putativeSpy - * @returns {Boolean} - */ -jasmine.isSpy = function(putativeSpy) { - return putativeSpy && putativeSpy.isSpy; -}; - -/** - * Creates a more complicated spy: an Object that has every property a function that is a spy. Used for stubbing something - * large in one call. - * - * @param {String} baseName name of spy class - * @param {Array} methodNames array of names of methods to make spies - */ -jasmine.createSpyObj = function(baseName, methodNames) { - if (!jasmine.isArray_(methodNames) || methodNames.length === 0) { - throw new Error('createSpyObj requires a non-empty array of method names to create spies for'); - } - var obj = {}; - for (var i = 0; i < methodNames.length; i++) { - obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]); - } - return obj; -}; - -/** - * All parameters are pretty-printed and concatenated together, then written to the current spec's output. - * - * Be careful not to leave calls to jasmine.log in production code. - */ -jasmine.log = function() { - var spec = jasmine.getEnv().currentSpec; - spec.log.apply(spec, arguments); -}; - -/** - * Function that installs a spy on an existing object's method name. Used within a Spec to create a spy. - * - * @example - * // spy example - * var foo = { - * not: function(bool) { return !bool; } - * } - * spyOn(foo, 'not'); // actual foo.not will not be called, execution stops - * - * @see jasmine.createSpy - * @param obj - * @param methodName - * @returns a Jasmine spy that can be chained with all spy methods - */ -var spyOn = function(obj, methodName) { - return jasmine.getEnv().currentSpec.spyOn(obj, methodName); -}; -if (isCommonJS) exports.spyOn = spyOn; - -/** - * Creates a Jasmine spec that will be added to the current suite. - * - * // TODO: pending tests - * - * @example - * it('should be true', function() { - * expect(true).toEqual(true); - * }); - * - * @param {String} desc description of this specification - * @param {Function} func defines the preconditions and expectations of the spec - */ -var it = function(desc, func) { - return jasmine.getEnv().it(desc, func); -}; -if (isCommonJS) exports.it = it; - -/** - * Creates a disabled Jasmine spec. - * - * A convenience method that allows existing specs to be disabled temporarily during development. - * - * @param {String} desc description of this specification - * @param {Function} func defines the preconditions and expectations of the spec - */ -var xit = function(desc, func) { - return jasmine.getEnv().xit(desc, func); -}; -if (isCommonJS) exports.xit = xit; - -/** - * Starts a chain for a Jasmine expectation. - * - * It is passed an Object that is the actual value and should chain to one of the many - * jasmine.Matchers functions. - * - * @param {Object} actual Actual value to test against and expected value - */ -var expect = function(actual) { - return jasmine.getEnv().currentSpec.expect(actual); -}; -if (isCommonJS) exports.expect = expect; - -/** - * Defines part of a jasmine spec. Used in cominbination with waits or waitsFor in asynchrnous specs. - * - * @param {Function} func Function that defines part of a jasmine spec. - */ -var runs = function(func) { - jasmine.getEnv().currentSpec.runs(func); -}; -if (isCommonJS) exports.runs = runs; - -/** - * Waits a fixed time period before moving to the next block. - * - * @deprecated Use waitsFor() instead - * @param {Number} timeout milliseconds to wait - */ -var waits = function(timeout) { - jasmine.getEnv().currentSpec.waits(timeout); -}; -if (isCommonJS) exports.waits = waits; - -/** - * Waits for the latchFunction to return true before proceeding to the next block. - * - * @param {Function} latchFunction - * @param {String} optional_timeoutMessage - * @param {Number} optional_timeout - */ -var waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) { - jasmine.getEnv().currentSpec.waitsFor.apply(jasmine.getEnv().currentSpec, arguments); -}; -if (isCommonJS) exports.waitsFor = waitsFor; - -/** - * A function that is called before each spec in a suite. - * - * Used for spec setup, including validating assumptions. - * - * @param {Function} beforeEachFunction - */ -var beforeEach = function(beforeEachFunction) { - jasmine.getEnv().beforeEach(beforeEachFunction); -}; -if (isCommonJS) exports.beforeEach = beforeEach; - -/** - * A function that is called after each spec in a suite. - * - * Used for restoring any state that is hijacked during spec execution. - * - * @param {Function} afterEachFunction - */ -var afterEach = function(afterEachFunction) { - jasmine.getEnv().afterEach(afterEachFunction); -}; -if (isCommonJS) exports.afterEach = afterEach; - -/** - * Defines a suite of specifications. - * - * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared - * are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization - * of setup in some tests. - * - * @example - * // TODO: a simple suite - * - * // TODO: a simple suite with a nested describe block - * - * @param {String} description A string, usually the class under test. - * @param {Function} specDefinitions function that defines several specs. - */ -var describe = function(description, specDefinitions) { - return jasmine.getEnv().describe(description, specDefinitions); -}; -if (isCommonJS) exports.describe = describe; - -/** - * Disables a suite of specifications. Used to disable some suites in a file, or files, temporarily during development. - * - * @param {String} description A string, usually the class under test. - * @param {Function} specDefinitions function that defines several specs. - */ -var xdescribe = function(description, specDefinitions) { - return jasmine.getEnv().xdescribe(description, specDefinitions); -}; -if (isCommonJS) exports.xdescribe = xdescribe; - - -// Provide the XMLHttpRequest class for IE 5.x-6.x: -jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() { - function tryIt(f) { - try { - return f(); - } catch(e) { - } - return null; - } - - var xhr = tryIt(function() { - return new ActiveXObject("Msxml2.XMLHTTP.6.0"); - }) || - tryIt(function() { - return new ActiveXObject("Msxml2.XMLHTTP.3.0"); - }) || - tryIt(function() { - return new ActiveXObject("Msxml2.XMLHTTP"); - }) || - tryIt(function() { - return new ActiveXObject("Microsoft.XMLHTTP"); - }); - - if (!xhr) throw new Error("This browser does not support XMLHttpRequest."); - - return xhr; -} : XMLHttpRequest; -/** - * @namespace - */ -jasmine.util = {}; - -/** - * Declare that a child class inherit it's prototype from the parent class. - * - * @private - * @param {Function} childClass - * @param {Function} parentClass - */ -jasmine.util.inherit = function(childClass, parentClass) { - /** - * @private - */ - var subclass = function() { - }; - subclass.prototype = parentClass.prototype; - childClass.prototype = new subclass(); -}; - -jasmine.util.formatException = function(e) { - var lineNumber; - if (e.line) { - lineNumber = e.line; - } - else if (e.lineNumber) { - lineNumber = e.lineNumber; - } - - var file; - - if (e.sourceURL) { - file = e.sourceURL; - } - else if (e.fileName) { - file = e.fileName; - } - - var message = (e.name && e.message) ? (e.name + ': ' + e.message) : e.toString(); - - if (file && lineNumber) { - message += ' in ' + file + ' (line ' + lineNumber + ')'; - } - - return message; -}; - -jasmine.util.htmlEscape = function(str) { - if (!str) return str; - return str.replace(/&/g, '&') - .replace(//g, '>'); -}; - -jasmine.util.argsToArray = function(args) { - var arrayOfArgs = []; - for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]); - return arrayOfArgs; -}; - -jasmine.util.extend = function(destination, source) { - for (var property in source) destination[property] = source[property]; - return destination; -}; - -/** - * Environment for Jasmine - * - * @constructor - */ -jasmine.Env = function() { - this.currentSpec = null; - this.currentSuite = null; - this.currentRunner_ = new jasmine.Runner(this); - - this.reporter = new jasmine.MultiReporter(); - - this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL; - this.defaultTimeoutInterval = jasmine.DEFAULT_TIMEOUT_INTERVAL; - this.lastUpdate = 0; - this.specFilter = function() { - return true; - }; - - this.nextSpecId_ = 0; - this.nextSuiteId_ = 0; - this.equalityTesters_ = []; - - // wrap matchers - this.matchersClass = function() { - jasmine.Matchers.apply(this, arguments); - }; - jasmine.util.inherit(this.matchersClass, jasmine.Matchers); - - jasmine.Matchers.wrapInto_(jasmine.Matchers.prototype, this.matchersClass); -}; - - -jasmine.Env.prototype.setTimeout = jasmine.setTimeout; -jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout; -jasmine.Env.prototype.setInterval = jasmine.setInterval; -jasmine.Env.prototype.clearInterval = jasmine.clearInterval; - -/** - * @returns an object containing jasmine version build info, if set. - */ -jasmine.Env.prototype.version = function () { - if (jasmine.version_) { - return jasmine.version_; - } else { - throw new Error('Version not set'); - } -}; - -/** - * @returns string containing jasmine version build info, if set. - */ -jasmine.Env.prototype.versionString = function() { - if (!jasmine.version_) { - return "version unknown"; - } - - var version = this.version(); - var versionString = version.major + "." + version.minor + "." + version.build; - if (version.release_candidate) { - versionString += ".rc" + version.release_candidate; - } - versionString += " revision " + version.revision; - return versionString; -}; - -/** - * @returns a sequential integer starting at 0 - */ -jasmine.Env.prototype.nextSpecId = function () { - return this.nextSpecId_++; -}; - -/** - * @returns a sequential integer starting at 0 - */ -jasmine.Env.prototype.nextSuiteId = function () { - return this.nextSuiteId_++; -}; - -/** - * Register a reporter to receive status updates from Jasmine. - * @param {jasmine.Reporter} reporter An object which will receive status updates. - */ -jasmine.Env.prototype.addReporter = function(reporter) { - this.reporter.addReporter(reporter); -}; - -jasmine.Env.prototype.execute = function() { - this.currentRunner_.execute(); -}; - -jasmine.Env.prototype.describe = function(description, specDefinitions) { - var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite); - - var parentSuite = this.currentSuite; - if (parentSuite) { - parentSuite.add(suite); - } else { - this.currentRunner_.add(suite); - } - - this.currentSuite = suite; - - var declarationError = null; - try { - specDefinitions.call(suite); - } catch(e) { - declarationError = e; - } - - if (declarationError) { - this.it("encountered a declaration exception", function() { - throw declarationError; - }); - } - - this.currentSuite = parentSuite; - - return suite; -}; - -jasmine.Env.prototype.beforeEach = function(beforeEachFunction) { - if (this.currentSuite) { - this.currentSuite.beforeEach(beforeEachFunction); - } else { - this.currentRunner_.beforeEach(beforeEachFunction); - } -}; - -jasmine.Env.prototype.currentRunner = function () { - return this.currentRunner_; -}; - -jasmine.Env.prototype.afterEach = function(afterEachFunction) { - if (this.currentSuite) { - this.currentSuite.afterEach(afterEachFunction); - } else { - this.currentRunner_.afterEach(afterEachFunction); - } - -}; - -jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) { - return { - execute: function() { - } - }; -}; - -jasmine.Env.prototype.it = function(description, func) { - var spec = new jasmine.Spec(this, this.currentSuite, description); - this.currentSuite.add(spec); - this.currentSpec = spec; - - if (func) { - spec.runs(func); - } - - return spec; -}; - -jasmine.Env.prototype.xit = function(desc, func) { - return { - id: this.nextSpecId(), - runs: function() { - } - }; -}; - -jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) { - if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) { - return true; - } - - a.__Jasmine_been_here_before__ = b; - b.__Jasmine_been_here_before__ = a; - - var hasKey = function(obj, keyName) { - return obj !== null && obj[keyName] !== jasmine.undefined; - }; - - for (var property in b) { - if (!hasKey(a, property) && hasKey(b, property)) { - mismatchKeys.push("expected has key '" + property + "', but missing from actual."); - } - } - for (property in a) { - if (!hasKey(b, property) && hasKey(a, property)) { - mismatchKeys.push("expected missing key '" + property + "', but present in actual."); - } - } - for (property in b) { - if (property == '__Jasmine_been_here_before__') continue; - if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) { - mismatchValues.push("'" + property + "' was '" + (b[property] ? jasmine.util.htmlEscape(b[property].toString()) : b[property]) + "' in expected, but was '" + (a[property] ? jasmine.util.htmlEscape(a[property].toString()) : a[property]) + "' in actual."); - } - } - - if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) { - mismatchValues.push("arrays were not the same length"); - } - - delete a.__Jasmine_been_here_before__; - delete b.__Jasmine_been_here_before__; - return (mismatchKeys.length === 0 && mismatchValues.length === 0); -}; - -jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) { - mismatchKeys = mismatchKeys || []; - mismatchValues = mismatchValues || []; - - for (var i = 0; i < this.equalityTesters_.length; i++) { - var equalityTester = this.equalityTesters_[i]; - var result = equalityTester(a, b, this, mismatchKeys, mismatchValues); - if (result !== jasmine.undefined) return result; - } - - if (a === b) return true; - - if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null) { - return (a == jasmine.undefined && b == jasmine.undefined); - } - - if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) { - return a === b; - } - - if (a instanceof Date && b instanceof Date) { - return a.getTime() == b.getTime(); - } - - if (a instanceof jasmine.Matchers.Any) { - return a.matches(b); - } - - if (b instanceof jasmine.Matchers.Any) { - return b.matches(a); - } - - if (jasmine.isString_(a) && jasmine.isString_(b)) { - return (a == b); - } - - if (jasmine.isNumber_(a) && jasmine.isNumber_(b)) { - return (a == b); - } - - if (typeof a === "object" && typeof b === "object") { - return this.compareObjects_(a, b, mismatchKeys, mismatchValues); - } - - //Straight check - return (a === b); -}; - -jasmine.Env.prototype.contains_ = function(haystack, needle) { - if (jasmine.isArray_(haystack)) { - for (var i = 0; i < haystack.length; i++) { - if (this.equals_(haystack[i], needle)) return true; - } - return false; - } - return haystack.indexOf(needle) >= 0; -}; - -jasmine.Env.prototype.addEqualityTester = function(equalityTester) { - this.equalityTesters_.push(equalityTester); -}; -/** No-op base class for Jasmine reporters. - * - * @constructor - */ -jasmine.Reporter = function() { -}; - -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.reportRunnerStarting = function(runner) { -}; - -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.reportRunnerResults = function(runner) { -}; - -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.reportSuiteResults = function(suite) { -}; - -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.reportSpecStarting = function(spec) { -}; - -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.reportSpecResults = function(spec) { -}; - -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.log = function(str) { -}; - -/** - * Blocks are functions with executable code that make up a spec. - * - * @constructor - * @param {jasmine.Env} env - * @param {Function} func - * @param {jasmine.Spec} spec - */ -jasmine.Block = function(env, func, spec) { - this.env = env; - this.func = func; - this.spec = spec; -}; - -jasmine.Block.prototype.execute = function(onComplete) { - try { - this.func.apply(this.spec); - } catch (e) { - this.spec.fail(e); - } - onComplete(); -}; -/** JavaScript API reporter. - * - * @constructor - */ -jasmine.JsApiReporter = function() { - this.started = false; - this.finished = false; - this.suites_ = []; - this.results_ = {}; -}; - -jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) { - this.started = true; - var suites = runner.topLevelSuites(); - for (var i = 0; i < suites.length; i++) { - var suite = suites[i]; - this.suites_.push(this.summarize_(suite)); - } -}; - -jasmine.JsApiReporter.prototype.suites = function() { - return this.suites_; -}; - -jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) { - var isSuite = suiteOrSpec instanceof jasmine.Suite; - var summary = { - id: suiteOrSpec.id, - name: suiteOrSpec.description, - type: isSuite ? 'suite' : 'spec', - children: [] - }; - - if (isSuite) { - var children = suiteOrSpec.children(); - for (var i = 0; i < children.length; i++) { - summary.children.push(this.summarize_(children[i])); - } - } - return summary; -}; - -jasmine.JsApiReporter.prototype.results = function() { - return this.results_; -}; - -jasmine.JsApiReporter.prototype.resultsForSpec = function(specId) { - return this.results_[specId]; -}; - -//noinspection JSUnusedLocalSymbols -jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) { - this.finished = true; -}; - -//noinspection JSUnusedLocalSymbols -jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) { -}; - -//noinspection JSUnusedLocalSymbols -jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) { - this.results_[spec.id] = { - messages: spec.results().getItems(), - result: spec.results().failedCount > 0 ? "failed" : "passed" - }; -}; - -//noinspection JSUnusedLocalSymbols -jasmine.JsApiReporter.prototype.log = function(str) { -}; - -jasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){ - var results = {}; - for (var i = 0; i < specIds.length; i++) { - var specId = specIds[i]; - results[specId] = this.summarizeResult_(this.results_[specId]); - } - return results; -}; - -jasmine.JsApiReporter.prototype.summarizeResult_ = function(result){ - var summaryMessages = []; - var messagesLength = result.messages.length; - for (var messageIndex = 0; messageIndex < messagesLength; messageIndex++) { - var resultMessage = result.messages[messageIndex]; - summaryMessages.push({ - text: resultMessage.type == 'log' ? resultMessage.toString() : jasmine.undefined, - passed: resultMessage.passed ? resultMessage.passed() : true, - type: resultMessage.type, - message: resultMessage.message, - trace: { - stack: resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack : jasmine.undefined - } - }); - } - - return { - result : result.result, - messages : summaryMessages - }; -}; - -/** - * @constructor - * @param {jasmine.Env} env - * @param actual - * @param {jasmine.Spec} spec - */ -jasmine.Matchers = function(env, actual, spec, opt_isNot) { - this.env = env; - this.actual = actual; - this.spec = spec; - this.isNot = opt_isNot || false; - this.reportWasCalled_ = false; -}; - -// todo: @deprecated as of Jasmine 0.11, remove soon [xw] -jasmine.Matchers.pp = function(str) { - throw new Error("jasmine.Matchers.pp() is no longer supported, please use jasmine.pp() instead!"); -}; - -// todo: @deprecated Deprecated as of Jasmine 0.10. Rewrite your custom matchers to return true or false. [xw] -jasmine.Matchers.prototype.report = function(result, failing_message, details) { - throw new Error("As of jasmine 0.11, custom matchers must be implemented differently -- please see jasmine docs"); -}; - -jasmine.Matchers.wrapInto_ = function(prototype, matchersClass) { - for (var methodName in prototype) { - if (methodName == 'report') continue; - var orig = prototype[methodName]; - matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName, orig); - } -}; - -jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) { - return function() { - var matcherArgs = jasmine.util.argsToArray(arguments); - var result = matcherFunction.apply(this, arguments); - - if (this.isNot) { - result = !result; - } - - if (this.reportWasCalled_) return result; - - var message; - if (!result) { - if (this.message) { - message = this.message.apply(this, arguments); - if (jasmine.isArray_(message)) { - message = message[this.isNot ? 1 : 0]; - } - } else { - var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); }); - message = "Expected " + jasmine.pp(this.actual) + (this.isNot ? " not " : " ") + englishyPredicate; - if (matcherArgs.length > 0) { - for (var i = 0; i < matcherArgs.length; i++) { - if (i > 0) message += ","; - message += " " + jasmine.pp(matcherArgs[i]); - } - } - message += "."; - } - } - var expectationResult = new jasmine.ExpectationResult({ - matcherName: matcherName, - passed: result, - expected: matcherArgs.length > 1 ? matcherArgs : matcherArgs[0], - actual: this.actual, - message: message - }); - this.spec.addMatcherResult(expectationResult); - return jasmine.undefined; - }; -}; - - - - -/** - * toBe: compares the actual to the expected using === - * @param expected - */ -jasmine.Matchers.prototype.toBe = function(expected) { - return this.actual === expected; -}; - -/** - * toNotBe: compares the actual to the expected using !== - * @param expected - * @deprecated as of 1.0. Use not.toBe() instead. - */ -jasmine.Matchers.prototype.toNotBe = function(expected) { - return this.actual !== expected; -}; - -/** - * toEqual: compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc. - * - * @param expected - */ -jasmine.Matchers.prototype.toEqual = function(expected) { - return this.env.equals_(this.actual, expected); -}; - -/** - * toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual - * @param expected - * @deprecated as of 1.0. Use not.toNotEqual() instead. - */ -jasmine.Matchers.prototype.toNotEqual = function(expected) { - return !this.env.equals_(this.actual, expected); -}; - -/** - * Matcher that compares the actual to the expected using a regular expression. Constructs a RegExp, so takes - * a pattern or a String. - * - * @param expected - */ -jasmine.Matchers.prototype.toMatch = function(expected) { - return new RegExp(expected).test(this.actual); -}; - -/** - * Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch - * @param expected - * @deprecated as of 1.0. Use not.toMatch() instead. - */ -jasmine.Matchers.prototype.toNotMatch = function(expected) { - return !(new RegExp(expected).test(this.actual)); -}; - -/** - * Matcher that compares the actual to jasmine.undefined. - */ -jasmine.Matchers.prototype.toBeDefined = function() { - return (this.actual !== jasmine.undefined); -}; - -/** - * Matcher that compares the actual to jasmine.undefined. - */ -jasmine.Matchers.prototype.toBeUndefined = function() { - return (this.actual === jasmine.undefined); -}; - -/** - * Matcher that compares the actual to null. - */ -jasmine.Matchers.prototype.toBeNull = function() { - return (this.actual === null); -}; - -/** - * Matcher that boolean not-nots the actual. - */ -jasmine.Matchers.prototype.toBeTruthy = function() { - return !!this.actual; -}; - - -/** - * Matcher that boolean nots the actual. - */ -jasmine.Matchers.prototype.toBeFalsy = function() { - return !this.actual; -}; - - -/** - * Matcher that checks to see if the actual, a Jasmine spy, was called. - */ -jasmine.Matchers.prototype.toHaveBeenCalled = function() { - if (arguments.length > 0) { - throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith'); - } - - if (!jasmine.isSpy(this.actual)) { - throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); - } - - this.message = function() { - return [ - "Expected spy " + this.actual.identity + " to have been called.", - "Expected spy " + this.actual.identity + " not to have been called." - ]; - }; - - return this.actual.wasCalled; -}; - -/** @deprecated Use expect(xxx).toHaveBeenCalled() instead */ -jasmine.Matchers.prototype.wasCalled = jasmine.Matchers.prototype.toHaveBeenCalled; - -/** - * Matcher that checks to see if the actual, a Jasmine spy, was not called. - * - * @deprecated Use expect(xxx).not.toHaveBeenCalled() instead - */ -jasmine.Matchers.prototype.wasNotCalled = function() { - if (arguments.length > 0) { - throw new Error('wasNotCalled does not take arguments'); - } - - if (!jasmine.isSpy(this.actual)) { - throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); - } - - this.message = function() { - return [ - "Expected spy " + this.actual.identity + " to not have been called.", - "Expected spy " + this.actual.identity + " to have been called." - ]; - }; - - return !this.actual.wasCalled; -}; - -/** - * Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters. - * - * @example - * - */ -jasmine.Matchers.prototype.toHaveBeenCalledWith = function() { - var expectedArgs = jasmine.util.argsToArray(arguments); - if (!jasmine.isSpy(this.actual)) { - throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); - } - this.message = function() { - if (this.actual.callCount === 0) { - // todo: what should the failure message for .not.toHaveBeenCalledWith() be? is this right? test better. [xw] - return [ - "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.", - "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but it was." - ]; - } else { - return [ - "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall), - "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall) - ]; - } - }; - - return this.env.contains_(this.actual.argsForCall, expectedArgs); -}; - -/** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */ -jasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.prototype.toHaveBeenCalledWith; - -/** @deprecated Use expect(xxx).not.toHaveBeenCalledWith() instead */ -jasmine.Matchers.prototype.wasNotCalledWith = function() { - var expectedArgs = jasmine.util.argsToArray(arguments); - if (!jasmine.isSpy(this.actual)) { - throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); - } - - this.message = function() { - return [ - "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was", - "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was" - ]; - }; - - return !this.env.contains_(this.actual.argsForCall, expectedArgs); -}; - -/** - * Matcher that checks that the expected item is an element in the actual Array. - * - * @param {Object} expected - */ -jasmine.Matchers.prototype.toContain = function(expected) { - return this.env.contains_(this.actual, expected); -}; - -/** - * Matcher that checks that the expected item is NOT an element in the actual Array. - * - * @param {Object} expected - * @deprecated as of 1.0. Use not.toNotContain() instead. - */ -jasmine.Matchers.prototype.toNotContain = function(expected) { - return !this.env.contains_(this.actual, expected); -}; - -jasmine.Matchers.prototype.toBeLessThan = function(expected) { - return this.actual < expected; -}; - -jasmine.Matchers.prototype.toBeGreaterThan = function(expected) { - return this.actual > expected; -}; - -/** - * Matcher that checks that the expected item is equal to the actual item - * up to a given level of decimal precision (default 2). - * - * @param {Number} expected - * @param {Number} precision - */ -jasmine.Matchers.prototype.toBeCloseTo = function(expected, precision) { - if (!(precision === 0)) { - precision = precision || 2; - } - var multiplier = Math.pow(10, precision); - var actual = Math.round(this.actual * multiplier); - expected = Math.round(expected * multiplier); - return expected == actual; -}; - -/** - * Matcher that checks that the expected exception was thrown by the actual. - * - * @param {String} expected - */ -jasmine.Matchers.prototype.toThrow = function(expected) { - var result = false; - var exception; - if (typeof this.actual != 'function') { - throw new Error('Actual is not a function'); - } - try { - this.actual(); - } catch (e) { - exception = e; - } - if (exception) { - result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected)); - } - - var not = this.isNot ? "not " : ""; - - this.message = function() { - if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) { - return ["Expected function " + not + "to throw", expected ? expected.message || expected : "an exception", ", but it threw", exception.message || exception].join(' '); - } else { - return "Expected function to throw an exception."; - } - }; - - return result; -}; - -jasmine.Matchers.Any = function(expectedClass) { - this.expectedClass = expectedClass; -}; - -jasmine.Matchers.Any.prototype.matches = function(other) { - if (this.expectedClass == String) { - return typeof other == 'string' || other instanceof String; - } - - if (this.expectedClass == Number) { - return typeof other == 'number' || other instanceof Number; - } - - if (this.expectedClass == Function) { - return typeof other == 'function' || other instanceof Function; - } - - if (this.expectedClass == Object) { - return typeof other == 'object'; - } - - return other instanceof this.expectedClass; -}; - -jasmine.Matchers.Any.prototype.toString = function() { - return ''; -}; - -/** - * @constructor - */ -jasmine.MultiReporter = function() { - this.subReporters_ = []; -}; -jasmine.util.inherit(jasmine.MultiReporter, jasmine.Reporter); - -jasmine.MultiReporter.prototype.addReporter = function(reporter) { - this.subReporters_.push(reporter); -}; - -(function() { - var functionNames = [ - "reportRunnerStarting", - "reportRunnerResults", - "reportSuiteResults", - "reportSpecStarting", - "reportSpecResults", - "log" - ]; - for (var i = 0; i < functionNames.length; i++) { - var functionName = functionNames[i]; - jasmine.MultiReporter.prototype[functionName] = (function(functionName) { - return function() { - for (var j = 0; j < this.subReporters_.length; j++) { - var subReporter = this.subReporters_[j]; - if (subReporter[functionName]) { - subReporter[functionName].apply(subReporter, arguments); - } - } - }; - })(functionName); - } -})(); -/** - * Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults - * - * @constructor - */ -jasmine.NestedResults = function() { - /** - * The total count of results - */ - this.totalCount = 0; - /** - * Number of passed results - */ - this.passedCount = 0; - /** - * Number of failed results - */ - this.failedCount = 0; - /** - * Was this suite/spec skipped? - */ - this.skipped = false; - /** - * @ignore - */ - this.items_ = []; -}; - -/** - * Roll up the result counts. - * - * @param result - */ -jasmine.NestedResults.prototype.rollupCounts = function(result) { - this.totalCount += result.totalCount; - this.passedCount += result.passedCount; - this.failedCount += result.failedCount; -}; - -/** - * Adds a log message. - * @param values Array of message parts which will be concatenated later. - */ -jasmine.NestedResults.prototype.log = function(values) { - this.items_.push(new jasmine.MessageResult(values)); -}; - -/** - * Getter for the results: message & results. - */ -jasmine.NestedResults.prototype.getItems = function() { - return this.items_; -}; - -/** - * Adds a result, tracking counts (total, passed, & failed) - * @param {jasmine.ExpectationResult|jasmine.NestedResults} result - */ -jasmine.NestedResults.prototype.addResult = function(result) { - if (result.type != 'log') { - if (result.items_) { - this.rollupCounts(result); - } else { - this.totalCount++; - if (result.passed()) { - this.passedCount++; - } else { - this.failedCount++; - } - } - } - this.items_.push(result); -}; - -/** - * @returns {Boolean} True if everything below passed - */ -jasmine.NestedResults.prototype.passed = function() { - return this.passedCount === this.totalCount; -}; -/** - * Base class for pretty printing for expectation results. - */ -jasmine.PrettyPrinter = function() { - this.ppNestLevel_ = 0; -}; - -/** - * Formats a value in a nice, human-readable string. - * - * @param value - */ -jasmine.PrettyPrinter.prototype.format = function(value) { - if (this.ppNestLevel_ > 40) { - throw new Error('jasmine.PrettyPrinter: format() nested too deeply!'); - } - - this.ppNestLevel_++; - try { - if (value === jasmine.undefined) { - this.emitScalar('undefined'); - } else if (value === null) { - this.emitScalar('null'); - } else if (value === jasmine.getGlobal()) { - this.emitScalar(''); - } else if (value instanceof jasmine.Matchers.Any) { - this.emitScalar(value.toString()); - } else if (typeof value === 'string') { - this.emitString(value); - } else if (jasmine.isSpy(value)) { - this.emitScalar("spy on " + value.identity); - } else if (value instanceof RegExp) { - this.emitScalar(value.toString()); - } else if (typeof value === 'function') { - this.emitScalar('Function'); - } else if (typeof value.nodeType === 'number') { - this.emitScalar('HTMLNode'); - } else if (value instanceof Date) { - this.emitScalar('Date(' + value + ')'); - } else if (value.__Jasmine_been_here_before__) { - this.emitScalar(''); - } else if (jasmine.isArray_(value) || typeof value == 'object') { - value.__Jasmine_been_here_before__ = true; - if (jasmine.isArray_(value)) { - this.emitArray(value); - } else { - this.emitObject(value); - } - delete value.__Jasmine_been_here_before__; - } else { - this.emitScalar(value.toString()); - } - } finally { - this.ppNestLevel_--; - } -}; - -jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) { - for (var property in obj) { - if (property == '__Jasmine_been_here_before__') continue; - fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) !== jasmine.undefined && - obj.__lookupGetter__(property) !== null) : false); - } -}; - -jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_; -jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_; -jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_; -jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_; - -jasmine.StringPrettyPrinter = function() { - jasmine.PrettyPrinter.call(this); - - this.string = ''; -}; -jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter); - -jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) { - this.append(value); -}; - -jasmine.StringPrettyPrinter.prototype.emitString = function(value) { - this.append("'" + value + "'"); -}; - -jasmine.StringPrettyPrinter.prototype.emitArray = function(array) { - this.append('[ '); - for (var i = 0; i < array.length; i++) { - if (i > 0) { - this.append(', '); - } - this.format(array[i]); - } - this.append(' ]'); -}; - -jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) { - var self = this; - this.append('{ '); - var first = true; - - this.iterateObject(obj, function(property, isGetter) { - if (first) { - first = false; - } else { - self.append(', '); - } - - self.append(property); - self.append(' : '); - if (isGetter) { - self.append(''); - } else { - self.format(obj[property]); - } - }); - - this.append(' }'); -}; - -jasmine.StringPrettyPrinter.prototype.append = function(value) { - this.string += value; -}; -jasmine.Queue = function(env) { - this.env = env; - this.blocks = []; - this.running = false; - this.index = 0; - this.offset = 0; - this.abort = false; -}; - -jasmine.Queue.prototype.addBefore = function(block) { - this.blocks.unshift(block); -}; - -jasmine.Queue.prototype.add = function(block) { - this.blocks.push(block); -}; - -jasmine.Queue.prototype.insertNext = function(block) { - this.blocks.splice((this.index + this.offset + 1), 0, block); - this.offset++; -}; - -jasmine.Queue.prototype.start = function(onComplete) { - this.running = true; - this.onComplete = onComplete; - this.next_(); -}; - -jasmine.Queue.prototype.isRunning = function() { - return this.running; -}; - -jasmine.Queue.LOOP_DONT_RECURSE = true; - -jasmine.Queue.prototype.next_ = function() { - var self = this; - var goAgain = true; - - while (goAgain) { - goAgain = false; - - if (self.index < self.blocks.length && !this.abort) { - var calledSynchronously = true; - var completedSynchronously = false; - - var onComplete = function () { - if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously) { - completedSynchronously = true; - return; - } - - if (self.blocks[self.index].abort) { - self.abort = true; - } - - self.offset = 0; - self.index++; - - var now = new Date().getTime(); - if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) { - self.env.lastUpdate = now; - self.env.setTimeout(function() { - self.next_(); - }, 0); - } else { - if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously) { - goAgain = true; - } else { - self.next_(); - } - } - }; - self.blocks[self.index].execute(onComplete); - - calledSynchronously = false; - if (completedSynchronously) { - onComplete(); - } - - } else { - self.running = false; - if (self.onComplete) { - self.onComplete(); - } - } - } -}; - -jasmine.Queue.prototype.results = function() { - var results = new jasmine.NestedResults(); - for (var i = 0; i < this.blocks.length; i++) { - if (this.blocks[i].results) { - results.addResult(this.blocks[i].results()); - } - } - return results; -}; - - -/** - * Runner - * - * @constructor - * @param {jasmine.Env} env - */ -jasmine.Runner = function(env) { - var self = this; - self.env = env; - self.queue = new jasmine.Queue(env); - self.before_ = []; - self.after_ = []; - self.suites_ = []; -}; - -jasmine.Runner.prototype.execute = function() { - var self = this; - if (self.env.reporter.reportRunnerStarting) { - self.env.reporter.reportRunnerStarting(this); - } - self.queue.start(function () { - self.finishCallback(); - }); -}; - -jasmine.Runner.prototype.beforeEach = function(beforeEachFunction) { - beforeEachFunction.typeName = 'beforeEach'; - this.before_.splice(0,0,beforeEachFunction); -}; - -jasmine.Runner.prototype.afterEach = function(afterEachFunction) { - afterEachFunction.typeName = 'afterEach'; - this.after_.splice(0,0,afterEachFunction); -}; - - -jasmine.Runner.prototype.finishCallback = function() { - this.env.reporter.reportRunnerResults(this); -}; - -jasmine.Runner.prototype.addSuite = function(suite) { - this.suites_.push(suite); -}; - -jasmine.Runner.prototype.add = function(block) { - if (block instanceof jasmine.Suite) { - this.addSuite(block); - } - this.queue.add(block); -}; - -jasmine.Runner.prototype.specs = function () { - var suites = this.suites(); - var specs = []; - for (var i = 0; i < suites.length; i++) { - specs = specs.concat(suites[i].specs()); - } - return specs; -}; - -jasmine.Runner.prototype.suites = function() { - return this.suites_; -}; - -jasmine.Runner.prototype.topLevelSuites = function() { - var topLevelSuites = []; - for (var i = 0; i < this.suites_.length; i++) { - if (!this.suites_[i].parentSuite) { - topLevelSuites.push(this.suites_[i]); - } - } - return topLevelSuites; -}; - -jasmine.Runner.prototype.results = function() { - return this.queue.results(); -}; -/** - * Internal representation of a Jasmine specification, or test. - * - * @constructor - * @param {jasmine.Env} env - * @param {jasmine.Suite} suite - * @param {String} description - */ -jasmine.Spec = function(env, suite, description) { - if (!env) { - throw new Error('jasmine.Env() required'); - } - if (!suite) { - throw new Error('jasmine.Suite() required'); - } - var spec = this; - spec.id = env.nextSpecId ? env.nextSpecId() : null; - spec.env = env; - spec.suite = suite; - spec.description = description; - spec.queue = new jasmine.Queue(env); - - spec.afterCallbacks = []; - spec.spies_ = []; - - spec.results_ = new jasmine.NestedResults(); - spec.results_.description = description; - spec.matchersClass = null; -}; - -jasmine.Spec.prototype.getFullName = function() { - return this.suite.getFullName() + ' ' + this.description + '.'; -}; - - -jasmine.Spec.prototype.results = function() { - return this.results_; -}; - -/** - * All parameters are pretty-printed and concatenated together, then written to the spec's output. - * - * Be careful not to leave calls to jasmine.log in production code. - */ -jasmine.Spec.prototype.log = function() { - return this.results_.log(arguments); -}; - -jasmine.Spec.prototype.runs = function (func) { - var block = new jasmine.Block(this.env, func, this); - this.addToQueue(block); - return this; -}; - -jasmine.Spec.prototype.addToQueue = function (block) { - if (this.queue.isRunning()) { - this.queue.insertNext(block); - } else { - this.queue.add(block); - } -}; - -/** - * @param {jasmine.ExpectationResult} result - */ -jasmine.Spec.prototype.addMatcherResult = function(result) { - this.results_.addResult(result); -}; - -jasmine.Spec.prototype.expect = function(actual) { - var positive = new (this.getMatchersClass_())(this.env, actual, this); - positive.not = new (this.getMatchersClass_())(this.env, actual, this, true); - return positive; -}; - -/** - * Waits a fixed time period before moving to the next block. - * - * @deprecated Use waitsFor() instead - * @param {Number} timeout milliseconds to wait - */ -jasmine.Spec.prototype.waits = function(timeout) { - var waitsFunc = new jasmine.WaitsBlock(this.env, timeout, this); - this.addToQueue(waitsFunc); - return this; -}; - -/** - * Waits for the latchFunction to return true before proceeding to the next block. - * - * @param {Function} latchFunction - * @param {String} optional_timeoutMessage - * @param {Number} optional_timeout - */ -jasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) { - var latchFunction_ = null; - var optional_timeoutMessage_ = null; - var optional_timeout_ = null; - - for (var i = 0; i < arguments.length; i++) { - var arg = arguments[i]; - switch (typeof arg) { - case 'function': - latchFunction_ = arg; - break; - case 'string': - optional_timeoutMessage_ = arg; - break; - case 'number': - optional_timeout_ = arg; - break; - } - } - - var waitsForFunc = new jasmine.WaitsForBlock(this.env, optional_timeout_, latchFunction_, optional_timeoutMessage_, this); - this.addToQueue(waitsForFunc); - return this; -}; - -jasmine.Spec.prototype.fail = function (e) { - var expectationResult = new jasmine.ExpectationResult({ - passed: false, - message: e ? jasmine.util.formatException(e) : 'Exception', - trace: { stack: e.stack } - }); - this.results_.addResult(expectationResult); -}; - -jasmine.Spec.prototype.getMatchersClass_ = function() { - return this.matchersClass || this.env.matchersClass; -}; - -jasmine.Spec.prototype.addMatchers = function(matchersPrototype) { - var parent = this.getMatchersClass_(); - var newMatchersClass = function() { - parent.apply(this, arguments); - }; - jasmine.util.inherit(newMatchersClass, parent); - jasmine.Matchers.wrapInto_(matchersPrototype, newMatchersClass); - this.matchersClass = newMatchersClass; -}; - -jasmine.Spec.prototype.finishCallback = function() { - this.env.reporter.reportSpecResults(this); -}; - -jasmine.Spec.prototype.finish = function(onComplete) { - this.removeAllSpies(); - this.finishCallback(); - if (onComplete) { - onComplete(); - } -}; - -jasmine.Spec.prototype.after = function(doAfter) { - if (this.queue.isRunning()) { - this.queue.add(new jasmine.Block(this.env, doAfter, this)); - } else { - this.afterCallbacks.unshift(doAfter); - } -}; - -jasmine.Spec.prototype.execute = function(onComplete) { - var spec = this; - if (!spec.env.specFilter(spec)) { - spec.results_.skipped = true; - spec.finish(onComplete); - return; - } - - this.env.reporter.reportSpecStarting(this); - - spec.env.currentSpec = spec; - - spec.addBeforesAndAftersToQueue(); - - spec.queue.start(function () { - spec.finish(onComplete); - }); -}; - -jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() { - var runner = this.env.currentRunner(); - var i; - - for (var suite = this.suite; suite; suite = suite.parentSuite) { - for (i = 0; i < suite.before_.length; i++) { - this.queue.addBefore(new jasmine.Block(this.env, suite.before_[i], this)); - } - } - for (i = 0; i < runner.before_.length; i++) { - this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this)); - } - for (i = 0; i < this.afterCallbacks.length; i++) { - this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this)); - } - for (suite = this.suite; suite; suite = suite.parentSuite) { - for (i = 0; i < suite.after_.length; i++) { - this.queue.add(new jasmine.Block(this.env, suite.after_[i], this)); - } - } - for (i = 0; i < runner.after_.length; i++) { - this.queue.add(new jasmine.Block(this.env, runner.after_[i], this)); - } -}; - -jasmine.Spec.prototype.explodes = function() { - throw 'explodes function should not have been called'; -}; - -jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) { - if (obj == jasmine.undefined) { - throw "spyOn could not find an object to spy upon for " + methodName + "()"; - } - - if (!ignoreMethodDoesntExist && obj[methodName] === jasmine.undefined) { - throw methodName + '() method does not exist'; - } - - if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) { - throw new Error(methodName + ' has already been spied upon'); - } - - var spyObj = jasmine.createSpy(methodName); - - this.spies_.push(spyObj); - spyObj.baseObj = obj; - spyObj.methodName = methodName; - spyObj.originalValue = obj[methodName]; - - obj[methodName] = spyObj; - - return spyObj; -}; - -jasmine.Spec.prototype.removeAllSpies = function() { - for (var i = 0; i < this.spies_.length; i++) { - var spy = this.spies_[i]; - spy.baseObj[spy.methodName] = spy.originalValue; - } - this.spies_ = []; -}; - -/** - * Internal representation of a Jasmine suite. - * - * @constructor - * @param {jasmine.Env} env - * @param {String} description - * @param {Function} specDefinitions - * @param {jasmine.Suite} parentSuite - */ -jasmine.Suite = function(env, description, specDefinitions, parentSuite) { - var self = this; - self.id = env.nextSuiteId ? env.nextSuiteId() : null; - self.description = description; - self.queue = new jasmine.Queue(env); - self.parentSuite = parentSuite; - self.env = env; - self.before_ = []; - self.after_ = []; - self.children_ = []; - self.suites_ = []; - self.specs_ = []; -}; - -jasmine.Suite.prototype.getFullName = function() { - var fullName = this.description; - for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) { - fullName = parentSuite.description + ' ' + fullName; - } - return fullName; -}; - -jasmine.Suite.prototype.finish = function(onComplete) { - this.env.reporter.reportSuiteResults(this); - this.finished = true; - if (typeof(onComplete) == 'function') { - onComplete(); - } -}; - -jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) { - beforeEachFunction.typeName = 'beforeEach'; - this.before_.unshift(beforeEachFunction); -}; - -jasmine.Suite.prototype.afterEach = function(afterEachFunction) { - afterEachFunction.typeName = 'afterEach'; - this.after_.unshift(afterEachFunction); -}; - -jasmine.Suite.prototype.results = function() { - return this.queue.results(); -}; - -jasmine.Suite.prototype.add = function(suiteOrSpec) { - this.children_.push(suiteOrSpec); - if (suiteOrSpec instanceof jasmine.Suite) { - this.suites_.push(suiteOrSpec); - this.env.currentRunner().addSuite(suiteOrSpec); - } else { - this.specs_.push(suiteOrSpec); - } - this.queue.add(suiteOrSpec); -}; - -jasmine.Suite.prototype.specs = function() { - return this.specs_; -}; - -jasmine.Suite.prototype.suites = function() { - return this.suites_; -}; - -jasmine.Suite.prototype.children = function() { - return this.children_; -}; - -jasmine.Suite.prototype.execute = function(onComplete) { - var self = this; - this.queue.start(function () { - self.finish(onComplete); - }); -}; -jasmine.WaitsBlock = function(env, timeout, spec) { - this.timeout = timeout; - jasmine.Block.call(this, env, null, spec); -}; - -jasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block); - -jasmine.WaitsBlock.prototype.execute = function (onComplete) { - if (jasmine.VERBOSE) { - this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...'); - } - this.env.setTimeout(function () { - onComplete(); - }, this.timeout); -}; -/** - * A block which waits for some condition to become true, with timeout. - * - * @constructor - * @extends jasmine.Block - * @param {jasmine.Env} env The Jasmine environment. - * @param {Number} timeout The maximum time in milliseconds to wait for the condition to become true. - * @param {Function} latchFunction A function which returns true when the desired condition has been met. - * @param {String} message The message to display if the desired condition hasn't been met within the given time period. - * @param {jasmine.Spec} spec The Jasmine spec. - */ -jasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) { - this.timeout = timeout || env.defaultTimeoutInterval; - this.latchFunction = latchFunction; - this.message = message; - this.totalTimeSpentWaitingForLatch = 0; - jasmine.Block.call(this, env, null, spec); -}; -jasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block); - -jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 10; - -jasmine.WaitsForBlock.prototype.execute = function(onComplete) { - if (jasmine.VERBOSE) { - this.env.reporter.log('>> Jasmine waiting for ' + (this.message || 'something to happen')); - } - var latchFunctionResult; - try { - latchFunctionResult = this.latchFunction.apply(this.spec); - } catch (e) { - this.spec.fail(e); - onComplete(); - return; - } - - if (latchFunctionResult) { - onComplete(); - } else if (this.totalTimeSpentWaitingForLatch >= this.timeout) { - var message = 'timed out after ' + this.timeout + ' msec waiting for ' + (this.message || 'something to happen'); - this.spec.fail({ - name: 'timeout', - message: message - }); - - this.abort = true; - onComplete(); - } else { - this.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT; - var self = this; - this.env.setTimeout(function() { - self.execute(onComplete); - }, jasmine.WaitsForBlock.TIMEOUT_INCREMENT); - } -}; -// Mock setTimeout, clearTimeout -// Contributed by Pivotal Computer Systems, www.pivotalsf.com - -jasmine.FakeTimer = function() { - this.reset(); - - var self = this; - self.setTimeout = function(funcToCall, millis) { - self.timeoutsMade++; - self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false); - return self.timeoutsMade; - }; - - self.setInterval = function(funcToCall, millis) { - self.timeoutsMade++; - self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true); - return self.timeoutsMade; - }; - - self.clearTimeout = function(timeoutKey) { - self.scheduledFunctions[timeoutKey] = jasmine.undefined; - }; - - self.clearInterval = function(timeoutKey) { - self.scheduledFunctions[timeoutKey] = jasmine.undefined; - }; - -}; - -jasmine.FakeTimer.prototype.reset = function() { - this.timeoutsMade = 0; - this.scheduledFunctions = {}; - this.nowMillis = 0; -}; - -jasmine.FakeTimer.prototype.tick = function(millis) { - var oldMillis = this.nowMillis; - var newMillis = oldMillis + millis; - this.runFunctionsWithinRange(oldMillis, newMillis); - this.nowMillis = newMillis; -}; - -jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) { - var scheduledFunc; - var funcsToRun = []; - for (var timeoutKey in this.scheduledFunctions) { - scheduledFunc = this.scheduledFunctions[timeoutKey]; - if (scheduledFunc != jasmine.undefined && - scheduledFunc.runAtMillis >= oldMillis && - scheduledFunc.runAtMillis <= nowMillis) { - funcsToRun.push(scheduledFunc); - this.scheduledFunctions[timeoutKey] = jasmine.undefined; - } - } - - if (funcsToRun.length > 0) { - funcsToRun.sort(function(a, b) { - return a.runAtMillis - b.runAtMillis; - }); - for (var i = 0; i < funcsToRun.length; ++i) { - try { - var funcToRun = funcsToRun[i]; - this.nowMillis = funcToRun.runAtMillis; - funcToRun.funcToCall(); - if (funcToRun.recurring) { - this.scheduleFunction(funcToRun.timeoutKey, - funcToRun.funcToCall, - funcToRun.millis, - true); - } - } catch(e) { - } - } - this.runFunctionsWithinRange(oldMillis, nowMillis); - } -}; - -jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) { - this.scheduledFunctions[timeoutKey] = { - runAtMillis: this.nowMillis + millis, - funcToCall: funcToCall, - recurring: recurring, - timeoutKey: timeoutKey, - millis: millis - }; -}; - -/** - * @namespace - */ -jasmine.Clock = { - defaultFakeTimer: new jasmine.FakeTimer(), - - reset: function() { - jasmine.Clock.assertInstalled(); - jasmine.Clock.defaultFakeTimer.reset(); - }, - - tick: function(millis) { - jasmine.Clock.assertInstalled(); - jasmine.Clock.defaultFakeTimer.tick(millis); - }, - - runFunctionsWithinRange: function(oldMillis, nowMillis) { - jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis); - }, - - scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) { - jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring); - }, - - useMock: function() { - if (!jasmine.Clock.isInstalled()) { - var spec = jasmine.getEnv().currentSpec; - spec.after(jasmine.Clock.uninstallMock); - - jasmine.Clock.installMock(); - } - }, - - installMock: function() { - jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer; - }, - - uninstallMock: function() { - jasmine.Clock.assertInstalled(); - jasmine.Clock.installed = jasmine.Clock.real; - }, - - real: { - setTimeout: jasmine.getGlobal().setTimeout, - clearTimeout: jasmine.getGlobal().clearTimeout, - setInterval: jasmine.getGlobal().setInterval, - clearInterval: jasmine.getGlobal().clearInterval - }, - - assertInstalled: function() { - if (!jasmine.Clock.isInstalled()) { - throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()"); - } - }, - - isInstalled: function() { - return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer; - }, - - installed: null -}; -jasmine.Clock.installed = jasmine.Clock.real; - -//else for IE support -jasmine.getGlobal().setTimeout = function(funcToCall, millis) { - if (jasmine.Clock.installed.setTimeout.apply) { - return jasmine.Clock.installed.setTimeout.apply(this, arguments); - } else { - return jasmine.Clock.installed.setTimeout(funcToCall, millis); - } -}; - -jasmine.getGlobal().setInterval = function(funcToCall, millis) { - if (jasmine.Clock.installed.setInterval.apply) { - return jasmine.Clock.installed.setInterval.apply(this, arguments); - } else { - return jasmine.Clock.installed.setInterval(funcToCall, millis); - } -}; - -jasmine.getGlobal().clearTimeout = function(timeoutKey) { - if (jasmine.Clock.installed.clearTimeout.apply) { - return jasmine.Clock.installed.clearTimeout.apply(this, arguments); - } else { - return jasmine.Clock.installed.clearTimeout(timeoutKey); - } -}; - -jasmine.getGlobal().clearInterval = function(timeoutKey) { - if (jasmine.Clock.installed.clearTimeout.apply) { - return jasmine.Clock.installed.clearInterval.apply(this, arguments); - } else { - return jasmine.Clock.installed.clearInterval(timeoutKey); - } -}; - -jasmine.version_= { - "major": 1, - "minor": 1, - "build": 0, - "revision": 1315677058 -}; diff --git a/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine_favicon.png b/node_modules/mongodb/node_modules/bson/tools/jasmine-1.1.0/jasmine_favicon.png deleted file mode 100644 index 218f3b43713598fa5a3e78b57aceb909c33f46df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 905 zcmV;419tq0P)Px#AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_0008u zNkl3{fod28|PjmA)7fYg4w8-(2my9xtBGOs}K`n&t1VzxMO^X)M zrW+Ln1udc?q6TP)z5gAjt)P&D!M$+HJK#x<`xnD030zwD?KrxxY!2tlA zGc-58?0D7SsT)7Km=v+tNVNUk`?s@;^OxCF)y6P}_mL;~7;S<@b|MzmKq)m8l@yky zT1~ECpxZw@64!nkI34QLiUsA%i%N>-$&zGYR7WJyi9ERMyS(%kf z7A_r)X>!90&m(FwDQZ>q;+nOa*KR2+E6Fz)QwU=W1Oyo*4>_qlm|~joa|{4_A_3W8 z#FFZzRp-xMIx5a7D_Fj3&#r^TbIY@cND1d0f*^qDIs{!pw!IWGQ_%l4#ASm_D5Vet z0%ek7^)@xPihX_G0&hIc9*14ca=D!8oG}vW?H%~w^F?f_s>zU|fKrNJXJ_d6{v!t( zpEoqMws_yQws>3o?VW8Txq~#->dJG^ELW5irR!s`(_JvD^6;r+ho~eIK@ia8_lH(h zt*-p?CFC1_h2MV=?jP){uW!7WjLjCaO&c1D+tf582!XEaoB#xWAYcN5f$sLtf$koW zQs{{>)ZTq?FC6|J_%n}AWbiFK(Bo-%^-{H`*)E(ucjo-r%SYm)W5f6tN=xz=S646E fNXW#U{x?4WXWJ> $(depfile) -# Add extra rules as in (2). -# We remove slashes and replace spaces with new lines; -# remove blank lines; -# delete the first line and append a colon to the remaining lines. -sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\ - grep -v '^$$' |\ - sed -e 1d -e 's|$$|:|' \ - >> $(depfile) -rm $(depfile).raw -endef - -# Command definitions: -# - cmd_foo is the actual command to run; -# - quiet_cmd_foo is the brief-output summary of the command. - -quiet_cmd_cc = CC($(TOOLSET)) $@ -cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $< - -quiet_cmd_cxx = CXX($(TOOLSET)) $@ -cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< - -quiet_cmd_objc = CXX($(TOOLSET)) $@ -cmd_objc = $(CC.$(TOOLSET)) $(GYP_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $< - -quiet_cmd_objcxx = CXX($(TOOLSET)) $@ -cmd_objcxx = $(CXX.$(TOOLSET)) $(GYP_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $< - -# Commands for precompiled header files. -quiet_cmd_pch_c = CXX($(TOOLSET)) $@ -cmd_pch_c = $(CC.$(TOOLSET)) $(GYP_PCH_CFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< -quiet_cmd_pch_cc = CXX($(TOOLSET)) $@ -cmd_pch_cc = $(CC.$(TOOLSET)) $(GYP_PCH_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< -quiet_cmd_pch_m = CXX($(TOOLSET)) $@ -cmd_pch_m = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $< -quiet_cmd_pch_mm = CXX($(TOOLSET)) $@ -cmd_pch_mm = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $< - -# gyp-mac-tool is written next to the root Makefile by gyp. -# Use $(4) for the command, since $(2) and $(3) are used as flag by do_cmd -# already. -quiet_cmd_mac_tool = MACTOOL $(4) $< -cmd_mac_tool = ./gyp-mac-tool $(4) $< "$@" - -quiet_cmd_mac_package_framework = PACKAGE FRAMEWORK $@ -cmd_mac_package_framework = ./gyp-mac-tool package-framework "$@" $(4) - -quiet_cmd_infoplist = INFOPLIST $@ -cmd_infoplist = $(CC.$(TOOLSET)) -E -P -Wno-trigraphs -x c $(INFOPLIST_DEFINES) "$<" -o "$@" - -quiet_cmd_touch = TOUCH $@ -cmd_touch = touch $@ - -quiet_cmd_copy = COPY $@ -# send stderr to /dev/null to ignore messages when linking directories. -cmd_copy = rm -rf "$@" && cp -af "$<" "$@" - -quiet_cmd_alink = LIBTOOL-STATIC $@ -cmd_alink = rm -f $@ && ./gyp-mac-tool filter-libtool libtool $(GYP_LIBTOOLFLAGS) -static -o $@ $(filter %.o,$^) - -quiet_cmd_link = LINK($(TOOLSET)) $@ -cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS) - -quiet_cmd_solink = SOLINK($(TOOLSET)) $@ -cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS) - -quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@ -cmd_solink_module = $(LINK.$(TOOLSET)) -bundle $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS) - - -# Define an escape_quotes function to escape single quotes. -# This allows us to handle quotes properly as long as we always use -# use single quotes and escape_quotes. -escape_quotes = $(subst ','\'',$(1)) -# This comment is here just to include a ' to unconfuse syntax highlighting. -# Define an escape_vars function to escape '$' variable syntax. -# This allows us to read/write command lines with shell variables (e.g. -# $LD_LIBRARY_PATH), without triggering make substitution. -escape_vars = $(subst $$,$$$$,$(1)) -# Helper that expands to a shell command to echo a string exactly as it is in -# make. This uses printf instead of echo because printf's behaviour with respect -# to escape sequences is more portable than echo's across different shells -# (e.g., dash, bash). -exact_echo = printf '%s\n' '$(call escape_quotes,$(1))' - -# Helper to compare the command we're about to run against the command -# we logged the last time we ran the command. Produces an empty -# string (false) when the commands match. -# Tricky point: Make has no string-equality test function. -# The kernel uses the following, but it seems like it would have false -# positives, where one string reordered its arguments. -# arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \ -# $(filter-out $(cmd_$@), $(cmd_$(1)))) -# We instead substitute each for the empty string into the other, and -# say they're equal if both substitutions produce the empty string. -# .d files contain ? instead of spaces, take that into account. -command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\ - $(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1)))) - -# Helper that is non-empty when a prerequisite changes. -# Normally make does this implicitly, but we force rules to always run -# so we can check their command lines. -# $? -- new prerequisites -# $| -- order-only dependencies -prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?)) - -# Helper that executes all postbuilds until one fails. -define do_postbuilds - @E=0;\ - for p in $(POSTBUILDS); do\ - eval $$p;\ - E=$$?;\ - if [ $$E -ne 0 ]; then\ - break;\ - fi;\ - done;\ - if [ $$E -ne 0 ]; then\ - rm -rf "$@";\ - exit $$E;\ - fi -endef - -# do_cmd: run a command via the above cmd_foo names, if necessary. -# Should always run for a given target to handle command-line changes. -# Second argument, if non-zero, makes it do asm/C/C++ dependency munging. -# Third argument, if non-zero, makes it do POSTBUILDS processing. -# Note: We intentionally do NOT call dirx for depfile, since it contains ? for -# spaces already and dirx strips the ? characters. -define do_cmd -$(if $(or $(command_changed),$(prereq_changed)), - @$(call exact_echo, $($(quiet)cmd_$(1))) - @mkdir -p "$(call dirx,$@)" "$(dir $(depfile))" - $(if $(findstring flock,$(word 2,$(cmd_$1))), - @$(cmd_$(1)) - @echo " $(quiet_cmd_$(1)): Finished", - @$(cmd_$(1)) - ) - @$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile) - @$(if $(2),$(fixup_dep)) - $(if $(and $(3), $(POSTBUILDS)), - $(call do_postbuilds) - ) -) -endef - -# Declare the "all" target first so it is the default, -# even though we don't have the deps yet. -.PHONY: all -all: - -# make looks for ways to re-generate included makefiles, but in our case, we -# don't have a direct way. Explicitly telling make that it has nothing to do -# for them makes it go faster. -%.d: ; - -# Use FORCE_DO_CMD to force a target to run. Should be coupled with -# do_cmd. -.PHONY: FORCE_DO_CMD -FORCE_DO_CMD: - -TOOLSET := target -# Suffix rules, putting all outputs into $(obj). -$(obj).$(TOOLSET)/%.o: $(srcdir)/%.c FORCE_DO_CMD - @$(call do_cmd,cc,1) -$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD - @$(call do_cmd,cxx,1) -$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD - @$(call do_cmd,cxx,1) -$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cxx FORCE_DO_CMD - @$(call do_cmd,cxx,1) -$(obj).$(TOOLSET)/%.o: $(srcdir)/%.m FORCE_DO_CMD - @$(call do_cmd,objc,1) -$(obj).$(TOOLSET)/%.o: $(srcdir)/%.mm FORCE_DO_CMD - @$(call do_cmd,objcxx,1) -$(obj).$(TOOLSET)/%.o: $(srcdir)/%.S FORCE_DO_CMD - @$(call do_cmd,cc,1) -$(obj).$(TOOLSET)/%.o: $(srcdir)/%.s FORCE_DO_CMD - @$(call do_cmd,cc,1) - -# Try building from generated source, too. -$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD - @$(call do_cmd,cc,1) -$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD - @$(call do_cmd,cxx,1) -$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD - @$(call do_cmd,cxx,1) -$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cxx FORCE_DO_CMD - @$(call do_cmd,cxx,1) -$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.m FORCE_DO_CMD - @$(call do_cmd,objc,1) -$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.mm FORCE_DO_CMD - @$(call do_cmd,objcxx,1) -$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.S FORCE_DO_CMD - @$(call do_cmd,cc,1) -$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.s FORCE_DO_CMD - @$(call do_cmd,cc,1) - -$(obj).$(TOOLSET)/%.o: $(obj)/%.c FORCE_DO_CMD - @$(call do_cmd,cc,1) -$(obj).$(TOOLSET)/%.o: $(obj)/%.cc FORCE_DO_CMD - @$(call do_cmd,cxx,1) -$(obj).$(TOOLSET)/%.o: $(obj)/%.cpp FORCE_DO_CMD - @$(call do_cmd,cxx,1) -$(obj).$(TOOLSET)/%.o: $(obj)/%.cxx FORCE_DO_CMD - @$(call do_cmd,cxx,1) -$(obj).$(TOOLSET)/%.o: $(obj)/%.m FORCE_DO_CMD - @$(call do_cmd,objc,1) -$(obj).$(TOOLSET)/%.o: $(obj)/%.mm FORCE_DO_CMD - @$(call do_cmd,objcxx,1) -$(obj).$(TOOLSET)/%.o: $(obj)/%.S FORCE_DO_CMD - @$(call do_cmd,cc,1) -$(obj).$(TOOLSET)/%.o: $(obj)/%.s FORCE_DO_CMD - @$(call do_cmd,cc,1) - - -ifeq ($(strip $(foreach prefix,$(NO_LOAD),\ - $(findstring $(join ^,$(prefix)),\ - $(join ^,kerberos.target.mk)))),) - include kerberos.target.mk -endif - -quiet_cmd_regen_makefile = ACTION Regenerating $@ -cmd_regen_makefile = cd $(srcdir); /usr/local/lib/node_modules/npm/node_modules/node-gyp/gyp/gyp_main.py -fmake --ignore-environment "--toplevel-dir=." -I/Users/voxfeed_1/code/offhours/argon/node_modules/mongodb/node_modules/kerberos/build/config.gypi -I/usr/local/lib/node_modules/npm/node_modules/node-gyp/addon.gypi -I/Users/voxfeed_1/.node-gyp/0.10.31/common.gypi "--depth=." "-Goutput_dir=." "--generator-output=build" "-Dlibrary=shared_library" "-Dvisibility=default" "-Dnode_root_dir=/Users/voxfeed_1/.node-gyp/0.10.31" "-Dmodule_root_dir=/Users/voxfeed_1/code/offhours/argon/node_modules/mongodb/node_modules/kerberos" binding.gyp -Makefile: $(srcdir)/../../../../../../../../../usr/local/lib/node_modules/npm/node_modules/node-gyp/addon.gypi $(srcdir)/build/config.gypi $(srcdir)/binding.gyp $(srcdir)/../../../../../../../.node-gyp/0.10.31/common.gypi - $(call do_cmd,regen_makefile) - -# "all" is a concatenation of the "all" targets from all the included -# sub-makefiles. This is just here to clarify. -all: - -# Add in dependency-tracking rules. $(all_deps) is the list of every single -# target in our tree. Only consider the ones with .d (dependency) info: -d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d)) -ifneq ($(d_files),) - include $(d_files) -endif diff --git a/node_modules/mongodb/node_modules/kerberos/build/Release/.deps/Release/obj.target/kerberos/lib/kerberos.o.d.raw b/node_modules/mongodb/node_modules/kerberos/build/Release/.deps/Release/obj.target/kerberos/lib/kerberos.o.d.raw deleted file mode 100644 index 5cff6ce..0000000 --- a/node_modules/mongodb/node_modules/kerberos/build/Release/.deps/Release/obj.target/kerberos/lib/kerberos.o.d.raw +++ /dev/null @@ -1,15 +0,0 @@ -Release/obj.target/kerberos/lib/kerberos.o: ../lib/kerberos.cc \ - ../lib/kerberos.h /Users/voxfeed_1/.node-gyp/0.10.31/src/node.h \ - /Users/voxfeed_1/.node-gyp/0.10.31/deps/uv/include/uv.h \ - /Users/voxfeed_1/.node-gyp/0.10.31/deps/uv/include/uv-private/uv-unix.h \ - /Users/voxfeed_1/.node-gyp/0.10.31/deps/uv/include/uv-private/ngx-queue.h \ - /Users/voxfeed_1/.node-gyp/0.10.31/deps/uv/include/uv-private/uv-darwin.h \ - /Users/voxfeed_1/.node-gyp/0.10.31/deps/v8/include/v8.h \ - /Users/voxfeed_1/.node-gyp/0.10.31/deps/v8/include/v8stdint.h \ - /Users/voxfeed_1/.node-gyp/0.10.31/src/node_object_wrap.h \ - ../node_modules/nan/nan.h \ - /Users/voxfeed_1/.node-gyp/0.10.31/src/node_buffer.h \ - /Users/voxfeed_1/.node-gyp/0.10.31/src/node_version.h \ - /Users/voxfeed_1/.node-gyp/0.10.31/src/util.h \ - /Users/voxfeed_1/.node-gyp/0.10.31/src/string_bytes.h \ - ../lib/kerberosgss.h ../lib/worker.h ../lib/kerberos_context.h diff --git a/node_modules/mongodb/node_modules/kerberos/build/binding.Makefile b/node_modules/mongodb/node_modules/kerberos/build/binding.Makefile deleted file mode 100644 index 69e964f..0000000 --- a/node_modules/mongodb/node_modules/kerberos/build/binding.Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# This file is generated by gyp; do not edit. - -export builddir_name ?= ./build/. -.PHONY: all -all: - $(MAKE) kerberos diff --git a/node_modules/mongodb/node_modules/kerberos/build/config.gypi b/node_modules/mongodb/node_modules/kerberos/build/config.gypi deleted file mode 100644 index e804b11..0000000 --- a/node_modules/mongodb/node_modules/kerberos/build/config.gypi +++ /dev/null @@ -1,119 +0,0 @@ -# Do not edit. File was generated by node-gyp's "configure" step -{ - "target_defaults": { - "cflags": [], - "default_configuration": "Release", - "defines": [], - "include_dirs": [], - "libraries": [] - }, - "variables": { - "clang": 1, - "host_arch": "x64", - "node_install_npm": "false", - "node_prefix": "/usr/local/Cellar/node/0.10.31", - "node_shared_cares": "false", - "node_shared_http_parser": "false", - "node_shared_libuv": "false", - "node_shared_openssl": "false", - "node_shared_v8": "false", - "node_shared_zlib": "false", - "node_tag": "", - "node_unsafe_optimizations": 0, - "node_use_dtrace": "true", - "node_use_etw": "false", - "node_use_openssl": "true", - "node_use_perfctr": "false", - "python": "/usr/local/opt/python/bin/python2.7", - "target_arch": "x64", - "v8_enable_gdbjit": 0, - "v8_no_strict_aliasing": 1, - "v8_use_snapshot": "true", - "want_separate_host_toolset": 0, - "nodedir": "/Users/voxfeed_1/.node-gyp/0.10.31", - "copy_dev_lib": "true", - "standalone_static_library": 1, - "save_dev": "", - "browser": "", - "viewer": "man", - "rollback": "true", - "usage": "", - "globalignorefile": "/usr/local/etc/npmignore", - "init_author_url": "", - "shell": "/bin/bash", - "parseable": "", - "shrinkwrap": "true", - "email": "contacto@voxfeed.com", - "init_license": "ISC", - "init_author_email": "contacto@voxfeed.com", - "cache_max": "Infinity", - "sign_git_tag": "", - "cert": "", - "git_tag_version": "true", - "local_address": "", - "long": "", - "registry": "https://registry.npmjs.org/", - "fetch_retries": "2", - "npat": "", - "key": "", - "message": "%s", - "versions": "", - "globalconfig": "/usr/local/etc/npmrc", - "always_auth": "", - "spin": "true", - "cache_lock_retries": "10", - "cafile": "", - "heading": "npm", - "fetch_retry_mintimeout": "10000", - "proprietary_attribs": "true", - "json": "", - "description": "true", - "engine_strict": "", - "https_proxy": "", - "init_module": "/Users/voxfeed_1/.npm-init.js", - "userconfig": "/Users/voxfeed_1/.npmrc", - "node_version": "0.10.31", - "user": "", - "save": "true", - "editor": "vi", - "tag": "latest", - "global": "", - "username": "voxfeed", - "optional": "true", - "bin_links": "true", - "force": "", - "searchopts": "", - "depth": "Infinity", - "rebuild_bundle": "true", - "searchsort": "name", - "unicode": "true", - "fetch_retry_maxtimeout": "60000", - "ca": "", - "save_prefix": "^", - "strict_ssl": "true", - "dev": "", - "fetch_retry_factor": "10", - "group": "20", - "save_exact": "", - "cache_lock_stale": "60000", - "version": "", - "cache_min": "10", - "cache": "/Users/voxfeed_1/.npm", - "searchexclude": "", - "color": "true", - "save_optional": "", - "user_agent": "npm/1.4.27 node/v0.10.31 darwin x64", - "ignore_scripts": "", - "cache_lock_wait": "10000", - "production": "", - "save_bundle": "", - "umask": "18", - "init_author_name": "VoxFeed", - "git": "git", - "onload_script": "", - "tmp": "/var/folders/8l/gc9d_yxd60b5nf5vxn5_rjfm0000gp/T", - "unsafe_perm": "true", - "link": "", - "prefix": "/usr/local" - } -} diff --git a/node_modules/mongodb/node_modules/kerberos/build/gyp-mac-tool b/node_modules/mongodb/node_modules/kerberos/build/gyp-mac-tool deleted file mode 100755 index 7abfed5..0000000 --- a/node_modules/mongodb/node_modules/kerberos/build/gyp-mac-tool +++ /dev/null @@ -1,512 +0,0 @@ -#!/usr/bin/env python -# Generated by gyp. Do not edit. -# Copyright (c) 2012 Google Inc. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Utility functions to perform Xcode-style build steps. - -These functions are executed via gyp-mac-tool when using the Makefile generator. -""" - -import fcntl -import fnmatch -import glob -import json -import os -import plistlib -import re -import shutil -import string -import subprocess -import sys -import tempfile - - -def main(args): - executor = MacTool() - exit_code = executor.Dispatch(args) - if exit_code is not None: - sys.exit(exit_code) - - -class MacTool(object): - """This class performs all the Mac tooling steps. The methods can either be - executed directly, or dispatched from an argument list.""" - - def Dispatch(self, args): - """Dispatches a string command to a method.""" - if len(args) < 1: - raise Exception("Not enough arguments") - - method = "Exec%s" % self._CommandifyName(args[0]) - return getattr(self, method)(*args[1:]) - - def _CommandifyName(self, name_string): - """Transforms a tool name like copy-info-plist to CopyInfoPlist""" - return name_string.title().replace('-', '') - - def ExecCopyBundleResource(self, source, dest): - """Copies a resource file to the bundle/Resources directory, performing any - necessary compilation on each resource.""" - extension = os.path.splitext(source)[1].lower() - if os.path.isdir(source): - # Copy tree. - # TODO(thakis): This copies file attributes like mtime, while the - # single-file branch below doesn't. This should probably be changed to - # be consistent with the single-file branch. - if os.path.exists(dest): - shutil.rmtree(dest) - shutil.copytree(source, dest) - elif extension == '.xib': - return self._CopyXIBFile(source, dest) - elif extension == '.storyboard': - return self._CopyXIBFile(source, dest) - elif extension == '.strings': - self._CopyStringsFile(source, dest) - else: - shutil.copy(source, dest) - - def _CopyXIBFile(self, source, dest): - """Compiles a XIB file with ibtool into a binary plist in the bundle.""" - - # ibtool sometimes crashes with relative paths. See crbug.com/314728. - base = os.path.dirname(os.path.realpath(__file__)) - if os.path.relpath(source): - source = os.path.join(base, source) - if os.path.relpath(dest): - dest = os.path.join(base, dest) - - args = ['xcrun', 'ibtool', '--errors', '--warnings', '--notices', - '--output-format', 'human-readable-text', '--compile', dest, source] - ibtool_section_re = re.compile(r'/\*.*\*/') - ibtool_re = re.compile(r'.*note:.*is clipping its content') - ibtoolout = subprocess.Popen(args, stdout=subprocess.PIPE) - current_section_header = None - for line in ibtoolout.stdout: - if ibtool_section_re.match(line): - current_section_header = line - elif not ibtool_re.match(line): - if current_section_header: - sys.stdout.write(current_section_header) - current_section_header = None - sys.stdout.write(line) - return ibtoolout.returncode - - def _CopyStringsFile(self, source, dest): - """Copies a .strings file using iconv to reconvert the input into UTF-16.""" - input_code = self._DetectInputEncoding(source) or "UTF-8" - - # Xcode's CpyCopyStringsFile / builtin-copyStrings seems to call - # CFPropertyListCreateFromXMLData() behind the scenes; at least it prints - # CFPropertyListCreateFromXMLData(): Old-style plist parser: missing - # semicolon in dictionary. - # on invalid files. Do the same kind of validation. - import CoreFoundation - s = open(source, 'rb').read() - d = CoreFoundation.CFDataCreate(None, s, len(s)) - _, error = CoreFoundation.CFPropertyListCreateFromXMLData(None, d, 0, None) - if error: - return - - fp = open(dest, 'wb') - fp.write(s.decode(input_code).encode('UTF-16')) - fp.close() - - def _DetectInputEncoding(self, file_name): - """Reads the first few bytes from file_name and tries to guess the text - encoding. Returns None as a guess if it can't detect it.""" - fp = open(file_name, 'rb') - try: - header = fp.read(3) - except e: - fp.close() - return None - fp.close() - if header.startswith("\xFE\xFF"): - return "UTF-16" - elif header.startswith("\xFF\xFE"): - return "UTF-16" - elif header.startswith("\xEF\xBB\xBF"): - return "UTF-8" - else: - return None - - def ExecCopyInfoPlist(self, source, dest, *keys): - """Copies the |source| Info.plist to the destination directory |dest|.""" - # Read the source Info.plist into memory. - fd = open(source, 'r') - lines = fd.read() - fd.close() - - # Insert synthesized key/value pairs (e.g. BuildMachineOSBuild). - plist = plistlib.readPlistFromString(lines) - if keys: - plist = dict(plist.items() + json.loads(keys[0]).items()) - lines = plistlib.writePlistToString(plist) - - # Go through all the environment variables and replace them as variables in - # the file. - IDENT_RE = re.compile('[/\s]') - for key in os.environ: - if key.startswith('_'): - continue - evar = '${%s}' % key - evalue = os.environ[key] - lines = string.replace(lines, evar, evalue) - - # Xcode supports various suffices on environment variables, which are - # all undocumented. :rfc1034identifier is used in the standard project - # template these days, and :identifier was used earlier. They are used to - # convert non-url characters into things that look like valid urls -- - # except that the replacement character for :identifier, '_' isn't valid - # in a URL either -- oops, hence :rfc1034identifier was born. - evar = '${%s:identifier}' % key - evalue = IDENT_RE.sub('_', os.environ[key]) - lines = string.replace(lines, evar, evalue) - - evar = '${%s:rfc1034identifier}' % key - evalue = IDENT_RE.sub('-', os.environ[key]) - lines = string.replace(lines, evar, evalue) - - # Remove any keys with values that haven't been replaced. - lines = lines.split('\n') - for i in range(len(lines)): - if lines[i].strip().startswith("${"): - lines[i] = None - lines[i - 1] = None - lines = '\n'.join(filter(lambda x: x is not None, lines)) - - # Write out the file with variables replaced. - fd = open(dest, 'w') - fd.write(lines) - fd.close() - - # Now write out PkgInfo file now that the Info.plist file has been - # "compiled". - self._WritePkgInfo(dest) - - def _WritePkgInfo(self, info_plist): - """This writes the PkgInfo file from the data stored in Info.plist.""" - plist = plistlib.readPlist(info_plist) - if not plist: - return - - # Only create PkgInfo for executable types. - package_type = plist['CFBundlePackageType'] - if package_type != 'APPL': - return - - # The format of PkgInfo is eight characters, representing the bundle type - # and bundle signature, each four characters. If that is missing, four - # '?' characters are used instead. - signature_code = plist.get('CFBundleSignature', '????') - if len(signature_code) != 4: # Wrong length resets everything, too. - signature_code = '?' * 4 - - dest = os.path.join(os.path.dirname(info_plist), 'PkgInfo') - fp = open(dest, 'w') - fp.write('%s%s' % (package_type, signature_code)) - fp.close() - - def ExecFlock(self, lockfile, *cmd_list): - """Emulates the most basic behavior of Linux's flock(1).""" - # Rely on exception handling to report errors. - fd = os.open(lockfile, os.O_RDONLY|os.O_NOCTTY|os.O_CREAT, 0o666) - fcntl.flock(fd, fcntl.LOCK_EX) - return subprocess.call(cmd_list) - - def ExecFilterLibtool(self, *cmd_list): - """Calls libtool and filters out '/path/to/libtool: file: foo.o has no - symbols'.""" - libtool_re = re.compile(r'^.*libtool: file: .* has no symbols$') - libtoolout = subprocess.Popen(cmd_list, stderr=subprocess.PIPE) - _, err = libtoolout.communicate() - for line in err.splitlines(): - if not libtool_re.match(line): - print >>sys.stderr, line - return libtoolout.returncode - - def ExecPackageFramework(self, framework, version): - """Takes a path to Something.framework and the Current version of that and - sets up all the symlinks.""" - # Find the name of the binary based on the part before the ".framework". - binary = os.path.basename(framework).split('.')[0] - - CURRENT = 'Current' - RESOURCES = 'Resources' - VERSIONS = 'Versions' - - if not os.path.exists(os.path.join(framework, VERSIONS, version, binary)): - # Binary-less frameworks don't seem to contain symlinks (see e.g. - # chromium's out/Debug/org.chromium.Chromium.manifest/ bundle). - return - - # Move into the framework directory to set the symlinks correctly. - pwd = os.getcwd() - os.chdir(framework) - - # Set up the Current version. - self._Relink(version, os.path.join(VERSIONS, CURRENT)) - - # Set up the root symlinks. - self._Relink(os.path.join(VERSIONS, CURRENT, binary), binary) - self._Relink(os.path.join(VERSIONS, CURRENT, RESOURCES), RESOURCES) - - # Back to where we were before! - os.chdir(pwd) - - def _Relink(self, dest, link): - """Creates a symlink to |dest| named |link|. If |link| already exists, - it is overwritten.""" - if os.path.lexists(link): - os.remove(link) - os.symlink(dest, link) - - def ExecCodeSignBundle(self, key, resource_rules, entitlements, provisioning): - """Code sign a bundle. - - This function tries to code sign an iOS bundle, following the same - algorithm as Xcode: - 1. copy ResourceRules.plist from the user or the SDK into the bundle, - 2. pick the provisioning profile that best match the bundle identifier, - and copy it into the bundle as embedded.mobileprovision, - 3. copy Entitlements.plist from user or SDK next to the bundle, - 4. code sign the bundle. - """ - resource_rules_path = self._InstallResourceRules(resource_rules) - substitutions, overrides = self._InstallProvisioningProfile( - provisioning, self._GetCFBundleIdentifier()) - entitlements_path = self._InstallEntitlements( - entitlements, substitutions, overrides) - subprocess.check_call([ - 'codesign', '--force', '--sign', key, '--resource-rules', - resource_rules_path, '--entitlements', entitlements_path, - os.path.join( - os.environ['TARGET_BUILD_DIR'], - os.environ['FULL_PRODUCT_NAME'])]) - - def _InstallResourceRules(self, resource_rules): - """Installs ResourceRules.plist from user or SDK into the bundle. - - Args: - resource_rules: string, optional, path to the ResourceRules.plist file - to use, default to "${SDKROOT}/ResourceRules.plist" - - Returns: - Path to the copy of ResourceRules.plist into the bundle. - """ - source_path = resource_rules - target_path = os.path.join( - os.environ['BUILT_PRODUCTS_DIR'], - os.environ['CONTENTS_FOLDER_PATH'], - 'ResourceRules.plist') - if not source_path: - source_path = os.path.join( - os.environ['SDKROOT'], 'ResourceRules.plist') - shutil.copy2(source_path, target_path) - return target_path - - def _InstallProvisioningProfile(self, profile, bundle_identifier): - """Installs embedded.mobileprovision into the bundle. - - Args: - profile: string, optional, short name of the .mobileprovision file - to use, if empty or the file is missing, the best file installed - will be used - bundle_identifier: string, value of CFBundleIdentifier from Info.plist - - Returns: - A tuple containing two dictionary: variables substitutions and values - to overrides when generating the entitlements file. - """ - source_path, provisioning_data, team_id = self._FindProvisioningProfile( - profile, bundle_identifier) - target_path = os.path.join( - os.environ['BUILT_PRODUCTS_DIR'], - os.environ['CONTENTS_FOLDER_PATH'], - 'embedded.mobileprovision') - shutil.copy2(source_path, target_path) - substitutions = self._GetSubstitutions(bundle_identifier, team_id + '.') - return substitutions, provisioning_data['Entitlements'] - - def _FindProvisioningProfile(self, profile, bundle_identifier): - """Finds the .mobileprovision file to use for signing the bundle. - - Checks all the installed provisioning profiles (or if the user specified - the PROVISIONING_PROFILE variable, only consult it) and select the most - specific that correspond to the bundle identifier. - - Args: - profile: string, optional, short name of the .mobileprovision file - to use, if empty or the file is missing, the best file installed - will be used - bundle_identifier: string, value of CFBundleIdentifier from Info.plist - - Returns: - A tuple of the path to the selected provisioning profile, the data of - the embedded plist in the provisioning profile and the team identifier - to use for code signing. - - Raises: - SystemExit: if no .mobileprovision can be used to sign the bundle. - """ - profiles_dir = os.path.join( - os.environ['HOME'], 'Library', 'MobileDevice', 'Provisioning Profiles') - if not os.path.isdir(profiles_dir): - print >>sys.stderr, ( - 'cannot find mobile provisioning for %s' % bundle_identifier) - sys.exit(1) - provisioning_profiles = None - if profile: - profile_path = os.path.join(profiles_dir, profile + '.mobileprovision') - if os.path.exists(profile_path): - provisioning_profiles = [profile_path] - if not provisioning_profiles: - provisioning_profiles = glob.glob( - os.path.join(profiles_dir, '*.mobileprovision')) - valid_provisioning_profiles = {} - for profile_path in provisioning_profiles: - profile_data = self._LoadProvisioningProfile(profile_path) - app_id_pattern = profile_data.get( - 'Entitlements', {}).get('application-identifier', '') - for team_identifier in profile_data.get('TeamIdentifier', []): - app_id = '%s.%s' % (team_identifier, bundle_identifier) - if fnmatch.fnmatch(app_id, app_id_pattern): - valid_provisioning_profiles[app_id_pattern] = ( - profile_path, profile_data, team_identifier) - if not valid_provisioning_profiles: - print >>sys.stderr, ( - 'cannot find mobile provisioning for %s' % bundle_identifier) - sys.exit(1) - # If the user has multiple provisioning profiles installed that can be - # used for ${bundle_identifier}, pick the most specific one (ie. the - # provisioning profile whose pattern is the longest). - selected_key = max(valid_provisioning_profiles, key=lambda v: len(v)) - return valid_provisioning_profiles[selected_key] - - def _LoadProvisioningProfile(self, profile_path): - """Extracts the plist embedded in a provisioning profile. - - Args: - profile_path: string, path to the .mobileprovision file - - Returns: - Content of the plist embedded in the provisioning profile as a dictionary. - """ - with tempfile.NamedTemporaryFile() as temp: - subprocess.check_call([ - 'security', 'cms', '-D', '-i', profile_path, '-o', temp.name]) - return self._LoadPlistMaybeBinary(temp.name) - - def _LoadPlistMaybeBinary(self, plist_path): - """Loads into a memory a plist possibly encoded in binary format. - - This is a wrapper around plistlib.readPlist that tries to convert the - plist to the XML format if it can't be parsed (assuming that it is in - the binary format). - - Args: - plist_path: string, path to a plist file, in XML or binary format - - Returns: - Content of the plist as a dictionary. - """ - try: - # First, try to read the file using plistlib that only supports XML, - # and if an exception is raised, convert a temporary copy to XML and - # load that copy. - return plistlib.readPlist(plist_path) - except: - pass - with tempfile.NamedTemporaryFile() as temp: - shutil.copy2(plist_path, temp.name) - subprocess.check_call(['plutil', '-convert', 'xml1', temp.name]) - return plistlib.readPlist(temp.name) - - def _GetSubstitutions(self, bundle_identifier, app_identifier_prefix): - """Constructs a dictionary of variable substitutions for Entitlements.plist. - - Args: - bundle_identifier: string, value of CFBundleIdentifier from Info.plist - app_identifier_prefix: string, value for AppIdentifierPrefix - - Returns: - Dictionary of substitutions to apply when generating Entitlements.plist. - """ - return { - 'CFBundleIdentifier': bundle_identifier, - 'AppIdentifierPrefix': app_identifier_prefix, - } - - def _GetCFBundleIdentifier(self): - """Extracts CFBundleIdentifier value from Info.plist in the bundle. - - Returns: - Value of CFBundleIdentifier in the Info.plist located in the bundle. - """ - info_plist_path = os.path.join( - os.environ['TARGET_BUILD_DIR'], - os.environ['INFOPLIST_PATH']) - info_plist_data = self._LoadPlistMaybeBinary(info_plist_path) - return info_plist_data['CFBundleIdentifier'] - - def _InstallEntitlements(self, entitlements, substitutions, overrides): - """Generates and install the ${BundleName}.xcent entitlements file. - - Expands variables "$(variable)" pattern in the source entitlements file, - add extra entitlements defined in the .mobileprovision file and the copy - the generated plist to "${BundlePath}.xcent". - - Args: - entitlements: string, optional, path to the Entitlements.plist template - to use, defaults to "${SDKROOT}/Entitlements.plist" - substitutions: dictionary, variable substitutions - overrides: dictionary, values to add to the entitlements - - Returns: - Path to the generated entitlements file. - """ - source_path = entitlements - target_path = os.path.join( - os.environ['BUILT_PRODUCTS_DIR'], - os.environ['PRODUCT_NAME'] + '.xcent') - if not source_path: - source_path = os.path.join( - os.environ['SDKROOT'], - 'Entitlements.plist') - shutil.copy2(source_path, target_path) - data = self._LoadPlistMaybeBinary(target_path) - data = self._ExpandVariables(data, substitutions) - if overrides: - for key in overrides: - if key not in data: - data[key] = overrides[key] - plistlib.writePlist(data, target_path) - return target_path - - def _ExpandVariables(self, data, substitutions): - """Expands variables "$(variable)" in data. - - Args: - data: object, can be either string, list or dictionary - substitutions: dictionary, variable substitutions to perform - - Returns: - Copy of data where each references to "$(variable)" has been replaced - by the corresponding value found in substitutions, or left intact if - the key was not found. - """ - if isinstance(data, str): - for key, value in substitutions.iteritems(): - data = data.replace('$(%s)' % key, value) - return data - if isinstance(data, list): - return [self._ExpandVariables(v, substitutions) for v in data] - if isinstance(data, dict): - return dict((k, self._ExpandVariables(data[k], - substitutions)) for k in data) - return data - -if __name__ == '__main__': - sys.exit(main(sys.argv[1:])) diff --git a/node_modules/mongodb/node_modules/kerberos/build/kerberos.target.mk b/node_modules/mongodb/node_modules/kerberos/build/kerberos.target.mk deleted file mode 100644 index 3df1650..0000000 --- a/node_modules/mongodb/node_modules/kerberos/build/kerberos.target.mk +++ /dev/null @@ -1,172 +0,0 @@ -# This file is generated by gyp; do not edit. - -TOOLSET := target -TARGET := kerberos -DEFS_Debug := \ - '-D_DARWIN_USE_64_BIT_INODE=1' \ - '-D_LARGEFILE_SOURCE' \ - '-D_FILE_OFFSET_BITS=64' \ - '-D__MACOSX_CORE__' \ - '-DBUILDING_NODE_EXTENSION' \ - '-DDEBUG' \ - '-D_DEBUG' - -# Flags passed to all source files. -CFLAGS_Debug := \ - -O0 \ - -gdwarf-2 \ - -mmacosx-version-min=10.5 \ - -arch x86_64 \ - -Wall \ - -Wendif-labels \ - -W \ - -Wno-unused-parameter - -# Flags passed to only C files. -CFLAGS_C_Debug := \ - -fno-strict-aliasing - -# Flags passed to only C++ files. -CFLAGS_CC_Debug := \ - -fno-rtti \ - -fno-threadsafe-statics \ - -fno-strict-aliasing - -# Flags passed to only ObjC files. -CFLAGS_OBJC_Debug := - -# Flags passed to only ObjC++ files. -CFLAGS_OBJCC_Debug := - -INCS_Debug := \ - -I/Users/voxfeed_1/.node-gyp/0.10.31/src \ - -I/Users/voxfeed_1/.node-gyp/0.10.31/deps/uv/include \ - -I/Users/voxfeed_1/.node-gyp/0.10.31/deps/v8/include \ - -I$(srcdir)/node_modules/nan \ - -I/usr/include/mit-krb5 - -DEFS_Release := \ - '-D_DARWIN_USE_64_BIT_INODE=1' \ - '-D_LARGEFILE_SOURCE' \ - '-D_FILE_OFFSET_BITS=64' \ - '-D__MACOSX_CORE__' \ - '-DBUILDING_NODE_EXTENSION' - -# Flags passed to all source files. -CFLAGS_Release := \ - -Os \ - -gdwarf-2 \ - -mmacosx-version-min=10.5 \ - -arch x86_64 \ - -Wall \ - -Wendif-labels \ - -W \ - -Wno-unused-parameter - -# Flags passed to only C files. -CFLAGS_C_Release := \ - -fno-strict-aliasing - -# Flags passed to only C++ files. -CFLAGS_CC_Release := \ - -fno-rtti \ - -fno-threadsafe-statics \ - -fno-strict-aliasing - -# Flags passed to only ObjC files. -CFLAGS_OBJC_Release := - -# Flags passed to only ObjC++ files. -CFLAGS_OBJCC_Release := - -INCS_Release := \ - -I/Users/voxfeed_1/.node-gyp/0.10.31/src \ - -I/Users/voxfeed_1/.node-gyp/0.10.31/deps/uv/include \ - -I/Users/voxfeed_1/.node-gyp/0.10.31/deps/v8/include \ - -I$(srcdir)/node_modules/nan \ - -I/usr/include/mit-krb5 - -OBJS := \ - $(obj).target/$(TARGET)/lib/kerberos.o \ - $(obj).target/$(TARGET)/lib/worker.o \ - $(obj).target/$(TARGET)/lib/kerberosgss.o \ - $(obj).target/$(TARGET)/lib/base64.o \ - $(obj).target/$(TARGET)/lib/kerberos_context.o - -# Add to the list of files we specially track dependencies for. -all_deps += $(OBJS) - -# CFLAGS et al overrides must be target-local. -# See "Target-specific Variable Values" in the GNU Make manual. -$(OBJS): TOOLSET := $(TOOLSET) -$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) -$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) -$(OBJS): GYP_OBJCFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) $(CFLAGS_OBJC_$(BUILDTYPE)) -$(OBJS): GYP_OBJCXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) $(CFLAGS_OBJCC_$(BUILDTYPE)) - -# Suffix rules, putting all outputs into $(obj). - -$(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD - @$(call do_cmd,cxx,1) - -$(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.c FORCE_DO_CMD - @$(call do_cmd,cc,1) - -# Try building from generated source, too. - -$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD - @$(call do_cmd,cxx,1) - -$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD - @$(call do_cmd,cc,1) - -$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.cc FORCE_DO_CMD - @$(call do_cmd,cxx,1) - -$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.c FORCE_DO_CMD - @$(call do_cmd,cc,1) - -# End of this set of suffix rules -### Rules for final target. -LDFLAGS_Debug := \ - -Wl,-search_paths_first \ - -mmacosx-version-min=10.5 \ - -arch x86_64 \ - -L$(builddir) - -LIBTOOLFLAGS_Debug := \ - -Wl,-search_paths_first - -LDFLAGS_Release := \ - -Wl,-search_paths_first \ - -mmacosx-version-min=10.5 \ - -arch x86_64 \ - -L$(builddir) - -LIBTOOLFLAGS_Release := \ - -Wl,-search_paths_first - -LIBS := \ - -undefined dynamic_lookup \ - -lkrb5 - -$(builddir)/kerberos.node: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE)) -$(builddir)/kerberos.node: LIBS := $(LIBS) -$(builddir)/kerberos.node: GYP_LIBTOOLFLAGS := $(LIBTOOLFLAGS_$(BUILDTYPE)) -$(builddir)/kerberos.node: TOOLSET := $(TOOLSET) -$(builddir)/kerberos.node: $(OBJS) FORCE_DO_CMD - $(call do_cmd,solink_module) - -all_deps += $(builddir)/kerberos.node -# Add target alias -.PHONY: kerberos -kerberos: $(builddir)/kerberos.node - -# Short alias for building this executable. -.PHONY: kerberos.node -kerberos.node: $(builddir)/kerberos.node - -# Add executable to "all" target. -.PHONY: all -all: $(builddir)/kerberos.node - diff --git a/node_modules/mongodb/node_modules/kerberos/builderror.log b/node_modules/mongodb/node_modules/kerberos/builderror.log deleted file mode 100644 index ed23681..0000000 --- a/node_modules/mongodb/node_modules/kerberos/builderror.log +++ /dev/null @@ -1,23 +0,0 @@ -xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance - -xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance - -../lib/kerberos.cc:79:3: error: use of undeclared identifier 'scope' - NanReturnValue(args.This()); - ^ -../node_modules/nan/nan.h:1281:39: note: expanded from macro 'NanReturnValue' -# define NanReturnValue(value) return scope.Close(value) - ^ -1 error generated. -make: *** [Release/obj.target/kerberos/lib/kerberos.o] Error 1 -gyp ERR! build error -gyp ERR! stack Error: `make` failed with exit code: 2 -gyp ERR! stack at ChildProcess.onExit (/usr/local/lib/node_modules/npm/node_modules/node-gyp/lib/build.js:267:23) -gyp ERR! stack at ChildProcess.emit (events.js:98:17) -gyp ERR! stack at Process.ChildProcess._handle.onexit (child_process.js:810:12) -gyp ERR! System Darwin 13.4.0 -gyp ERR! command "node" "/usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild" -gyp ERR! cwd /Users/voxfeed_1/code/offhours/argon/node_modules/mongodb/node_modules/kerberos -gyp ERR! node -v v0.10.31 -gyp ERR! node-gyp -v v1.0.1 -gyp ERR! not ok diff --git a/node_modules/mongodb/node_modules/kerberos/index.js b/node_modules/mongodb/node_modules/kerberos/index.js deleted file mode 100644 index b8c8532..0000000 --- a/node_modules/mongodb/node_modules/kerberos/index.js +++ /dev/null @@ -1,6 +0,0 @@ -// Get the Kerberos library -module.exports = require('./lib/kerberos'); -// Set up the auth processes -module.exports['processes'] = { - MongoAuthProcess: require('./lib/auth_processes/mongodb').MongoAuthProcess -} \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/auth_processes/mongodb.js b/node_modules/mongodb/node_modules/kerberos/lib/auth_processes/mongodb.js deleted file mode 100644 index f1e9231..0000000 --- a/node_modules/mongodb/node_modules/kerberos/lib/auth_processes/mongodb.js +++ /dev/null @@ -1,281 +0,0 @@ -var format = require('util').format; - -var MongoAuthProcess = function(host, port, service_name) { - // Check what system we are on - if(process.platform == 'win32') { - this._processor = new Win32MongoProcessor(host, port, service_name); - } else { - this._processor = new UnixMongoProcessor(host, port, service_name); - } -} - -MongoAuthProcess.prototype.init = function(username, password, callback) { - this._processor.init(username, password, callback); -} - -MongoAuthProcess.prototype.transition = function(payload, callback) { - this._processor.transition(payload, callback); -} - -/******************************************************************* - * - * Win32 SSIP Processor for MongoDB - * - *******************************************************************/ -var Win32MongoProcessor = function(host, port, service_name) { - this.host = host; - this.port = port - // SSIP classes - this.ssip = require("../kerberos").SSIP; - // Set up first transition - this._transition = Win32MongoProcessor.first_transition(this); - // Set up service name - service_name = service_name || "mongodb"; - // Set up target - this.target = format("%s/%s", service_name, host); - // Number of retries - this.retries = 10; -} - -Win32MongoProcessor.prototype.init = function(username, password, callback) { - var self = this; - // Save the values used later - this.username = username; - this.password = password; - // Aquire credentials - this.ssip.SecurityCredentials.aquire_kerberos(username, password, function(err, security_credentials) { - if(err) return callback(err); - // Save credentials - self.security_credentials = security_credentials; - // Callback with success - callback(null); - }); -} - -Win32MongoProcessor.prototype.transition = function(payload, callback) { - if(this._transition == null) return callback(new Error("Transition finished")); - this._transition(payload, callback); -} - -Win32MongoProcessor.first_transition = function(self) { - return function(payload, callback) { - self.ssip.SecurityContext.initialize( - self.security_credentials, - self.target, - payload, function(err, security_context) { - if(err) return callback(err); - - // If no context try again until we have no more retries - if(!security_context.hasContext) { - if(self.retries == 0) return callback(new Error("Failed to initialize security context")); - // Update the number of retries - self.retries = self.retries - 1; - // Set next transition - return self.transition(payload, callback); - } - - // Set next transition - self._transition = Win32MongoProcessor.second_transition(self); - self.security_context = security_context; - // Return the payload - callback(null, security_context.payload); - }); - } -} - -Win32MongoProcessor.second_transition = function(self) { - return function(payload, callback) { - // Perform a step - self.security_context.initialize(self.target, payload, function(err, security_context) { - if(err) return callback(err); - - // If no context try again until we have no more retries - if(!security_context.hasContext) { - if(self.retries == 0) return callback(new Error("Failed to initialize security context")); - // Update the number of retries - self.retries = self.retries - 1; - // Set next transition - self._transition = Win32MongoProcessor.first_transition(self); - // Retry - return self.transition(payload, callback); - } - - // Set next transition - self._transition = Win32MongoProcessor.third_transition(self); - // Return the payload - callback(null, security_context.payload); - }); - } -} - -Win32MongoProcessor.third_transition = function(self) { - return function(payload, callback) { - var messageLength = 0; - // Get the raw bytes - var encryptedBytes = new Buffer(payload, 'base64'); - var encryptedMessage = new Buffer(messageLength); - // Copy first byte - encryptedBytes.copy(encryptedMessage, 0, 0, messageLength); - // Set up trailer - var securityTrailerLength = encryptedBytes.length - messageLength; - var securityTrailer = new Buffer(securityTrailerLength); - // Copy the bytes - encryptedBytes.copy(securityTrailer, 0, messageLength, securityTrailerLength); - - // Types used - var SecurityBuffer = self.ssip.SecurityBuffer; - var SecurityBufferDescriptor = self.ssip.SecurityBufferDescriptor; - - // Set up security buffers - var buffers = [ - new SecurityBuffer(SecurityBuffer.DATA, encryptedBytes) - , new SecurityBuffer(SecurityBuffer.STREAM, securityTrailer) - ]; - - // Set up the descriptor - var descriptor = new SecurityBufferDescriptor(buffers); - - // Decrypt the data - self.security_context.decryptMessage(descriptor, function(err, security_context) { - if(err) return callback(err); - - var length = 4; - if(self.username != null) { - length += self.username.length; - } - - var bytesReceivedFromServer = new Buffer(length); - bytesReceivedFromServer[0] = 0x01; // NO_PROTECTION - bytesReceivedFromServer[1] = 0x00; // NO_PROTECTION - bytesReceivedFromServer[2] = 0x00; // NO_PROTECTION - bytesReceivedFromServer[3] = 0x00; // NO_PROTECTION - - if(self.username != null) { - var authorization_id_bytes = new Buffer(self.username, 'utf8'); - authorization_id_bytes.copy(bytesReceivedFromServer, 4, 0); - } - - self.security_context.queryContextAttributes(0x00, function(err, sizes) { - if(err) return callback(err); - - var buffers = [ - new SecurityBuffer(SecurityBuffer.TOKEN, new Buffer(sizes.securityTrailer)) - , new SecurityBuffer(SecurityBuffer.DATA, bytesReceivedFromServer) - , new SecurityBuffer(SecurityBuffer.PADDING, new Buffer(sizes.blockSize)) - ] - - var descriptor = new SecurityBufferDescriptor(buffers); - - self.security_context.encryptMessage(descriptor, 0x80000001, function(err, security_context) { - if(err) return callback(err); - callback(null, security_context.payload); - }); - }); - }); - } -} - -/******************************************************************* - * - * UNIX MIT Kerberos processor - * - *******************************************************************/ -var UnixMongoProcessor = function(host, port, service_name) { - this.host = host; - this.port = port - // SSIP classes - this.Kerberos = require("../kerberos").Kerberos; - this.kerberos = new this.Kerberos(); - service_name = service_name || "mongodb"; - // Set up first transition - this._transition = UnixMongoProcessor.first_transition(this); - // Set up target - this.target = format("%s@%s", service_name, host); - // Number of retries - this.retries = 10; -} - -UnixMongoProcessor.prototype.init = function(username, password, callback) { - var self = this; - this.username = username; - this.password = password; - // Call client initiate - this.kerberos.authGSSClientInit( - self.target - , this.Kerberos.GSS_C_MUTUAL_FLAG, function(err, context) { - self.context = context; - // Return the context - callback(null, context); - }); -} - -UnixMongoProcessor.prototype.transition = function(payload, callback) { - if(this._transition == null) return callback(new Error("Transition finished")); - this._transition(payload, callback); -} - -UnixMongoProcessor.first_transition = function(self) { - return function(payload, callback) { - self.kerberos.authGSSClientStep(self.context, '', function(err, result) { - if(err) return callback(err); - // Set up the next step - self._transition = UnixMongoProcessor.second_transition(self); - // Return the payload - callback(null, self.context.response); - }) - } -} - -UnixMongoProcessor.second_transition = function(self) { - return function(payload, callback) { - self.kerberos.authGSSClientStep(self.context, payload, function(err, result) { - if(err && self.retries == 0) return callback(err); - // Attempt to re-establish a context - if(err) { - // Adjust the number of retries - self.retries = self.retries - 1; - // Call same step again - return self.transition(payload, callback); - } - - // Set up the next step - self._transition = UnixMongoProcessor.third_transition(self); - // Return the payload - callback(null, self.context.response || ''); - }); - } -} - -UnixMongoProcessor.third_transition = function(self) { - return function(payload, callback) { - // GSS Client Unwrap - self.kerberos.authGSSClientUnwrap(self.context, payload, function(err, result) { - if(err) return callback(err, false); - - // Wrap the response - self.kerberos.authGSSClientWrap(self.context, self.context.response, self.username, function(err, result) { - if(err) return callback(err, false); - // Set up the next step - self._transition = UnixMongoProcessor.fourth_transition(self); - // Return the payload - callback(null, self.context.response); - }); - }); - } -} - -UnixMongoProcessor.fourth_transition = function(self) { - return function(payload, callback) { - // Clean up context - self.kerberos.authGSSClientClean(self.context, function(err, result) { - if(err) return callback(err, false); - // Set the transition to null - self._transition = null; - // Callback with valid authentication - callback(null, true); - }); - } -} - -// Set the process -exports.MongoAuthProcess = MongoAuthProcess; \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/base64.c b/node_modules/mongodb/node_modules/kerberos/lib/base64.c deleted file mode 100644 index aca0a61..0000000 --- a/node_modules/mongodb/node_modules/kerberos/lib/base64.c +++ /dev/null @@ -1,134 +0,0 @@ -/** - * Copyright (c) 2006-2008 Apple Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - **/ - -#include "base64.h" - -#include -#include -#include -#include - -void die2(const char *message) { - if(errno) { - perror(message); - } else { - printf("ERROR: %s\n", message); - } - - exit(1); -} - -// base64 tables -static char basis_64[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -static signed char index_64[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,62, -1,-1,-1,63, - 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1, - -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, - 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, - -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, - 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1 -}; -#define CHAR64(c) (((c) < 0 || (c) > 127) ? -1 : index_64[(c)]) - -// base64_encode : base64 encode -// -// value : data to encode -// vlen : length of data -// (result) : new char[] - c-str of result -char *base64_encode(const unsigned char *value, int vlen) -{ - char *result = (char *)malloc((vlen * 4) / 3 + 5); - if(result == NULL) die2("Memory allocation failed"); - char *out = result; - while (vlen >= 3) - { - *out++ = basis_64[value[0] >> 2]; - *out++ = basis_64[((value[0] << 4) & 0x30) | (value[1] >> 4)]; - *out++ = basis_64[((value[1] << 2) & 0x3C) | (value[2] >> 6)]; - *out++ = basis_64[value[2] & 0x3F]; - value += 3; - vlen -= 3; - } - if (vlen > 0) - { - *out++ = basis_64[value[0] >> 2]; - unsigned char oval = (value[0] << 4) & 0x30; - if (vlen > 1) oval |= value[1] >> 4; - *out++ = basis_64[oval]; - *out++ = (vlen < 2) ? '=' : basis_64[(value[1] << 2) & 0x3C]; - *out++ = '='; - } - *out = '\0'; - - return result; -} - -// base64_decode : base64 decode -// -// value : c-str to decode -// rlen : length of decoded result -// (result) : new unsigned char[] - decoded result -unsigned char *base64_decode(const char *value, int *rlen) -{ - *rlen = 0; - int c1, c2, c3, c4; - - int vlen = strlen(value); - unsigned char *result =(unsigned char *)malloc((vlen * 3) / 4 + 1); - if(result == NULL) die2("Memory allocation failed"); - unsigned char *out = result; - - while (1) - { - if (value[0]==0) - return result; - c1 = value[0]; - if (CHAR64(c1) == -1) - goto base64_decode_error;; - c2 = value[1]; - if (CHAR64(c2) == -1) - goto base64_decode_error;; - c3 = value[2]; - if ((c3 != '=') && (CHAR64(c3) == -1)) - goto base64_decode_error;; - c4 = value[3]; - if ((c4 != '=') && (CHAR64(c4) == -1)) - goto base64_decode_error;; - - value += 4; - *out++ = (CHAR64(c1) << 2) | (CHAR64(c2) >> 4); - *rlen += 1; - if (c3 != '=') - { - *out++ = ((CHAR64(c2) << 4) & 0xf0) | (CHAR64(c3) >> 2); - *rlen += 1; - if (c4 != '=') - { - *out++ = ((CHAR64(c3) << 6) & 0xc0) | CHAR64(c4); - *rlen += 1; - } - } - } - -base64_decode_error: - *result = 0; - *rlen = 0; - return result; -} diff --git a/node_modules/mongodb/node_modules/kerberos/lib/base64.h b/node_modules/mongodb/node_modules/kerberos/lib/base64.h deleted file mode 100644 index 9152e6a..0000000 --- a/node_modules/mongodb/node_modules/kerberos/lib/base64.h +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Copyright (c) 2006-2008 Apple Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - **/ -#ifndef BASE64_H -#define BASE64_H - -char *base64_encode(const unsigned char *value, int vlen); -unsigned char *base64_decode(const char *value, int *rlen); - -#endif \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/kerberos.cc b/node_modules/mongodb/node_modules/kerberos/lib/kerberos.cc deleted file mode 100644 index 4e2bc85..0000000 --- a/node_modules/mongodb/node_modules/kerberos/lib/kerberos.cc +++ /dev/null @@ -1,591 +0,0 @@ -#include "kerberos.h" -#include -#include -#include "worker.h" -#include "kerberos_context.h" - -#ifndef ARRAY_SIZE -# define ARRAY_SIZE(a) (sizeof((a)) / sizeof((a)[0])) -#endif - -void die(const char *message) { - if(errno) { - perror(message); - } else { - printf("ERROR: %s\n", message); - } - - exit(1); -} - -// Call structs -typedef struct AuthGSSClientCall { - uint32_t flags; - char *uri; -} AuthGSSClientCall; - -typedef struct AuthGSSClientStepCall { - KerberosContext *context; - char *challenge; -} AuthGSSClientStepCall; - -typedef struct AuthGSSClientUnwrapCall { - KerberosContext *context; - char *challenge; -} AuthGSSClientUnwrapCall; - -typedef struct AuthGSSClientWrapCall { - KerberosContext *context; - char *challenge; - char *user_name; -} AuthGSSClientWrapCall; - -typedef struct AuthGSSClientCleanCall { - KerberosContext *context; -} AuthGSSClientCleanCall; - -Kerberos::Kerberos() : ObjectWrap() { -} - -Persistent Kerberos::constructor_template; - -void Kerberos::Initialize(v8::Handle target) { - // Grab the scope of the call from Node - NanScope(); - - // Define a new function template - Local t = NanNew(New); - t->InstanceTemplate()->SetInternalFieldCount(1); - t->SetClassName(NanNew("Kerberos")); - - // Set up method for the Kerberos instance - NODE_SET_PROTOTYPE_METHOD(t, "authGSSClientInit", AuthGSSClientInit); - NODE_SET_PROTOTYPE_METHOD(t, "authGSSClientStep", AuthGSSClientStep); - NODE_SET_PROTOTYPE_METHOD(t, "authGSSClientUnwrap", AuthGSSClientUnwrap); - NODE_SET_PROTOTYPE_METHOD(t, "authGSSClientWrap", AuthGSSClientWrap); - NODE_SET_PROTOTYPE_METHOD(t, "authGSSClientClean", AuthGSSClientClean); - - NanAssignPersistent(constructor_template, t); - - // Set the symbol - target->ForceSet(NanNew("Kerberos"), t->GetFunction()); -} - -NAN_METHOD(Kerberos::New) { - // Create a Kerberos instance - Kerberos *kerberos = new Kerberos(); - // Return the kerberos object - kerberos->Wrap(args.This()); - NanReturnValue(args.This()); -} - -// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -// authGSSClientInit -// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -static void _authGSSClientInit(Worker *worker) { - gss_client_state *state; - gss_client_response *response; - - // Allocate state - state = (gss_client_state *)malloc(sizeof(gss_client_state)); - if(state == NULL) die("Memory allocation failed"); - - // Unpack the parameter data struct - AuthGSSClientCall *call = (AuthGSSClientCall *)worker->parameters; - // Start the kerberos client - response = authenticate_gss_client_init(call->uri, call->flags, state); - - // Release the parameter struct memory - free(call->uri); - free(call); - - // If we have an error mark worker as having had an error - if(response->return_code == AUTH_GSS_ERROR) { - worker->error = TRUE; - worker->error_code = response->return_code; - worker->error_message = response->message; - free(state); - } else { - worker->return_value = state; - } - - // Free structure - free(response); -} - -static Handle _map_authGSSClientInit(Worker *worker) { - KerberosContext *context = KerberosContext::New(); - context->state = (gss_client_state *)worker->return_value; - return NanObjectWrapHandle(context); -} - -// Initialize method -NAN_METHOD(Kerberos::AuthGSSClientInit) { - NanScope(); - - // Ensure valid call - if(args.Length() != 3) return NanThrowError("Requires a service string uri, integer flags and a callback function"); - if(args.Length() == 3 && !args[0]->IsString() && !args[1]->IsInt32() && !args[2]->IsFunction()) - return NanThrowError("Requires a service string uri, integer flags and a callback function"); - - Local service = args[0]->ToString(); - // Convert uri string to c-string - char *service_str = (char *)calloc(service->Utf8Length() + 1, sizeof(char)); - if(service_str == NULL) die("Memory allocation failed"); - - // Write v8 string to c-string - service->WriteUtf8(service_str); - - // Allocate a structure - AuthGSSClientCall *call = (AuthGSSClientCall *)calloc(1, sizeof(AuthGSSClientCall)); - if(call == NULL) die("Memory allocation failed"); - call->flags =args[1]->ToInt32()->Uint32Value(); - call->uri = service_str; - - // Unpack the callback - Local callbackHandle = Local::Cast(args[2]); - NanCallback *callback = new NanCallback(callbackHandle); - - // Let's allocate some space - Worker *worker = new Worker(); - worker->error = false; - worker->request.data = worker; - worker->callback = callback; - worker->parameters = call; - worker->execute = _authGSSClientInit; - worker->mapper = _map_authGSSClientInit; - - // Schedule the worker with lib_uv - uv_queue_work(uv_default_loop(), &worker->request, Kerberos::Process, (uv_after_work_cb)Kerberos::After); - // Return no value as it's callback based - NanReturnValue(NanUndefined()); -} - -// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -// authGSSClientStep -// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -static void _authGSSClientStep(Worker *worker) { - gss_client_state *state; - gss_client_response *response; - char *challenge; - - // Unpack the parameter data struct - AuthGSSClientStepCall *call = (AuthGSSClientStepCall *)worker->parameters; - // Get the state - state = call->context->state; - challenge = call->challenge; - - // Check what kind of challenge we have - if(call->challenge == NULL) { - challenge = (char *)""; - } - - // Perform authentication step - response = authenticate_gss_client_step(state, challenge); - - // If we have an error mark worker as having had an error - if(response->return_code == AUTH_GSS_ERROR) { - worker->error = TRUE; - worker->error_code = response->return_code; - worker->error_message = response->message; - } else { - worker->return_code = response->return_code; - } - - // Free up structure - if(call->challenge != NULL) free(call->challenge); - free(call); - free(response); -} - -static Handle _map_authGSSClientStep(Worker *worker) { - NanScope(); - // Return the return code - return NanNew(worker->return_code); -} - -// Initialize method -NAN_METHOD(Kerberos::AuthGSSClientStep) { - NanScope(); - - // Ensure valid call - if(args.Length() != 2 && args.Length() != 3) return NanThrowError("Requires a GSS context, optional challenge string and callback function"); - if(args.Length() == 2 && !KerberosContext::HasInstance(args[0])) return NanThrowError("Requires a GSS context, optional challenge string and callback function"); - if(args.Length() == 3 && !KerberosContext::HasInstance(args[0]) && !args[1]->IsString()) return NanThrowError("Requires a GSS context, optional challenge string and callback function"); - - // Challenge string - char *challenge_str = NULL; - // Let's unpack the parameters - Local object = args[0]->ToObject(); - KerberosContext *kerberos_context = KerberosContext::Unwrap(object); - - // If we have a challenge string - if(args.Length() == 3) { - // Unpack the challenge string - Local challenge = args[1]->ToString(); - // Convert uri string to c-string - challenge_str = (char *)calloc(challenge->Utf8Length() + 1, sizeof(char)); - if(challenge_str == NULL) die("Memory allocation failed"); - // Write v8 string to c-string - challenge->WriteUtf8(challenge_str); - } - - // Allocate a structure - AuthGSSClientStepCall *call = (AuthGSSClientStepCall *)calloc(1, sizeof(AuthGSSClientCall)); - if(call == NULL) die("Memory allocation failed"); - call->context = kerberos_context; - call->challenge = challenge_str; - - // Unpack the callback - Local callbackHandle = Local::Cast(args[2]); - NanCallback *callback = new NanCallback(callbackHandle); - - // Let's allocate some space - Worker *worker = new Worker(); - worker->error = false; - worker->request.data = worker; - worker->callback = callback; - worker->parameters = call; - worker->execute = _authGSSClientStep; - worker->mapper = _map_authGSSClientStep; - - // Schedule the worker with lib_uv - uv_queue_work(uv_default_loop(), &worker->request, Kerberos::Process, (uv_after_work_cb)Kerberos::After); - - // Return no value as it's callback based - NanReturnValue(NanUndefined()); -} - -// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -// authGSSClientUnwrap -// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -static void _authGSSClientUnwrap(Worker *worker) { - gss_client_response *response; - char *challenge; - - // Unpack the parameter data struct - AuthGSSClientUnwrapCall *call = (AuthGSSClientUnwrapCall *)worker->parameters; - challenge = call->challenge; - - // Check what kind of challenge we have - if(call->challenge == NULL) { - challenge = (char *)""; - } - - // Perform authentication step - response = authenticate_gss_client_unwrap(call->context->state, challenge); - - // If we have an error mark worker as having had an error - if(response->return_code == AUTH_GSS_ERROR) { - worker->error = TRUE; - worker->error_code = response->return_code; - worker->error_message = response->message; - } else { - worker->return_code = response->return_code; - } - - // Free up structure - if(call->challenge != NULL) free(call->challenge); - free(call); - free(response); -} - -static Handle _map_authGSSClientUnwrap(Worker *worker) { - NanScope(); - // Return the return code - return NanNew(worker->return_code); -} - -// Initialize method -NAN_METHOD(Kerberos::AuthGSSClientUnwrap) { - NanScope(); - - // Ensure valid call - if(args.Length() != 2 && args.Length() != 3) return NanThrowError("Requires a GSS context, optional challenge string and callback function"); - if(args.Length() == 2 && !KerberosContext::HasInstance(args[0]) && !args[1]->IsFunction()) return NanThrowError("Requires a GSS context, optional challenge string and callback function"); - if(args.Length() == 3 && !KerberosContext::HasInstance(args[0]) && !args[1]->IsString() && !args[2]->IsFunction()) return NanThrowError("Requires a GSS context, optional challenge string and callback function"); - - // Challenge string - char *challenge_str = NULL; - // Let's unpack the parameters - Local object = args[0]->ToObject(); - KerberosContext *kerberos_context = KerberosContext::Unwrap(object); - - // If we have a challenge string - if(args.Length() == 3) { - // Unpack the challenge string - Local challenge = args[1]->ToString(); - // Convert uri string to c-string - challenge_str = (char *)calloc(challenge->Utf8Length() + 1, sizeof(char)); - if(challenge_str == NULL) die("Memory allocation failed"); - // Write v8 string to c-string - challenge->WriteUtf8(challenge_str); - } - - // Allocate a structure - AuthGSSClientUnwrapCall *call = (AuthGSSClientUnwrapCall *)calloc(1, sizeof(AuthGSSClientUnwrapCall)); - if(call == NULL) die("Memory allocation failed"); - call->context = kerberos_context; - call->challenge = challenge_str; - - // Unpack the callback - Local callbackHandle = args.Length() == 3 ? Local::Cast(args[2]) : Local::Cast(args[1]); - NanCallback *callback = new NanCallback(callbackHandle); - - // Let's allocate some space - Worker *worker = new Worker(); - worker->error = false; - worker->request.data = worker; - worker->callback = callback; - worker->parameters = call; - worker->execute = _authGSSClientUnwrap; - worker->mapper = _map_authGSSClientUnwrap; - - // Schedule the worker with lib_uv - uv_queue_work(uv_default_loop(), &worker->request, Kerberos::Process, (uv_after_work_cb)Kerberos::After); - - // Return no value as it's callback based - // return scope.Close(NanUndefined()); - NanReturnValue(NanUndefined()); -} - -// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -// authGSSClientWrap -// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -static void _authGSSClientWrap(Worker *worker) { - gss_client_response *response; - char *user_name = NULL; - - // Unpack the parameter data struct - AuthGSSClientWrapCall *call = (AuthGSSClientWrapCall *)worker->parameters; - user_name = call->user_name; - - // Check what kind of challenge we have - if(call->user_name == NULL) { - user_name = (char *)""; - } - - // Perform authentication step - response = authenticate_gss_client_wrap(call->context->state, call->challenge, user_name); - - // If we have an error mark worker as having had an error - if(response->return_code == AUTH_GSS_ERROR) { - worker->error = TRUE; - worker->error_code = response->return_code; - worker->error_message = response->message; - } else { - worker->return_code = response->return_code; - } - - // Free up structure - if(call->challenge != NULL) free(call->challenge); - if(call->user_name != NULL) free(call->user_name); - free(call); - free(response); -} - -static Handle _map_authGSSClientWrap(Worker *worker) { - NanScope(); - // Return the return code - return NanNew(worker->return_code); -} - -// Initialize method -NAN_METHOD(Kerberos::AuthGSSClientWrap) { - NanScope(); - - // Ensure valid call - if(args.Length() != 3 && args.Length() != 4) return NanThrowError("Requires a GSS context, the result from the authGSSClientResponse after authGSSClientUnwrap, optional user name and callback function"); - if(args.Length() == 3 && !KerberosContext::HasInstance(args[0]) && !args[1]->IsString() && !args[2]->IsFunction()) return NanThrowError("Requires a GSS context, the result from the authGSSClientResponse after authGSSClientUnwrap, optional user name and callback function"); - if(args.Length() == 4 && !KerberosContext::HasInstance(args[0]) && !args[1]->IsString() && !args[2]->IsString() && !args[2]->IsFunction()) return NanThrowError("Requires a GSS context, the result from the authGSSClientResponse after authGSSClientUnwrap, optional user name and callback function"); - - // Challenge string - char *challenge_str = NULL; - char *user_name_str = NULL; - - // Let's unpack the kerberos context - Local object = args[0]->ToObject(); - KerberosContext *kerberos_context = KerberosContext::Unwrap(object); - - // Unpack the challenge string - Local challenge = args[1]->ToString(); - // Convert uri string to c-string - challenge_str = (char *)calloc(challenge->Utf8Length() + 1, sizeof(char)); - if(challenge_str == NULL) die("Memory allocation failed"); - // Write v8 string to c-string - challenge->WriteUtf8(challenge_str); - - // If we have a user string - if(args.Length() == 4) { - // Unpack user name - Local user_name = args[2]->ToString(); - // Convert uri string to c-string - user_name_str = (char *)calloc(user_name->Utf8Length() + 1, sizeof(char)); - if(user_name_str == NULL) die("Memory allocation failed"); - // Write v8 string to c-string - user_name->WriteUtf8(user_name_str); - } - - // Allocate a structure - AuthGSSClientWrapCall *call = (AuthGSSClientWrapCall *)calloc(1, sizeof(AuthGSSClientWrapCall)); - if(call == NULL) die("Memory allocation failed"); - call->context = kerberos_context; - call->challenge = challenge_str; - call->user_name = user_name_str; - - // Unpack the callback - Local callbackHandle = args.Length() == 4 ? Local::Cast(args[3]) : Local::Cast(args[2]); - NanCallback *callback = new NanCallback(callbackHandle); - - // Let's allocate some space - Worker *worker = new Worker(); - worker->error = false; - worker->request.data = worker; - worker->callback = callback; - worker->parameters = call; - worker->execute = _authGSSClientWrap; - worker->mapper = _map_authGSSClientWrap; - - // Schedule the worker with lib_uv - uv_queue_work(uv_default_loop(), &worker->request, Kerberos::Process, (uv_after_work_cb)Kerberos::After); - - // Return no value as it's callback based - NanReturnValue(NanUndefined()); -} - -// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -// authGSSClientWrap -// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -static void _authGSSClientClean(Worker *worker) { - gss_client_response *response; - - // Unpack the parameter data struct - AuthGSSClientCleanCall *call = (AuthGSSClientCleanCall *)worker->parameters; - - // Perform authentication step - response = authenticate_gss_client_clean(call->context->state); - - // If we have an error mark worker as having had an error - if(response->return_code == AUTH_GSS_ERROR) { - worker->error = TRUE; - worker->error_code = response->return_code; - worker->error_message = response->message; - } else { - worker->return_code = response->return_code; - } - - // Free up structure - free(call); - free(response); -} - -static Handle _map_authGSSClientClean(Worker *worker) { - NanScope(); - // Return the return code - return NanNew(worker->return_code); -} - -// Initialize method -NAN_METHOD(Kerberos::AuthGSSClientClean) { - NanScope(); - - // // Ensure valid call - if(args.Length() != 2) return NanThrowError("Requires a GSS context and callback function"); - if(!KerberosContext::HasInstance(args[0]) && !args[1]->IsFunction()) return NanThrowError("Requires a GSS context and callback function"); - - // Let's unpack the kerberos context - Local object = args[0]->ToObject(); - KerberosContext *kerberos_context = KerberosContext::Unwrap(object); - - // Allocate a structure - AuthGSSClientCleanCall *call = (AuthGSSClientCleanCall *)calloc(1, sizeof(AuthGSSClientCleanCall)); - if(call == NULL) die("Memory allocation failed"); - call->context = kerberos_context; - - // Unpack the callback - Local callbackHandle = Local::Cast(args[1]); - NanCallback *callback = new NanCallback(callbackHandle); - - // Let's allocate some space - Worker *worker = new Worker(); - worker->error = false; - worker->request.data = worker; - worker->callback = callback; - worker->parameters = call; - worker->execute = _authGSSClientClean; - worker->mapper = _map_authGSSClientClean; - - // Schedule the worker with lib_uv - uv_queue_work(uv_default_loop(), &worker->request, Kerberos::Process, (uv_after_work_cb)Kerberos::After); - - // Return no value as it's callback based - NanReturnValue(NanUndefined()); -} - -// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -// UV Lib callbacks -// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -void Kerberos::Process(uv_work_t* work_req) { - // Grab the worker - Worker *worker = static_cast(work_req->data); - // Execute the worker code - worker->execute(worker); -} - -void Kerberos::After(uv_work_t* work_req) { - // Grab the scope of the call from Node - NanScope(); - - // Get the worker reference - Worker *worker = static_cast(work_req->data); - - // If we have an error - if(worker->error) { - Local err = v8::Exception::Error(NanNew(worker->error_message)); - Local obj = err->ToObject(); - obj->Set(NanNew("code"), NanNew(worker->error_code)); - Local args[2] = { err, NanNull() }; - // Execute the error - v8::TryCatch try_catch; - - // Call the callback - worker->callback->Call(ARRAY_SIZE(args), args); - - // If we have an exception handle it as a fatalexception - if (try_catch.HasCaught()) { - node::FatalException(try_catch); - } - } else { - // // Map the data - Handle result = worker->mapper(worker); - // Set up the callback with a null first - Handle args[2] = { NanNull(), result}; - - // Wrap the callback function call in a TryCatch so that we can call - // node's FatalException afterwards. This makes it possible to catch - // the exception from JavaScript land using the - // process.on('uncaughtException') event. - v8::TryCatch try_catch; - - // Call the callback - worker->callback->Call(ARRAY_SIZE(args), args); - - // If we have an exception handle it as a fatalexception - if (try_catch.HasCaught()) { - node::FatalException(try_catch); - } - } - - // Clean up the memory - delete worker->callback; - delete worker; -} - -// Exporting function -extern "C" void init(Handle target) { - NanScope(); - Kerberos::Initialize(target); - KerberosContext::Initialize(target); -} - -NODE_MODULE(kerberos, init); diff --git a/node_modules/mongodb/node_modules/kerberos/lib/kerberos.h b/node_modules/mongodb/node_modules/kerberos/lib/kerberos.h deleted file mode 100644 index b037d4e..0000000 --- a/node_modules/mongodb/node_modules/kerberos/lib/kerberos.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef KERBEROS_H -#define KERBEROS_H - -#include -#include -#include -#include - -#include "nan.h" -#include -#include - -#include "util.h" - -extern "C" { - #include "kerberosgss.h" -} - -using namespace v8; -using namespace node; - -class Kerberos : public ObjectWrap { - -public: - Kerberos(); - ~Kerberos() {}; - - // Constructor used for creating new Kerberos objects from C++ - static Persistent constructor_template; - - // Initialize function for the object - static void Initialize(Handle target); - - // Method available - static NAN_METHOD(AuthGSSClientInit); - static NAN_METHOD(AuthGSSClientStep); - static NAN_METHOD(AuthGSSClientUnwrap); - static NAN_METHOD(AuthGSSClientWrap); - static NAN_METHOD(AuthGSSClientClean); - -private: - static NAN_METHOD(New); - // Handles the uv calls - static void Process(uv_work_t* work_req); - // Called after work is done - static void After(uv_work_t* work_req); -}; - -#endif \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/kerberos.js b/node_modules/mongodb/node_modules/kerberos/lib/kerberos.js deleted file mode 100644 index b1a701b..0000000 --- a/node_modules/mongodb/node_modules/kerberos/lib/kerberos.js +++ /dev/null @@ -1,91 +0,0 @@ -var kerberos = require('../build/Release/kerberos') - , KerberosNative = kerberos.Kerberos; - -var Kerberos = function() { - this._native_kerberos = new KerberosNative(); -} - -Kerberos.prototype.authGSSClientInit = function(uri, flags, callback) { - return this._native_kerberos.authGSSClientInit(uri, flags, callback); -} - -Kerberos.prototype.authGSSClientStep = function(context, challenge, callback) { - if(typeof challenge == 'function') { - callback = challenge; - challenge = ''; - } - - return this._native_kerberos.authGSSClientStep(context, challenge, callback); -} - -Kerberos.prototype.authGSSClientUnwrap = function(context, challenge, callback) { - if(typeof challenge == 'function') { - callback = challenge; - challenge = ''; - } - - return this._native_kerberos.authGSSClientUnwrap(context, challenge, callback); -} - -Kerberos.prototype.authGSSClientWrap = function(context, challenge, user_name, callback) { - if(typeof user_name == 'function') { - callback = user_name; - user_name = ''; - } - - return this._native_kerberos.authGSSClientWrap(context, challenge, user_name, callback); -} - -Kerberos.prototype.authGSSClientClean = function(context, callback) { - return this._native_kerberos.authGSSClientClean(context, callback); -} - -Kerberos.prototype.acquireAlternateCredentials = function(user_name, password, domain) { - return this._native_kerberos.acquireAlternateCredentials(user_name, password, domain); -} - -Kerberos.prototype.prepareOutboundPackage = function(principal, inputdata) { - return this._native_kerberos.prepareOutboundPackage(principal, inputdata); -} - -Kerberos.prototype.decryptMessage = function(challenge) { - return this._native_kerberos.decryptMessage(challenge); -} - -Kerberos.prototype.encryptMessage = function(challenge) { - return this._native_kerberos.encryptMessage(challenge); -} - -Kerberos.prototype.queryContextAttribute = function(attribute) { - if(typeof attribute != 'number' && attribute != 0x00) throw new Error("Attribute not supported"); - return this._native_kerberos.queryContextAttribute(attribute); -} - -// Some useful result codes -Kerberos.AUTH_GSS_CONTINUE = 0; -Kerberos.AUTH_GSS_COMPLETE = 1; - -// Some useful gss flags -Kerberos.GSS_C_DELEG_FLAG = 1; -Kerberos.GSS_C_MUTUAL_FLAG = 2; -Kerberos.GSS_C_REPLAY_FLAG = 4; -Kerberos.GSS_C_SEQUENCE_FLAG = 8; -Kerberos.GSS_C_CONF_FLAG = 16; -Kerberos.GSS_C_INTEG_FLAG = 32; -Kerberos.GSS_C_ANON_FLAG = 64; -Kerberos.GSS_C_PROT_READY_FLAG = 128; -Kerberos.GSS_C_TRANS_FLAG = 256; - -// Export Kerberos class -exports.Kerberos = Kerberos; - -// If we have SSPI (windows) -if(kerberos.SecurityCredentials) { - // Put all SSPI classes in it's own namespace - exports.SSIP = { - SecurityCredentials: require('./win32/wrappers/security_credentials').SecurityCredentials - , SecurityContext: require('./win32/wrappers/security_context').SecurityContext - , SecurityBuffer: require('./win32/wrappers/security_buffer').SecurityBuffer - , SecurityBufferDescriptor: require('./win32/wrappers/security_buffer_descriptor').SecurityBufferDescriptor - } -} diff --git a/node_modules/mongodb/node_modules/kerberos/lib/kerberos_context.cc b/node_modules/mongodb/node_modules/kerberos/lib/kerberos_context.cc deleted file mode 100644 index de32aad..0000000 --- a/node_modules/mongodb/node_modules/kerberos/lib/kerberos_context.cc +++ /dev/null @@ -1,76 +0,0 @@ -#include "kerberos_context.h" - -Persistent KerberosContext::constructor_template; - -KerberosContext::KerberosContext() : ObjectWrap() { -} - -KerberosContext::~KerberosContext() { -} - -KerberosContext* KerberosContext::New() { - NanScope(); - Local obj = NanNew(constructor_template)->GetFunction()->NewInstance(); - KerberosContext *kerberos_context = ObjectWrap::Unwrap(obj); - return kerberos_context; -} - -NAN_METHOD(KerberosContext::New) { - NanScope(); - // Create code object - KerberosContext *kerberos_context = new KerberosContext(); - // Wrap it - kerberos_context->Wrap(args.This()); - // Return the object - NanReturnValue(args.This()); -} - -void KerberosContext::Initialize(v8::Handle target) { - // Grab the scope of the call from Node - NanScope(); - - // Define a new function template - Local t = NanNew(New); - t->InstanceTemplate()->SetInternalFieldCount(1); - t->SetClassName(NanNew("KerberosContext")); - - // Get prototype - Local proto = t->PrototypeTemplate(); - - // Getter for the response - proto->SetAccessor(NanNew("response"), KerberosContext::ResponseGetter); - - // Set persistent - NanAssignPersistent(constructor_template, t); - - // Set the symbol - target->ForceSet(NanNew("KerberosContext"), t->GetFunction()); -} - -// -// Response Setter / Getter -NAN_GETTER(KerberosContext::ResponseGetter) { - NanScope(); - gss_client_state *state; - - // Unpack the object - KerberosContext *context = ObjectWrap::Unwrap(args.This()); - // Let's grab the response - state = context->state; - // No state no response - if(state == NULL || state->response == NULL) { - NanReturnValue(NanNull()); - } else { - // Return the response - NanReturnValue(NanNew(state->response)); - } -} - - - - - - - - - diff --git a/node_modules/mongodb/node_modules/kerberos/lib/kerberos_context.h b/node_modules/mongodb/node_modules/kerberos/lib/kerberos_context.h deleted file mode 100644 index dd00f1d..0000000 --- a/node_modules/mongodb/node_modules/kerberos/lib/kerberos_context.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef KERBEROS_CONTEXT_H -#define KERBEROS_CONTEXT_H - -#include -#include -#include -#include - -#include "nan.h" -#include -#include - -extern "C" { - #include "kerberosgss.h" -} - -using namespace v8; -using namespace node; - -class KerberosContext : public ObjectWrap { - -public: - KerberosContext(); - ~KerberosContext(); - - static inline bool HasInstance(Handle val) { - if (!val->IsObject()) return false; - Local obj = val->ToObject(); - return NanNew(constructor_template)->HasInstance(obj); - }; - - // Constructor used for creating new Kerberos objects from C++ - static Persistent constructor_template; - - // Initialize function for the object - static void Initialize(Handle target); - - // Public constructor - static KerberosContext* New(); - - // Handle to the kerberos context - gss_client_state *state; - -private: - static NAN_METHOD(New); - static NAN_GETTER(ResponseGetter); -}; -#endif \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/kerberosgss.c b/node_modules/mongodb/node_modules/kerberos/lib/kerberosgss.c deleted file mode 100644 index 8e55b62..0000000 --- a/node_modules/mongodb/node_modules/kerberos/lib/kerberosgss.c +++ /dev/null @@ -1,693 +0,0 @@ -/** - * Copyright (c) 2006-2010 Apple Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - **/ - -#include "kerberosgss.h" - -#include "base64.h" - -#include -#include -#include -#include -#include - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - -void die1(const char *message) { - if(errno) { - perror(message); - } else { - printf("ERROR: %s\n", message); - } - - exit(1); -} - -static void set_gss_error(OM_uint32 err_maj, OM_uint32 err_min); - -/*extern PyObject *GssException_class; -extern PyObject *KrbException_class; - -char* server_principal_details(const char* service, const char* hostname) -{ - char match[1024]; - int match_len = 0; - char* result = NULL; - - int code; - krb5_context kcontext; - krb5_keytab kt = NULL; - krb5_kt_cursor cursor = NULL; - krb5_keytab_entry entry; - char* pname = NULL; - - // Generate the principal prefix we want to match - snprintf(match, 1024, "%s/%s@", service, hostname); - match_len = strlen(match); - - code = krb5_init_context(&kcontext); - if (code) - { - PyErr_SetObject(KrbException_class, Py_BuildValue("((s:i))", - "Cannot initialize Kerberos5 context", code)); - return NULL; - } - - if ((code = krb5_kt_default(kcontext, &kt))) - { - PyErr_SetObject(KrbException_class, Py_BuildValue("((s:i))", - "Cannot get default keytab", code)); - goto end; - } - - if ((code = krb5_kt_start_seq_get(kcontext, kt, &cursor))) - { - PyErr_SetObject(KrbException_class, Py_BuildValue("((s:i))", - "Cannot get sequence cursor from keytab", code)); - goto end; - } - - while ((code = krb5_kt_next_entry(kcontext, kt, &entry, &cursor)) == 0) - { - if ((code = krb5_unparse_name(kcontext, entry.principal, &pname))) - { - PyErr_SetObject(KrbException_class, Py_BuildValue("((s:i))", - "Cannot parse principal name from keytab", code)); - goto end; - } - - if (strncmp(pname, match, match_len) == 0) - { - result = malloc(strlen(pname) + 1); - strcpy(result, pname); - krb5_free_unparsed_name(kcontext, pname); - krb5_free_keytab_entry_contents(kcontext, &entry); - break; - } - - krb5_free_unparsed_name(kcontext, pname); - krb5_free_keytab_entry_contents(kcontext, &entry); - } - - if (result == NULL) - { - PyErr_SetObject(KrbException_class, Py_BuildValue("((s:i))", - "Principal not found in keytab", -1)); - } - -end: - if (cursor) - krb5_kt_end_seq_get(kcontext, kt, &cursor); - if (kt) - krb5_kt_close(kcontext, kt); - krb5_free_context(kcontext); - - return result; -} -*/ -gss_client_response *authenticate_gss_client_init(const char* service, long int gss_flags, gss_client_state* state) { - OM_uint32 maj_stat; - OM_uint32 min_stat; - gss_buffer_desc name_token = GSS_C_EMPTY_BUFFER; - gss_client_response *response = NULL; - int ret = AUTH_GSS_COMPLETE; - - state->server_name = GSS_C_NO_NAME; - state->context = GSS_C_NO_CONTEXT; - state->gss_flags = gss_flags; - state->username = NULL; - state->response = NULL; - - // Import server name first - name_token.length = strlen(service); - name_token.value = (char *)service; - - maj_stat = gss_import_name(&min_stat, &name_token, gss_krb5_nt_service_name, &state->server_name); - - if (GSS_ERROR(maj_stat)) { - response = gss_error(maj_stat, min_stat); - response->return_code = AUTH_GSS_ERROR; - goto end; - } - -end: - if(response == NULL) { - response = calloc(1, sizeof(gss_client_response)); - if(response == NULL) die1("Memory allocation failed"); - response->return_code = ret; - } - - return response; -} - -gss_client_response *authenticate_gss_client_clean(gss_client_state *state) { - OM_uint32 min_stat; - int ret = AUTH_GSS_COMPLETE; - gss_client_response *response = NULL; - - if(state->context != GSS_C_NO_CONTEXT) - gss_delete_sec_context(&min_stat, &state->context, GSS_C_NO_BUFFER); - - if(state->server_name != GSS_C_NO_NAME) - gss_release_name(&min_stat, &state->server_name); - - if(state->username != NULL) { - free(state->username); - state->username = NULL; - } - - if (state->response != NULL) { - free(state->response); - state->response = NULL; - } - - if(response == NULL) { - response = calloc(1, sizeof(gss_client_response)); - if(response == NULL) die1("Memory allocation failed"); - response->return_code = ret; - } - - return response; -} - -gss_client_response *authenticate_gss_client_step(gss_client_state* state, const char* challenge) { - OM_uint32 maj_stat; - OM_uint32 min_stat; - gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; - gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; - int ret = AUTH_GSS_CONTINUE; - gss_client_response *response = NULL; - - // Always clear out the old response - if (state->response != NULL) { - free(state->response); - state->response = NULL; - } - - // If there is a challenge (data from the server) we need to give it to GSS - if (challenge && *challenge) { - int len; - input_token.value = base64_decode(challenge, &len); - input_token.length = len; - } - - // Do GSSAPI step - maj_stat = gss_init_sec_context(&min_stat, - GSS_C_NO_CREDENTIAL, - &state->context, - state->server_name, - GSS_C_NO_OID, - (OM_uint32)state->gss_flags, - 0, - GSS_C_NO_CHANNEL_BINDINGS, - &input_token, - NULL, - &output_token, - NULL, - NULL); - - if ((maj_stat != GSS_S_COMPLETE) && (maj_stat != GSS_S_CONTINUE_NEEDED)) { - response = gss_error(maj_stat, min_stat); - response->return_code = AUTH_GSS_ERROR; - goto end; - } - - ret = (maj_stat == GSS_S_COMPLETE) ? AUTH_GSS_COMPLETE : AUTH_GSS_CONTINUE; - // Grab the client response to send back to the server - if(output_token.length) { - state->response = base64_encode((const unsigned char *)output_token.value, output_token.length); - maj_stat = gss_release_buffer(&min_stat, &output_token); - } - - // Try to get the user name if we have completed all GSS operations - if (ret == AUTH_GSS_COMPLETE) { - gss_name_t gssuser = GSS_C_NO_NAME; - maj_stat = gss_inquire_context(&min_stat, state->context, &gssuser, NULL, NULL, NULL, NULL, NULL, NULL); - - if(GSS_ERROR(maj_stat)) { - response = gss_error(maj_stat, min_stat); - response->return_code = AUTH_GSS_ERROR; - goto end; - } - - gss_buffer_desc name_token; - name_token.length = 0; - maj_stat = gss_display_name(&min_stat, gssuser, &name_token, NULL); - - if(GSS_ERROR(maj_stat)) { - if(name_token.value) - gss_release_buffer(&min_stat, &name_token); - gss_release_name(&min_stat, &gssuser); - - response = gss_error(maj_stat, min_stat); - response->return_code = AUTH_GSS_ERROR; - goto end; - } else { - state->username = (char *)malloc(name_token.length + 1); - if(state->username == NULL) die1("Memory allocation failed"); - strncpy(state->username, (char*) name_token.value, name_token.length); - state->username[name_token.length] = 0; - gss_release_buffer(&min_stat, &name_token); - gss_release_name(&min_stat, &gssuser); - } - } - -end: - if(output_token.value) - gss_release_buffer(&min_stat, &output_token); - if(input_token.value) - free(input_token.value); - - if(response == NULL) { - response = calloc(1, sizeof(gss_client_response)); - if(response == NULL) die1("Memory allocation failed"); - response->return_code = ret; - } - - // Return the response - return response; -} - -gss_client_response *authenticate_gss_client_unwrap(gss_client_state *state, const char *challenge) { - OM_uint32 maj_stat; - OM_uint32 min_stat; - gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; - gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; - gss_client_response *response = NULL; - int ret = AUTH_GSS_CONTINUE; - - // Always clear out the old response - if(state->response != NULL) { - free(state->response); - state->response = NULL; - } - - // If there is a challenge (data from the server) we need to give it to GSS - if(challenge && *challenge) { - int len; - input_token.value = base64_decode(challenge, &len); - input_token.length = len; - } - - // Do GSSAPI step - maj_stat = gss_unwrap(&min_stat, - state->context, - &input_token, - &output_token, - NULL, - NULL); - - if(maj_stat != GSS_S_COMPLETE) { - response = gss_error(maj_stat, min_stat); - response->return_code = AUTH_GSS_ERROR; - goto end; - } else { - ret = AUTH_GSS_COMPLETE; - } - - // Grab the client response - if(output_token.length) { - state->response = base64_encode((const unsigned char *)output_token.value, output_token.length); - gss_release_buffer(&min_stat, &output_token); - } -end: - if(output_token.value) - gss_release_buffer(&min_stat, &output_token); - if(input_token.value) - free(input_token.value); - - if(response == NULL) { - response = calloc(1, sizeof(gss_client_response)); - if(response == NULL) die1("Memory allocation failed"); - response->return_code = ret; - } - - // Return the response - return response; -} - -gss_client_response *authenticate_gss_client_wrap(gss_client_state* state, const char* challenge, const char* user) { - OM_uint32 maj_stat; - OM_uint32 min_stat; - gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; - gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; - int ret = AUTH_GSS_CONTINUE; - gss_client_response *response = NULL; - char buf[4096], server_conf_flags; - unsigned long buf_size; - - // Always clear out the old response - if(state->response != NULL) { - free(state->response); - state->response = NULL; - } - - if(challenge && *challenge) { - int len; - input_token.value = base64_decode(challenge, &len); - input_token.length = len; - } - - if(user) { - // get bufsize - server_conf_flags = ((char*) input_token.value)[0]; - ((char*) input_token.value)[0] = 0; - buf_size = ntohl(*((long *) input_token.value)); - free(input_token.value); -#ifdef PRINTFS - printf("User: %s, %c%c%c\n", user, - server_conf_flags & GSS_AUTH_P_NONE ? 'N' : '-', - server_conf_flags & GSS_AUTH_P_INTEGRITY ? 'I' : '-', - server_conf_flags & GSS_AUTH_P_PRIVACY ? 'P' : '-'); - printf("Maximum GSS token size is %ld\n", buf_size); -#endif - - // agree to terms (hack!) - buf_size = htonl(buf_size); // not relevant without integrity/privacy - memcpy(buf, &buf_size, 4); - buf[0] = GSS_AUTH_P_NONE; - // server decides if principal can log in as user - strncpy(buf + 4, user, sizeof(buf) - 4); - input_token.value = buf; - input_token.length = 4 + strlen(user); - } - - // Do GSSAPI wrap - maj_stat = gss_wrap(&min_stat, - state->context, - 0, - GSS_C_QOP_DEFAULT, - &input_token, - NULL, - &output_token); - - if (maj_stat != GSS_S_COMPLETE) { - response = gss_error(maj_stat, min_stat); - response->return_code = AUTH_GSS_ERROR; - goto end; - } else - ret = AUTH_GSS_COMPLETE; - // Grab the client response to send back to the server - if (output_token.length) { - state->response = base64_encode((const unsigned char *)output_token.value, output_token.length);; - gss_release_buffer(&min_stat, &output_token); - } -end: - if (output_token.value) - gss_release_buffer(&min_stat, &output_token); - - if(response == NULL) { - response = calloc(1, sizeof(gss_client_response)); - if(response == NULL) die1("Memory allocation failed"); - response->return_code = ret; - } - - // Return the response - return response; -} - -int authenticate_gss_server_init(const char *service, gss_server_state *state) -{ - OM_uint32 maj_stat; - OM_uint32 min_stat; - gss_buffer_desc name_token = GSS_C_EMPTY_BUFFER; - int ret = AUTH_GSS_COMPLETE; - - state->context = GSS_C_NO_CONTEXT; - state->server_name = GSS_C_NO_NAME; - state->client_name = GSS_C_NO_NAME; - state->server_creds = GSS_C_NO_CREDENTIAL; - state->client_creds = GSS_C_NO_CREDENTIAL; - state->username = NULL; - state->targetname = NULL; - state->response = NULL; - - // Server name may be empty which means we aren't going to create our own creds - size_t service_len = strlen(service); - if (service_len != 0) - { - // Import server name first - name_token.length = strlen(service); - name_token.value = (char *)service; - - maj_stat = gss_import_name(&min_stat, &name_token, GSS_C_NT_HOSTBASED_SERVICE, &state->server_name); - - if (GSS_ERROR(maj_stat)) - { - set_gss_error(maj_stat, min_stat); - ret = AUTH_GSS_ERROR; - goto end; - } - - // Get credentials - maj_stat = gss_acquire_cred(&min_stat, state->server_name, GSS_C_INDEFINITE, - GSS_C_NO_OID_SET, GSS_C_ACCEPT, &state->server_creds, NULL, NULL); - - if (GSS_ERROR(maj_stat)) - { - set_gss_error(maj_stat, min_stat); - ret = AUTH_GSS_ERROR; - goto end; - } - } - -end: - return ret; -} - -int authenticate_gss_server_clean(gss_server_state *state) -{ - OM_uint32 min_stat; - int ret = AUTH_GSS_COMPLETE; - - if (state->context != GSS_C_NO_CONTEXT) - gss_delete_sec_context(&min_stat, &state->context, GSS_C_NO_BUFFER); - if (state->server_name != GSS_C_NO_NAME) - gss_release_name(&min_stat, &state->server_name); - if (state->client_name != GSS_C_NO_NAME) - gss_release_name(&min_stat, &state->client_name); - if (state->server_creds != GSS_C_NO_CREDENTIAL) - gss_release_cred(&min_stat, &state->server_creds); - if (state->client_creds != GSS_C_NO_CREDENTIAL) - gss_release_cred(&min_stat, &state->client_creds); - if (state->username != NULL) - { - free(state->username); - state->username = NULL; - } - if (state->targetname != NULL) - { - free(state->targetname); - state->targetname = NULL; - } - if (state->response != NULL) - { - free(state->response); - state->response = NULL; - } - - return ret; -} - -/*int authenticate_gss_server_step(gss_server_state *state, const char *challenge) -{ - OM_uint32 maj_stat; - OM_uint32 min_stat; - gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; - gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; - int ret = AUTH_GSS_CONTINUE; - - // Always clear out the old response - if (state->response != NULL) - { - free(state->response); - state->response = NULL; - } - - // If there is a challenge (data from the server) we need to give it to GSS - if (challenge && *challenge) - { - int len; - input_token.value = base64_decode(challenge, &len); - input_token.length = len; - } - else - { - PyErr_SetString(KrbException_class, "No challenge parameter in request from client"); - ret = AUTH_GSS_ERROR; - goto end; - } - - maj_stat = gss_accept_sec_context(&min_stat, - &state->context, - state->server_creds, - &input_token, - GSS_C_NO_CHANNEL_BINDINGS, - &state->client_name, - NULL, - &output_token, - NULL, - NULL, - &state->client_creds); - - if (GSS_ERROR(maj_stat)) - { - set_gss_error(maj_stat, min_stat); - ret = AUTH_GSS_ERROR; - goto end; - } - - // Grab the server response to send back to the client - if (output_token.length) - { - state->response = base64_encode((const unsigned char *)output_token.value, output_token.length);; - maj_stat = gss_release_buffer(&min_stat, &output_token); - } - - // Get the user name - maj_stat = gss_display_name(&min_stat, state->client_name, &output_token, NULL); - if (GSS_ERROR(maj_stat)) - { - set_gss_error(maj_stat, min_stat); - ret = AUTH_GSS_ERROR; - goto end; - } - state->username = (char *)malloc(output_token.length + 1); - strncpy(state->username, (char*) output_token.value, output_token.length); - state->username[output_token.length] = 0; - - // Get the target name if no server creds were supplied - if (state->server_creds == GSS_C_NO_CREDENTIAL) - { - gss_name_t target_name = GSS_C_NO_NAME; - maj_stat = gss_inquire_context(&min_stat, state->context, NULL, &target_name, NULL, NULL, NULL, NULL, NULL); - if (GSS_ERROR(maj_stat)) - { - set_gss_error(maj_stat, min_stat); - ret = AUTH_GSS_ERROR; - goto end; - } - maj_stat = gss_display_name(&min_stat, target_name, &output_token, NULL); - if (GSS_ERROR(maj_stat)) - { - set_gss_error(maj_stat, min_stat); - ret = AUTH_GSS_ERROR; - goto end; - } - state->targetname = (char *)malloc(output_token.length + 1); - strncpy(state->targetname, (char*) output_token.value, output_token.length); - state->targetname[output_token.length] = 0; - } - - ret = AUTH_GSS_COMPLETE; - -end: - if (output_token.length) - gss_release_buffer(&min_stat, &output_token); - if (input_token.value) - free(input_token.value); - return ret; -} -*/ - -static void set_gss_error(OM_uint32 err_maj, OM_uint32 err_min) { - OM_uint32 maj_stat, min_stat; - OM_uint32 msg_ctx = 0; - gss_buffer_desc status_string; - char buf_maj[512]; - char buf_min[512]; - - do { - maj_stat = gss_display_status (&min_stat, - err_maj, - GSS_C_GSS_CODE, - GSS_C_NO_OID, - &msg_ctx, - &status_string); - if(GSS_ERROR(maj_stat)) - break; - - strncpy(buf_maj, (char*) status_string.value, sizeof(buf_maj)); - gss_release_buffer(&min_stat, &status_string); - - maj_stat = gss_display_status (&min_stat, - err_min, - GSS_C_MECH_CODE, - GSS_C_NULL_OID, - &msg_ctx, - &status_string); - if (!GSS_ERROR(maj_stat)) { - - strncpy(buf_min, (char*) status_string.value , sizeof(buf_min)); - gss_release_buffer(&min_stat, &status_string); - } - } while (!GSS_ERROR(maj_stat) && msg_ctx != 0); -} - -gss_client_response *gss_error(OM_uint32 err_maj, OM_uint32 err_min) { - OM_uint32 maj_stat, min_stat; - OM_uint32 msg_ctx = 0; - gss_buffer_desc status_string; - char *buf_maj = calloc(512, sizeof(char)); - if(buf_maj == NULL) die1("Memory allocation failed"); - char *buf_min = calloc(512, sizeof(char)); - if(buf_min == NULL) die1("Memory allocation failed"); - char *message = NULL; - gss_client_response *response = calloc(1, sizeof(gss_client_response)); - if(response == NULL) die1("Memory allocation failed"); - - do { - maj_stat = gss_display_status (&min_stat, - err_maj, - GSS_C_GSS_CODE, - GSS_C_NO_OID, - &msg_ctx, - &status_string); - if(GSS_ERROR(maj_stat)) - break; - - strncpy(buf_maj, (char*) status_string.value, 512); - gss_release_buffer(&min_stat, &status_string); - - maj_stat = gss_display_status (&min_stat, - err_min, - GSS_C_MECH_CODE, - GSS_C_NULL_OID, - &msg_ctx, - &status_string); - if(!GSS_ERROR(maj_stat)) { - strncpy(buf_min, (char*) status_string.value , 512); - gss_release_buffer(&min_stat, &status_string); - } - } while (!GSS_ERROR(maj_stat) && msg_ctx != 0); - - // Join the strings - message = calloc(1026, 1); - if(message == NULL) die1("Memory allocation failed"); - // Join the two messages - sprintf(message, "%s, %s", buf_maj, buf_min); - // Free data - free(buf_min); - free(buf_maj); - // Set the message - response->message = message; - // Return the message - return response; -} - -#pragma clang diagnostic pop - diff --git a/node_modules/mongodb/node_modules/kerberos/lib/kerberosgss.h b/node_modules/mongodb/node_modules/kerberos/lib/kerberosgss.h deleted file mode 100644 index 58ac0b7..0000000 --- a/node_modules/mongodb/node_modules/kerberos/lib/kerberosgss.h +++ /dev/null @@ -1,70 +0,0 @@ -/** - * Copyright (c) 2006-2009 Apple Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - **/ -#ifndef KERBEROS_GSS_H -#define KERBEROS_GSS_H - -#include -#include -#include - -#define krb5_get_err_text(context,code) error_message(code) - -#define AUTH_GSS_ERROR -1 -#define AUTH_GSS_COMPLETE 1 -#define AUTH_GSS_CONTINUE 0 - -#define GSS_AUTH_P_NONE 1 -#define GSS_AUTH_P_INTEGRITY 2 -#define GSS_AUTH_P_PRIVACY 4 - -typedef struct { - int return_code; - char *message; -} gss_client_response; - -typedef struct { - gss_ctx_id_t context; - gss_name_t server_name; - long int gss_flags; - char* username; - char* response; -} gss_client_state; - -typedef struct { - gss_ctx_id_t context; - gss_name_t server_name; - gss_name_t client_name; - gss_cred_id_t server_creds; - gss_cred_id_t client_creds; - char* username; - char* targetname; - char* response; -} gss_server_state; - -// char* server_principal_details(const char* service, const char* hostname); - -gss_client_response *authenticate_gss_client_init(const char* service, long int gss_flags, gss_client_state* state); -gss_client_response *authenticate_gss_client_clean(gss_client_state *state); -gss_client_response *authenticate_gss_client_step(gss_client_state *state, const char *challenge); -gss_client_response *authenticate_gss_client_unwrap(gss_client_state* state, const char* challenge); -gss_client_response *authenticate_gss_client_wrap(gss_client_state* state, const char* challenge, const char* user); - -int authenticate_gss_server_init(const char* service, gss_server_state* state); -int authenticate_gss_server_clean(gss_server_state *state); -// int authenticate_gss_server_step(gss_server_state *state, const char *challenge); - -gss_client_response *gss_error(OM_uint32 err_maj, OM_uint32 err_min); -#endif diff --git a/node_modules/mongodb/node_modules/kerberos/lib/sspi.js b/node_modules/mongodb/node_modules/kerberos/lib/sspi.js deleted file mode 100644 index d9120fb..0000000 --- a/node_modules/mongodb/node_modules/kerberos/lib/sspi.js +++ /dev/null @@ -1,15 +0,0 @@ -// Load the native SSPI classes -var kerberos = require('../build/Release/kerberos') - , Kerberos = kerberos.Kerberos - , SecurityBuffer = require('./win32/wrappers/security_buffer').SecurityBuffer - , SecurityBufferDescriptor = require('./win32/wrappers/security_buffer_descriptor').SecurityBufferDescriptor - , SecurityCredentials = require('./win32/wrappers/security_credentials').SecurityCredentials - , SecurityContext = require('./win32/wrappers/security_context').SecurityContext; -var SSPI = function() { -} - -exports.SSPI = SSPI; -exports.SecurityBuffer = SecurityBuffer; -exports.SecurityBufferDescriptor = SecurityBufferDescriptor; -exports.SecurityCredentials = SecurityCredentials; -exports.SecurityContext = SecurityContext; \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/base64.c b/node_modules/mongodb/node_modules/kerberos/lib/win32/base64.c deleted file mode 100644 index 502a021..0000000 --- a/node_modules/mongodb/node_modules/kerberos/lib/win32/base64.c +++ /dev/null @@ -1,121 +0,0 @@ -/** - * Copyright (c) 2006-2008 Apple Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - **/ - -#include "base64.h" - -#include -#include - -// base64 tables -static char basis_64[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -static signed char index_64[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,62, -1,-1,-1,63, - 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1, - -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, - 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, - -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, - 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1 -}; -#define CHAR64(c) (((c) < 0 || (c) > 127) ? -1 : index_64[(c)]) - -// base64_encode : base64 encode -// -// value : data to encode -// vlen : length of data -// (result) : new char[] - c-str of result -char *base64_encode(const unsigned char *value, int vlen) -{ - char *result = (char *)malloc((vlen * 4) / 3 + 5); - char *out = result; - unsigned char oval; - - while (vlen >= 3) - { - *out++ = basis_64[value[0] >> 2]; - *out++ = basis_64[((value[0] << 4) & 0x30) | (value[1] >> 4)]; - *out++ = basis_64[((value[1] << 2) & 0x3C) | (value[2] >> 6)]; - *out++ = basis_64[value[2] & 0x3F]; - value += 3; - vlen -= 3; - } - if (vlen > 0) - { - *out++ = basis_64[value[0] >> 2]; - oval = (value[0] << 4) & 0x30; - if (vlen > 1) oval |= value[1] >> 4; - *out++ = basis_64[oval]; - *out++ = (vlen < 2) ? '=' : basis_64[(value[1] << 2) & 0x3C]; - *out++ = '='; - } - *out = '\0'; - - return result; -} - -// base64_decode : base64 decode -// -// value : c-str to decode -// rlen : length of decoded result -// (result) : new unsigned char[] - decoded result -unsigned char *base64_decode(const char *value, int *rlen) -{ - int c1, c2, c3, c4; - int vlen = (int)strlen(value); - unsigned char *result =(unsigned char *)malloc((vlen * 3) / 4 + 1); - unsigned char *out = result; - *rlen = 0; - - while (1) - { - if (value[0]==0) - return result; - c1 = value[0]; - if (CHAR64(c1) == -1) - goto base64_decode_error;; - c2 = value[1]; - if (CHAR64(c2) == -1) - goto base64_decode_error;; - c3 = value[2]; - if ((c3 != '=') && (CHAR64(c3) == -1)) - goto base64_decode_error;; - c4 = value[3]; - if ((c4 != '=') && (CHAR64(c4) == -1)) - goto base64_decode_error;; - - value += 4; - *out++ = (CHAR64(c1) << 2) | (CHAR64(c2) >> 4); - *rlen += 1; - if (c3 != '=') - { - *out++ = ((CHAR64(c2) << 4) & 0xf0) | (CHAR64(c3) >> 2); - *rlen += 1; - if (c4 != '=') - { - *out++ = ((CHAR64(c3) << 6) & 0xc0) | CHAR64(c4); - *rlen += 1; - } - } - } - -base64_decode_error: - *result = 0; - *rlen = 0; - return result; -} diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/base64.h b/node_modules/mongodb/node_modules/kerberos/lib/win32/base64.h deleted file mode 100644 index f0e1f06..0000000 --- a/node_modules/mongodb/node_modules/kerberos/lib/win32/base64.h +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Copyright (c) 2006-2008 Apple Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - **/ - -char *base64_encode(const unsigned char *value, int vlen); -unsigned char *base64_decode(const char *value, int *rlen); diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos.cc b/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos.cc deleted file mode 100644 index c40be18..0000000 --- a/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos.cc +++ /dev/null @@ -1,53 +0,0 @@ -#include "kerberos.h" -#include -#include -#include "base64.h" -#include "wrappers/security_buffer.h" -#include "wrappers/security_buffer_descriptor.h" -#include "wrappers/security_context.h" -#include "wrappers/security_credentials.h" - -Persistent Kerberos::constructor_template; - -Kerberos::Kerberos() : ObjectWrap() { -} - -void Kerberos::Initialize(v8::Handle target) { - // Grab the scope of the call from Node - NanScope(); - - // Define a new function template - Local t = NanNew(New); - t->InstanceTemplate()->SetInternalFieldCount(1); - t->SetClassName(NanNew("Kerberos")); - - // Set persistent - NanAssignPersistent(constructor_template, t); - - // Set the symbol - target->ForceSet(NanNew("Kerberos"), t->GetFunction()); -} - -NAN_METHOD(Kerberos::New) { - NanScope(); - // Load the security.dll library - load_library(); - // Create a Kerberos instance - Kerberos *kerberos = new Kerberos(); - // Return the kerberos object - kerberos->Wrap(args.This()); - // Return the object - NanReturnValue(args.This()); -} - -// Exporting function -extern "C" void init(Handle target) { - NanScope(); - Kerberos::Initialize(target); - SecurityContext::Initialize(target); - SecurityBuffer::Initialize(target); - SecurityBufferDescriptor::Initialize(target); - SecurityCredentials::Initialize(target); -} - -NODE_MODULE(kerberos, init); diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos.h b/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos.h deleted file mode 100644 index 579d04e..0000000 --- a/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef KERBEROS_H -#define KERBEROS_H - -#include -#include -#include -#include "nan.h" - -extern "C" { - #include "kerberos_sspi.h" - #include "base64.h" -} - -using namespace v8; -using namespace node; - -class Kerberos : public ObjectWrap { - -public: - Kerberos(); - ~Kerberos() {}; - - // Constructor used for creating new Kerberos objects from C++ - static Persistent constructor_template; - - // Initialize function for the object - static void Initialize(Handle target); - - // Method available - static NAN_METHOD(AcquireAlternateCredentials); - static NAN_METHOD(PrepareOutboundPackage); - static NAN_METHOD(DecryptMessage); - static NAN_METHOD(EncryptMessage); - static NAN_METHOD(QueryContextAttributes); - -private: - static NAN_METHOD(New); - - // Pointer to context object - SEC_WINNT_AUTH_IDENTITY m_Identity; - // credentials - CredHandle m_Credentials; - // Expiry time for ticket - TimeStamp Expiration; - // package info - SecPkgInfo m_PkgInfo; - // context - CtxtHandle m_Context; - // Do we have a context - bool m_HaveContext; - // Attributes - DWORD CtxtAttr; - - // Handles the uv calls - static void Process(uv_work_t* work_req); - // Called after work is done - static void After(uv_work_t* work_req); -}; - -#endif \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos_sspi.c b/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos_sspi.c deleted file mode 100644 index d75c9ab..0000000 --- a/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos_sspi.c +++ /dev/null @@ -1,244 +0,0 @@ -#include "kerberos_sspi.h" -#include -#include - -static HINSTANCE _sspi_security_dll = NULL; -static HINSTANCE _sspi_secur32_dll = NULL; - -/** - * Encrypt A Message - */ -SECURITY_STATUS SEC_ENTRY _sspi_EncryptMessage(PCtxtHandle phContext, unsigned long fQOP, PSecBufferDesc pMessage, unsigned long MessageSeqNo) { - // Create function pointer instance - encryptMessage_fn pfn_encryptMessage = NULL; - - // Return error if library not loaded - if(_sspi_security_dll == NULL) return -1; - - // Map function to library method - pfn_encryptMessage = (encryptMessage_fn)GetProcAddress(_sspi_security_dll, "EncryptMessage"); - // Check if the we managed to map function pointer - if(!pfn_encryptMessage) { - printf("GetProcAddress failed.\n"); - return -2; - } - - // Call the function - return (*pfn_encryptMessage)(phContext, fQOP, pMessage, MessageSeqNo); -} - -/** - * Acquire Credentials - */ -SECURITY_STATUS SEC_ENTRY _sspi_AcquireCredentialsHandle( - LPSTR pszPrincipal, LPSTR pszPackage, unsigned long fCredentialUse, - void * pvLogonId, void * pAuthData, SEC_GET_KEY_FN pGetKeyFn, void * pvGetKeyArgument, - PCredHandle phCredential, PTimeStamp ptsExpiry -) { - SECURITY_STATUS status; - // Create function pointer instance - acquireCredentialsHandle_fn pfn_acquireCredentialsHandle = NULL; - - // Return error if library not loaded - if(_sspi_security_dll == NULL) return -1; - - // Map function - #ifdef _UNICODE - pfn_acquireCredentialsHandle = (acquireCredentialsHandle_fn)GetProcAddress(_sspi_security_dll, "AcquireCredentialsHandleW"); - #else - pfn_acquireCredentialsHandle = (acquireCredentialsHandle_fn)GetProcAddress(_sspi_security_dll, "AcquireCredentialsHandleA"); - #endif - - // Check if the we managed to map function pointer - if(!pfn_acquireCredentialsHandle) { - printf("GetProcAddress failed.\n"); - return -2; - } - - // Status - status = (*pfn_acquireCredentialsHandle)(pszPrincipal, pszPackage, fCredentialUse, - pvLogonId, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry - ); - - // Call the function - return status; -} - -/** - * Delete Security Context - */ -SECURITY_STATUS SEC_ENTRY _sspi_DeleteSecurityContext(PCtxtHandle phContext) { - // Create function pointer instance - deleteSecurityContext_fn pfn_deleteSecurityContext = NULL; - - // Return error if library not loaded - if(_sspi_security_dll == NULL) return -1; - // Map function - pfn_deleteSecurityContext = (deleteSecurityContext_fn)GetProcAddress(_sspi_security_dll, "DeleteSecurityContext"); - - // Check if the we managed to map function pointer - if(!pfn_deleteSecurityContext) { - printf("GetProcAddress failed.\n"); - return -2; - } - - // Call the function - return (*pfn_deleteSecurityContext)(phContext); -} - -/** - * Decrypt Message - */ -SECURITY_STATUS SEC_ENTRY _sspi_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, unsigned long MessageSeqNo, unsigned long pfQOP) { - // Create function pointer instance - decryptMessage_fn pfn_decryptMessage = NULL; - - // Return error if library not loaded - if(_sspi_security_dll == NULL) return -1; - // Map function - pfn_decryptMessage = (decryptMessage_fn)GetProcAddress(_sspi_security_dll, "DecryptMessage"); - - // Check if the we managed to map function pointer - if(!pfn_decryptMessage) { - printf("GetProcAddress failed.\n"); - return -2; - } - - // Call the function - return (*pfn_decryptMessage)(phContext, pMessage, MessageSeqNo, pfQOP); -} - -/** - * Initialize Security Context - */ -SECURITY_STATUS SEC_ENTRY _sspi_initializeSecurityContext( - PCredHandle phCredential, PCtxtHandle phContext, - LPSTR pszTargetName, unsigned long fContextReq, - unsigned long Reserved1, unsigned long TargetDataRep, - PSecBufferDesc pInput, unsigned long Reserved2, - PCtxtHandle phNewContext, PSecBufferDesc pOutput, - unsigned long * pfContextAttr, PTimeStamp ptsExpiry -) { - SECURITY_STATUS status; - // Create function pointer instance - initializeSecurityContext_fn pfn_initializeSecurityContext = NULL; - - // Return error if library not loaded - if(_sspi_security_dll == NULL) return -1; - - // Map function - #ifdef _UNICODE - pfn_initializeSecurityContext = (initializeSecurityContext_fn)GetProcAddress(_sspi_security_dll, "InitializeSecurityContextW"); - #else - pfn_initializeSecurityContext = (initializeSecurityContext_fn)GetProcAddress(_sspi_security_dll, "InitializeSecurityContextA"); - #endif - - // Check if the we managed to map function pointer - if(!pfn_initializeSecurityContext) { - printf("GetProcAddress failed.\n"); - return -2; - } - - // Execute intialize context - status = (*pfn_initializeSecurityContext)( - phCredential, phContext, pszTargetName, fContextReq, - Reserved1, TargetDataRep, pInput, Reserved2, - phNewContext, pOutput, pfContextAttr, ptsExpiry - ); - - // Call the function - return status; -} -/** - * Query Context Attributes - */ -SECURITY_STATUS SEC_ENTRY _sspi_QueryContextAttributes( - PCtxtHandle phContext, unsigned long ulAttribute, void * pBuffer -) { - // Create function pointer instance - queryContextAttributes_fn pfn_queryContextAttributes = NULL; - - // Return error if library not loaded - if(_sspi_security_dll == NULL) return -1; - - #ifdef _UNICODE - pfn_queryContextAttributes = (queryContextAttributes_fn)GetProcAddress(_sspi_security_dll, "QueryContextAttributesW"); - #else - pfn_queryContextAttributes = (queryContextAttributes_fn)GetProcAddress(_sspi_security_dll, "QueryContextAttributesA"); - #endif - - // Check if the we managed to map function pointer - if(!pfn_queryContextAttributes) { - printf("GetProcAddress failed.\n"); - return -2; - } - - // Call the function - return (*pfn_queryContextAttributes)( - phContext, ulAttribute, pBuffer - ); -} - -/** - * InitSecurityInterface - */ -PSecurityFunctionTable _ssip_InitSecurityInterface() { - INIT_SECURITY_INTERFACE InitSecurityInterface; - PSecurityFunctionTable pSecurityInterface = NULL; - - // Return error if library not loaded - if(_sspi_security_dll == NULL) return NULL; - - #ifdef _UNICODE - // Get the address of the InitSecurityInterface function. - InitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress ( - _sspi_secur32_dll, - TEXT("InitSecurityInterfaceW")); - #else - // Get the address of the InitSecurityInterface function. - InitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress ( - _sspi_secur32_dll, - TEXT("InitSecurityInterfaceA")); - #endif - - if(!InitSecurityInterface) { - printf (TEXT("Failed in getting the function address, Error: %x"), GetLastError ()); - return NULL; - } - - // Use InitSecurityInterface to get the function table. - pSecurityInterface = (*InitSecurityInterface)(); - - if(!pSecurityInterface) { - printf (TEXT("Failed in getting the function table, Error: %x"), GetLastError ()); - return NULL; - } - - return pSecurityInterface; -} - -/** - * Load security.dll dynamically - */ -int load_library() { - DWORD err; - // Load the library - _sspi_security_dll = LoadLibrary("security.dll"); - - // Check if the library loaded - if(_sspi_security_dll == NULL) { - err = GetLastError(); - return err; - } - - // Load the library - _sspi_secur32_dll = LoadLibrary("secur32.dll"); - - // Check if the library loaded - if(_sspi_secur32_dll == NULL) { - err = GetLastError(); - return err; - } - - return 0; -} \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos_sspi.h b/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos_sspi.h deleted file mode 100644 index a3008dc..0000000 --- a/node_modules/mongodb/node_modules/kerberos/lib/win32/kerberos_sspi.h +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef SSPI_C_H -#define SSPI_C_H - -#define SECURITY_WIN32 1 - -#include -#include - -/** - * Encrypt A Message - */ -SECURITY_STATUS SEC_ENTRY _sspi_EncryptMessage(PCtxtHandle phContext, unsigned long fQOP, PSecBufferDesc pMessage, unsigned long MessageSeqNo); - -typedef DWORD (WINAPI *encryptMessage_fn)(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo); - -/** - * Acquire Credentials - */ -SECURITY_STATUS SEC_ENTRY _sspi_AcquireCredentialsHandle( - LPSTR pszPrincipal, // Name of principal - LPSTR pszPackage, // Name of package - unsigned long fCredentialUse, // Flags indicating use - void * pvLogonId, // Pointer to logon ID - void * pAuthData, // Package specific data - SEC_GET_KEY_FN pGetKeyFn, // Pointer to GetKey() func - void * pvGetKeyArgument, // Value to pass to GetKey() - PCredHandle phCredential, // (out) Cred Handle - PTimeStamp ptsExpiry // (out) Lifetime (optional) -); - -typedef DWORD (WINAPI *acquireCredentialsHandle_fn)( - LPSTR pszPrincipal, LPSTR pszPackage, unsigned long fCredentialUse, - void * pvLogonId, void * pAuthData, SEC_GET_KEY_FN pGetKeyFn, void * pvGetKeyArgument, - PCredHandle phCredential, PTimeStamp ptsExpiry - ); - -/** - * Delete Security Context - */ -SECURITY_STATUS SEC_ENTRY _sspi_DeleteSecurityContext( - PCtxtHandle phContext // Context to delete -); - -typedef DWORD (WINAPI *deleteSecurityContext_fn)(PCtxtHandle phContext); - -/** - * Decrypt Message - */ -SECURITY_STATUS SEC_ENTRY _sspi_DecryptMessage( - PCtxtHandle phContext, - PSecBufferDesc pMessage, - unsigned long MessageSeqNo, - unsigned long pfQOP -); - -typedef DWORD (WINAPI *decryptMessage_fn)( - PCtxtHandle phContext, PSecBufferDesc pMessage, unsigned long MessageSeqNo, unsigned long pfQOP); - -/** - * Initialize Security Context - */ -SECURITY_STATUS SEC_ENTRY _sspi_initializeSecurityContext( - PCredHandle phCredential, // Cred to base context - PCtxtHandle phContext, // Existing context (OPT) - LPSTR pszTargetName, // Name of target - unsigned long fContextReq, // Context Requirements - unsigned long Reserved1, // Reserved, MBZ - unsigned long TargetDataRep, // Data rep of target - PSecBufferDesc pInput, // Input Buffers - unsigned long Reserved2, // Reserved, MBZ - PCtxtHandle phNewContext, // (out) New Context handle - PSecBufferDesc pOutput, // (inout) Output Buffers - unsigned long * pfContextAttr, // (out) Context attrs - PTimeStamp ptsExpiry // (out) Life span (OPT) -); - -typedef DWORD (WINAPI *initializeSecurityContext_fn)( - PCredHandle phCredential, PCtxtHandle phContext, LPSTR pszTargetName, unsigned long fContextReq, - unsigned long Reserved1, unsigned long TargetDataRep, PSecBufferDesc pInput, unsigned long Reserved2, - PCtxtHandle phNewContext, PSecBufferDesc pOutput, unsigned long * pfContextAttr, PTimeStamp ptsExpiry); - -/** - * Query Context Attributes - */ -SECURITY_STATUS SEC_ENTRY _sspi_QueryContextAttributes( - PCtxtHandle phContext, // Context to query - unsigned long ulAttribute, // Attribute to query - void * pBuffer // Buffer for attributes -); - -typedef DWORD (WINAPI *queryContextAttributes_fn)( - PCtxtHandle phContext, unsigned long ulAttribute, void * pBuffer); - -/** - * InitSecurityInterface - */ -PSecurityFunctionTable _ssip_InitSecurityInterface(); - -typedef DWORD (WINAPI *initSecurityInterface_fn) (); - -/** - * Load security.dll dynamically - */ -int load_library(); - -#endif \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/worker.cc b/node_modules/mongodb/node_modules/kerberos/lib/win32/worker.cc deleted file mode 100644 index e7a472f..0000000 --- a/node_modules/mongodb/node_modules/kerberos/lib/win32/worker.cc +++ /dev/null @@ -1,7 +0,0 @@ -#include "worker.h" - -Worker::Worker() { -} - -Worker::~Worker() { -} \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/worker.h b/node_modules/mongodb/node_modules/kerberos/lib/win32/worker.h deleted file mode 100644 index fb62b55..0000000 --- a/node_modules/mongodb/node_modules/kerberos/lib/win32/worker.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef WORKER_H_ -#define WORKER_H_ - -#include -#include -#include -#include "nan.h" - -using namespace node; -using namespace v8; - -class Worker { - public: - Worker(); - virtual ~Worker(); - - // libuv's request struct. - uv_work_t request; - // Callback - NanCallback *callback; - // Parameters - void *parameters; - // Results - void *return_value; - // Did we raise an error - bool error; - // The error message - char *error_message; - // Error code if not message - int error_code; - // Any return code - int return_code; - // Method we are going to fire - void (*execute)(Worker *worker); - Handle (*mapper)(Worker *worker); -}; - -#endif // WORKER_H_ diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.cc b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.cc deleted file mode 100644 index 6dea93a..0000000 --- a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.cc +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "security_buffer.h" - -using namespace node; - -Persistent SecurityBuffer::constructor_template; - -SecurityBuffer::SecurityBuffer(uint32_t security_type, size_t size) : ObjectWrap() { - this->size = size; - this->data = calloc(size, sizeof(char)); - this->security_type = security_type; - // Set up the data in the sec_buffer - this->sec_buffer.BufferType = security_type; - this->sec_buffer.cbBuffer = (unsigned long)size; - this->sec_buffer.pvBuffer = this->data; -} - -SecurityBuffer::SecurityBuffer(uint32_t security_type, size_t size, void *data) : ObjectWrap() { - this->size = size; - this->data = data; - this->security_type = security_type; - // Set up the data in the sec_buffer - this->sec_buffer.BufferType = security_type; - this->sec_buffer.cbBuffer = (unsigned long)size; - this->sec_buffer.pvBuffer = this->data; -} - -SecurityBuffer::~SecurityBuffer() { - free(this->data); -} - -NAN_METHOD(SecurityBuffer::New) { - NanScope(); - SecurityBuffer *security_obj; - - if(args.Length() != 2) - return NanThrowError("Two parameters needed integer buffer type and [32 bit integer/Buffer] required"); - - if(!args[0]->IsInt32()) - return NanThrowError("Two parameters needed integer buffer type and [32 bit integer/Buffer] required"); - - if(!args[1]->IsInt32() && !Buffer::HasInstance(args[1])) - return NanThrowError("Two parameters needed integer buffer type and [32 bit integer/Buffer] required"); - - // Unpack buffer type - uint32_t buffer_type = args[0]->ToUint32()->Value(); - - // If we have an integer - if(args[1]->IsInt32()) { - security_obj = new SecurityBuffer(buffer_type, args[1]->ToUint32()->Value()); - } else { - // Get the length of the Buffer - size_t length = Buffer::Length(args[1]->ToObject()); - // Allocate space for the internal void data pointer - void *data = calloc(length, sizeof(char)); - // Write the data to out of V8 heap space - memcpy(data, Buffer::Data(args[1]->ToObject()), length); - // Create new SecurityBuffer - security_obj = new SecurityBuffer(buffer_type, length, data); - } - - // Wrap it - security_obj->Wrap(args.This()); - // Return the object - NanReturnValue(args.This()); -} - -NAN_METHOD(SecurityBuffer::ToBuffer) { - NanScope(); - // Unpack the Security Buffer object - SecurityBuffer *security_obj = ObjectWrap::Unwrap(args.This()); - // Create a Buffer - Local buffer = NanNewBufferHandle((char *)security_obj->data, (size_t)security_obj->size); - // Return the buffer - NanReturnValue(buffer); -} - -void SecurityBuffer::Initialize(Handle target) { - // Grab the scope of the call from Node - NanScope(); - - // Define a new function template - Local t = NanNew(New); - t->InstanceTemplate()->SetInternalFieldCount(1); - t->SetClassName(NanNew("SecurityBuffer")); - - // Class methods - NODE_SET_PROTOTYPE_METHOD(t, "toBuffer", ToBuffer); - - // Set persistent - NanAssignPersistent(constructor_template, t); - - // Set the symbol - target->ForceSet(NanNew("SecurityBuffer"), t->GetFunction()); -} diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.h b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.h deleted file mode 100644 index 8958820..0000000 --- a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef SECURITY_BUFFER_H -#define SECURITY_BUFFER_H - -#include -#include -#include - -#define SECURITY_WIN32 1 - -#include -#include -#include "nan.h" - -using namespace v8; -using namespace node; - -class SecurityBuffer : public ObjectWrap { - public: - SecurityBuffer(uint32_t security_type, size_t size); - SecurityBuffer(uint32_t security_type, size_t size, void *data); - ~SecurityBuffer(); - - // Internal values - void *data; - size_t size; - uint32_t security_type; - SecBuffer sec_buffer; - - // Has instance check - static inline bool HasInstance(Handle val) { - if (!val->IsObject()) return false; - Local obj = val->ToObject(); - return NanNew(constructor_template)->HasInstance(obj); - }; - - // Functions available from V8 - static void Initialize(Handle target); - static NAN_METHOD(ToBuffer); - - // Constructor used for creating new Long objects from C++ - static Persistent constructor_template; - - private: - static NAN_METHOD(New); -}; - -#endif \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.js b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.js deleted file mode 100644 index 4996163..0000000 --- a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer.js +++ /dev/null @@ -1,12 +0,0 @@ -var SecurityBufferNative = require('../../../build/Release/kerberos').SecurityBuffer; - -// Add some attributes -SecurityBufferNative.VERSION = 0; -SecurityBufferNative.EMPTY = 0; -SecurityBufferNative.DATA = 1; -SecurityBufferNative.TOKEN = 2; -SecurityBufferNative.PADDING = 9; -SecurityBufferNative.STREAM = 10; - -// Export the modified class -exports.SecurityBuffer = SecurityBufferNative; \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.cc b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.cc deleted file mode 100644 index 1c335df..0000000 --- a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.cc +++ /dev/null @@ -1,185 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define SECURITY_WIN32 1 - -#include "security_buffer_descriptor.h" -#include "security_buffer.h" - -Persistent SecurityBufferDescriptor::constructor_template; - -SecurityBufferDescriptor::SecurityBufferDescriptor() : ObjectWrap() { -} - -SecurityBufferDescriptor::SecurityBufferDescriptor(Persistent arrayObjectPersistent) : ObjectWrap() { - SecurityBuffer *security_obj = NULL; - // Get the Local value - Local arrayObject = NanNew(arrayObjectPersistent); - - // Safe reference to array - this->arrayObject = arrayObject; - - // Unpack the array and ensure we have a valid descriptor - this->secBufferDesc.cBuffers = arrayObject->Length(); - this->secBufferDesc.ulVersion = SECBUFFER_VERSION; - - if(arrayObject->Length() == 1) { - // Unwrap the buffer - security_obj = ObjectWrap::Unwrap(arrayObject->Get(0)->ToObject()); - // Assign the buffer - this->secBufferDesc.pBuffers = &security_obj->sec_buffer; - } else { - this->secBufferDesc.pBuffers = new SecBuffer[arrayObject->Length()]; - this->secBufferDesc.cBuffers = arrayObject->Length(); - - // Assign the buffers - for(uint32_t i = 0; i < arrayObject->Length(); i++) { - security_obj = ObjectWrap::Unwrap(arrayObject->Get(i)->ToObject()); - this->secBufferDesc.pBuffers[i].BufferType = security_obj->sec_buffer.BufferType; - this->secBufferDesc.pBuffers[i].pvBuffer = security_obj->sec_buffer.pvBuffer; - this->secBufferDesc.pBuffers[i].cbBuffer = security_obj->sec_buffer.cbBuffer; - } - } -} - -SecurityBufferDescriptor::~SecurityBufferDescriptor() { -} - -size_t SecurityBufferDescriptor::bufferSize() { - SecurityBuffer *security_obj = NULL; - - if(this->secBufferDesc.cBuffers == 1) { - security_obj = ObjectWrap::Unwrap(arrayObject->Get(0)->ToObject()); - return security_obj->size; - } else { - int bytesToAllocate = 0; - - for(unsigned int i = 0; i < this->secBufferDesc.cBuffers; i++) { - bytesToAllocate += this->secBufferDesc.pBuffers[i].cbBuffer; - } - - // Return total size - return bytesToAllocate; - } -} - -char *SecurityBufferDescriptor::toBuffer() { - SecurityBuffer *security_obj = NULL; - char *data = NULL; - - if(this->secBufferDesc.cBuffers == 1) { - security_obj = ObjectWrap::Unwrap(arrayObject->Get(0)->ToObject()); - data = (char *)malloc(security_obj->size * sizeof(char)); - memcpy(data, security_obj->data, security_obj->size); - } else { - size_t bytesToAllocate = this->bufferSize(); - char *data = (char *)calloc(bytesToAllocate, sizeof(char)); - int offset = 0; - - for(unsigned int i = 0; i < this->secBufferDesc.cBuffers; i++) { - memcpy((data + offset), this->secBufferDesc.pBuffers[i].pvBuffer, this->secBufferDesc.pBuffers[i].cbBuffer); - offset +=this->secBufferDesc.pBuffers[i].cbBuffer; - } - - // Return the data - return data; - } - - return data; -} - -NAN_METHOD(SecurityBufferDescriptor::New) { - NanScope(); - SecurityBufferDescriptor *security_obj; - Persistent arrayObject; - - if(args.Length() != 1) - return NanThrowError("There must be 1 argument passed in where the first argument is a [int32 or an Array of SecurityBuffers]"); - - if(!args[0]->IsInt32() && !args[0]->IsArray()) - return NanThrowError("There must be 1 argument passed in where the first argument is a [int32 or an Array of SecurityBuffers]"); - - if(args[0]->IsArray()) { - Handle array = Handle::Cast(args[0]); - // Iterate over all items and ensure we the right type - for(uint32_t i = 0; i < array->Length(); i++) { - if(!SecurityBuffer::HasInstance(array->Get(i))) { - return NanThrowError("There must be 1 argument passed in where the first argument is a [int32 or an Array of SecurityBuffers]"); - } - } - } - - // We have a single integer - if(args[0]->IsInt32()) { - // Create new SecurityBuffer instance - Local argv[] = {NanNew(0x02), args[0]}; - Handle security_buffer = NanNew(SecurityBuffer::constructor_template)->GetFunction()->NewInstance(2, argv); - // Create a new array - Local array = NanNew(1); - // Set the first value - array->Set(0, security_buffer); - - // Create persistent handle - Persistent persistenHandler; - NanAssignPersistent(persistenHandler, array); - - // Create descriptor - security_obj = new SecurityBufferDescriptor(persistenHandler); - } else { - // Create a persistent handler - Persistent persistenHandler; - NanAssignPersistent(persistenHandler, Handle::Cast(args[0])); - // Create a descriptor - security_obj = new SecurityBufferDescriptor(persistenHandler); - } - - // Wrap it - security_obj->Wrap(args.This()); - // Return the object - NanReturnValue(args.This()); -} - -NAN_METHOD(SecurityBufferDescriptor::ToBuffer) { - NanScope(); - - // Unpack the Security Buffer object - SecurityBufferDescriptor *security_obj = ObjectWrap::Unwrap(args.This()); - - // Get the buffer - char *buffer_data = security_obj->toBuffer(); - size_t buffer_size = security_obj->bufferSize(); - - // Create a Buffer - Local buffer = NanNewBufferHandle(buffer_data, buffer_size); - - // Return the buffer - NanReturnValue(buffer); -} - -void SecurityBufferDescriptor::Initialize(Handle target) { - // Grab the scope of the call from Node - NanScope(); - - // Define a new function template - Local t = NanNew(New); - t->InstanceTemplate()->SetInternalFieldCount(1); - t->SetClassName(NanNew("SecurityBufferDescriptor")); - - // Class methods - NODE_SET_PROTOTYPE_METHOD(t, "toBuffer", ToBuffer); - - // Set persistent - NanAssignPersistent(constructor_template, t); - - // Set the symbol - target->ForceSet(NanNew("SecurityBufferDescriptor"), t->GetFunction()); -} diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.h b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.h deleted file mode 100644 index cfe18cf..0000000 --- a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef SECURITY_BUFFER_DESCRIPTOR_H -#define SECURITY_BUFFER_DESCRIPTOR_H - -#include -#include -#include - -#include -#include -#include "nan.h" - -using namespace v8; -using namespace node; - -class SecurityBufferDescriptor : public ObjectWrap { - public: - Local arrayObject; - SecBufferDesc secBufferDesc; - - SecurityBufferDescriptor(); - SecurityBufferDescriptor(Persistent arrayObjectPersistent); - ~SecurityBufferDescriptor(); - - // Has instance check - static inline bool HasInstance(Handle val) { - if (!val->IsObject()) return false; - Local obj = val->ToObject(); - return NanNew(constructor_template)->HasInstance(obj); - }; - - char *toBuffer(); - size_t bufferSize(); - - // Functions available from V8 - static void Initialize(Handle target); - static NAN_METHOD(ToBuffer); - - // Constructor used for creating new Long objects from C++ - static Persistent constructor_template; - - private: - static NAN_METHOD(New); -}; - -#endif \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.js b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.js deleted file mode 100644 index 9421392..0000000 --- a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_buffer_descriptor.js +++ /dev/null @@ -1,3 +0,0 @@ -var SecurityBufferDescriptorNative = require('../../../build/Release/kerberos').SecurityBufferDescriptor; -// Export the modified class -exports.SecurityBufferDescriptor = SecurityBufferDescriptorNative; \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.cc b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.cc deleted file mode 100644 index 7ff9ae5..0000000 --- a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.cc +++ /dev/null @@ -1,871 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "security_context.h" -#include "security_buffer_descriptor.h" - -#ifndef ARRAY_SIZE -# define ARRAY_SIZE(a) (sizeof((a)) / sizeof((a)[0])) -#endif - -static LPSTR DisplaySECError(DWORD ErrCode); - -// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -// UV Lib callbacks -// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -static void Process(uv_work_t* work_req) { - // Grab the worker - Worker *worker = static_cast(work_req->data); - // Execute the worker code - worker->execute(worker); -} - -static void After(uv_work_t* work_req) { - // Grab the scope of the call from Node - NanScope(); - - // Get the worker reference - Worker *worker = static_cast(work_req->data); - - // If we have an error - if(worker->error) { - Local err = v8::Exception::Error(NanNew(worker->error_message)); - Local obj = err->ToObject(); - obj->Set(NanNew("code"), NanNew(worker->error_code)); - Local args[2] = { err, NanNull() }; - // Execute the error - v8::TryCatch try_catch; - - // Call the callback - worker->callback->Call(ARRAY_SIZE(args), args); - - // If we have an exception handle it as a fatalexception - if (try_catch.HasCaught()) { - node::FatalException(try_catch); - } - } else { - // // Map the data - Handle result = worker->mapper(worker); - // Set up the callback with a null first - Handle args[2] = { NanNull(), result}; - // Wrap the callback function call in a TryCatch so that we can call - // node's FatalException afterwards. This makes it possible to catch - // the exception from JavaScript land using the - // process.on('uncaughtException') event. - v8::TryCatch try_catch; - - // Call the callback - worker->callback->Call(ARRAY_SIZE(args), args); - - // If we have an exception handle it as a fatalexception - if (try_catch.HasCaught()) { - node::FatalException(try_catch); - } - } - - // Clean up the memory - delete worker->callback; - delete worker; -} - -Persistent SecurityContext::constructor_template; - -SecurityContext::SecurityContext() : ObjectWrap() { -} - -SecurityContext::~SecurityContext() { - if(this->hasContext) { - _sspi_DeleteSecurityContext(&this->m_Context); - } -} - -NAN_METHOD(SecurityContext::New) { - NanScope(); - - PSecurityFunctionTable pSecurityInterface = NULL; - DWORD dwNumOfPkgs; - SECURITY_STATUS status; - - // Create code object - SecurityContext *security_obj = new SecurityContext(); - // Get security table interface - pSecurityInterface = _ssip_InitSecurityInterface(); - // Call the security interface - status = (*pSecurityInterface->EnumerateSecurityPackages)( - &dwNumOfPkgs, - &security_obj->m_PkgInfo); - if(status != SEC_E_OK) { - printf(TEXT("Failed in retrieving security packages, Error: %x"), GetLastError()); - return NanThrowError("Failed in retrieving security packages"); - } - - // Wrap it - security_obj->Wrap(args.This()); - // Return the object - NanReturnValue(args.This()); -} - -// -// Async InitializeContext -// -typedef struct SecurityContextStaticInitializeCall { - char *service_principal_name_str; - char *decoded_input_str; - int decoded_input_str_length; - SecurityContext *context; -} SecurityContextStaticInitializeCall; - -static void _initializeContext(Worker *worker) { - // Status of operation - SECURITY_STATUS status; - BYTE *out_bound_data_str = NULL; - SecurityContextStaticInitializeCall *call = (SecurityContextStaticInitializeCall *)worker->parameters; - - // Structures used for c calls - SecBufferDesc ibd, obd; - SecBuffer ib, ob; - - // - // Prepare data structure for returned data from SSPI - ob.BufferType = SECBUFFER_TOKEN; - ob.cbBuffer = call->context->m_PkgInfo->cbMaxToken; - // Allocate space for return data - out_bound_data_str = new BYTE[ob.cbBuffer + sizeof(DWORD)]; - ob.pvBuffer = out_bound_data_str; - // prepare buffer description - obd.cBuffers = 1; - obd.ulVersion = SECBUFFER_VERSION; - obd.pBuffers = &ob; - - // - // Prepare the data we are passing to the SSPI method - if(call->decoded_input_str_length > 0) { - ib.BufferType = SECBUFFER_TOKEN; - ib.cbBuffer = call->decoded_input_str_length; - ib.pvBuffer = call->decoded_input_str; - // prepare buffer description - ibd.cBuffers = 1; - ibd.ulVersion = SECBUFFER_VERSION; - ibd.pBuffers = &ib; - } - - // Perform initialization step - status = _sspi_initializeSecurityContext( - &call->context->security_credentials->m_Credentials - , NULL - , const_cast(call->service_principal_name_str) - , 0x02 // MUTUAL - , 0 - , 0 // Network - , call->decoded_input_str_length > 0 ? &ibd : NULL - , 0 - , &call->context->m_Context - , &obd - , &call->context->CtxtAttr - , &call->context->Expiration - ); - - // If we have a ok or continue let's prepare the result - if(status == SEC_E_OK - || status == SEC_I_COMPLETE_NEEDED - || status == SEC_I_CONTINUE_NEEDED - || status == SEC_I_COMPLETE_AND_CONTINUE - ) { - call->context->hasContext = true; - call->context->payload = base64_encode((const unsigned char *)ob.pvBuffer, ob.cbBuffer); - - // Set the context - worker->return_code = status; - worker->return_value = call->context; - } else if(status == SEC_E_INSUFFICIENT_MEMORY) { - worker->error = TRUE; - worker->error_code = status; - worker->error_message = "SEC_E_INSUFFICIENT_MEMORY There is not enough memory available to complete the requested action."; - } else if(status == SEC_E_INTERNAL_ERROR) { - worker->error = TRUE; - worker->error_code = status; - worker->error_message = "SEC_E_INTERNAL_ERROR An error occurred that did not map to an SSPI error code."; - } else if(status == SEC_E_INVALID_HANDLE) { - worker->error = TRUE; - worker->error_code = status; - worker->error_message = "SEC_E_INVALID_HANDLE The handle passed to the function is not valid."; - } else if(status == SEC_E_INVALID_TOKEN) { - worker->error = TRUE; - worker->error_code = status; - worker->error_message = "SEC_E_INVALID_TOKEN The error is due to a malformed input token, such as a token corrupted in transit, a token of incorrect size, or a token passed into the wrong security package. Passing a token to the wrong package can happen if the client and server did not negotiate the proper security package."; - } else if(status == SEC_E_LOGON_DENIED) { - worker->error = TRUE; - worker->error_code = status; - worker->error_message = "SEC_E_LOGON_DENIED The logon failed."; - } else if(status == SEC_E_NO_AUTHENTICATING_AUTHORITY) { - worker->error = TRUE; - worker->error_code = status; - worker->error_message = "SEC_E_NO_AUTHENTICATING_AUTHORITY No authority could be contacted for authentication. The domain name of the authenticating party could be wrong, the domain could be unreachable, or there might have been a trust relationship failure."; - } else if(status == SEC_E_NO_CREDENTIALS) { - worker->error = TRUE; - worker->error_code = status; - worker->error_message = "SEC_E_NO_CREDENTIALS No credentials are available in the security package."; - } else if(status == SEC_E_TARGET_UNKNOWN) { - worker->error = TRUE; - worker->error_code = status; - worker->error_message = "SEC_E_TARGET_UNKNOWN The target was not recognized."; - } else if(status == SEC_E_UNSUPPORTED_FUNCTION) { - worker->error = TRUE; - worker->error_code = status; - worker->error_message = "SEC_E_UNSUPPORTED_FUNCTION A context attribute flag that is not valid (ISC_REQ_DELEGATE or ISC_REQ_PROMPT_FOR_CREDS) was specified in the fContextReq parameter."; - } else if(status == SEC_E_WRONG_PRINCIPAL) { - worker->error = TRUE; - worker->error_code = status; - worker->error_message = "SEC_E_WRONG_PRINCIPAL The principal that received the authentication request is not the same as the one passed into the pszTargetName parameter. This indicates a failure in mutual authentication."; - } else { - worker->error = TRUE; - worker->error_code = status; - worker->error_message = DisplaySECError(status); - } - - // Clean up data - if(call->decoded_input_str != NULL) free(call->decoded_input_str); - if(call->service_principal_name_str != NULL) free(call->service_principal_name_str); -} - -static Handle _map_initializeContext(Worker *worker) { - // Unwrap the security context - SecurityContext *context = (SecurityContext *)worker->return_value; - // Return the value - return NanObjectWrapHandle(context); -} - -NAN_METHOD(SecurityContext::InitializeContext) { - NanScope(); - char *service_principal_name_str = NULL, *input_str = NULL, *decoded_input_str = NULL; - int decoded_input_str_length = NULL; - // Store reference to security credentials - SecurityCredentials *security_credentials = NULL; - - // We need 3 parameters - if(args.Length() != 4) - return NanThrowError("Initialize must be called with [credential:SecurityCredential, servicePrincipalName:string, input:string, callback:function]"); - - // First parameter must be an instance of SecurityCredentials - if(!SecurityCredentials::HasInstance(args[0])) - return NanThrowError("First parameter for Initialize must be an instance of SecurityCredentials"); - - // Second parameter must be a string - if(!args[1]->IsString()) - return NanThrowError("Second parameter for Initialize must be a string"); - - // Third parameter must be a base64 encoded string - if(!args[2]->IsString()) - return NanThrowError("Second parameter for Initialize must be a string"); - - // Third parameter must be a callback - if(!args[3]->IsFunction()) - return NanThrowError("Third parameter for Initialize must be a callback function"); - - // Let's unpack the values - Local service_principal_name = args[1]->ToString(); - service_principal_name_str = (char *)calloc(service_principal_name->Utf8Length() + 1, sizeof(char)); - service_principal_name->WriteUtf8(service_principal_name_str); - - // Unpack the user name - Local input = args[2]->ToString(); - - if(input->Utf8Length() > 0) { - input_str = (char *)calloc(input->Utf8Length() + 1, sizeof(char)); - input->WriteUtf8(input_str); - - // Now let's get the base64 decoded string - decoded_input_str = (char *)base64_decode(input_str, &decoded_input_str_length); - // Free original allocation - free(input_str); - } - - // Unpack the Security credentials - security_credentials = ObjectWrap::Unwrap(args[0]->ToObject()); - // Create Security context instance - Local security_context_value = constructor_template->GetFunction()->NewInstance(); - // Unwrap the security context - SecurityContext *security_context = ObjectWrap::Unwrap(security_context_value); - // Add a reference to the security_credentials - security_context->security_credentials = security_credentials; - - // Build the call function - SecurityContextStaticInitializeCall *call = (SecurityContextStaticInitializeCall *)calloc(1, sizeof(SecurityContextStaticInitializeCall)); - call->context = security_context; - call->decoded_input_str = decoded_input_str; - call->decoded_input_str_length = decoded_input_str_length; - call->service_principal_name_str = service_principal_name_str; - - // Callback - Local callback = Local::Cast(args[3]); - - // Let's allocate some space - Worker *worker = new Worker(); - worker->error = false; - worker->request.data = worker; - worker->callback = new NanCallback(callback); - worker->parameters = call; - worker->execute = _initializeContext; - worker->mapper = _map_initializeContext; - - // Schedule the worker with lib_uv - uv_queue_work(uv_default_loop(), &worker->request, Process, (uv_after_work_cb)After); - - // Return no value as it's callback based - NanReturnValue(NanUndefined()); -} - -NAN_GETTER(SecurityContext::PayloadGetter) { - NanScope(); - // Unpack the context object - SecurityContext *context = ObjectWrap::Unwrap(args.This()); - // Return the low bits - NanReturnValue(NanNew(context->payload)); -} - -NAN_GETTER(SecurityContext::HasContextGetter) { - NanScope(); - // Unpack the context object - SecurityContext *context = ObjectWrap::Unwrap(args.This()); - // Return the low bits - NanReturnValue(NanNew(context->hasContext)); -} - -// -// Async InitializeContextStep -// -typedef struct SecurityContextStepStaticInitializeCall { - char *service_principal_name_str; - char *decoded_input_str; - int decoded_input_str_length; - SecurityContext *context; -} SecurityContextStepStaticInitializeCall; - -static void _initializeContextStep(Worker *worker) { - // Outbound data array - BYTE *out_bound_data_str = NULL; - // Status of operation - SECURITY_STATUS status; - // Unpack data - SecurityContextStepStaticInitializeCall *call = (SecurityContextStepStaticInitializeCall *)worker->parameters; - SecurityContext *context = call->context; - // Structures used for c calls - SecBufferDesc ibd, obd; - SecBuffer ib, ob; - - // - // Prepare data structure for returned data from SSPI - ob.BufferType = SECBUFFER_TOKEN; - ob.cbBuffer = context->m_PkgInfo->cbMaxToken; - // Allocate space for return data - out_bound_data_str = new BYTE[ob.cbBuffer + sizeof(DWORD)]; - ob.pvBuffer = out_bound_data_str; - // prepare buffer description - obd.cBuffers = 1; - obd.ulVersion = SECBUFFER_VERSION; - obd.pBuffers = &ob; - - // - // Prepare the data we are passing to the SSPI method - if(call->decoded_input_str_length > 0) { - ib.BufferType = SECBUFFER_TOKEN; - ib.cbBuffer = call->decoded_input_str_length; - ib.pvBuffer = call->decoded_input_str; - // prepare buffer description - ibd.cBuffers = 1; - ibd.ulVersion = SECBUFFER_VERSION; - ibd.pBuffers = &ib; - } - - // Perform initialization step - status = _sspi_initializeSecurityContext( - &context->security_credentials->m_Credentials - , context->hasContext == true ? &context->m_Context : NULL - , const_cast(call->service_principal_name_str) - , 0x02 // MUTUAL - , 0 - , 0 // Network - , call->decoded_input_str_length ? &ibd : NULL - , 0 - , &context->m_Context - , &obd - , &context->CtxtAttr - , &context->Expiration - ); - - // If we have a ok or continue let's prepare the result - if(status == SEC_E_OK - || status == SEC_I_COMPLETE_NEEDED - || status == SEC_I_CONTINUE_NEEDED - || status == SEC_I_COMPLETE_AND_CONTINUE - ) { - // Set the new payload - if(context->payload != NULL) free(context->payload); - context->payload = base64_encode((const unsigned char *)ob.pvBuffer, ob.cbBuffer); - worker->return_code = status; - worker->return_value = context; - } else { - worker->error = TRUE; - worker->error_code = status; - worker->error_message = DisplaySECError(status); - } - - // Clean up data - if(call->decoded_input_str != NULL) free(call->decoded_input_str); - if(call->service_principal_name_str != NULL) free(call->service_principal_name_str); -} - -static Handle _map_initializeContextStep(Worker *worker) { - // Unwrap the security context - SecurityContext *context = (SecurityContext *)worker->return_value; - // Return the value - return NanObjectWrapHandle(context); -} - -NAN_METHOD(SecurityContext::InitalizeStep) { - NanScope(); - - char *service_principal_name_str = NULL, *input_str = NULL, *decoded_input_str = NULL; - int decoded_input_str_length = NULL; - - // We need 3 parameters - if(args.Length() != 3) - return NanThrowError("Initialize must be called with [servicePrincipalName:string, input:string, callback:function]"); - - // Second parameter must be a string - if(!args[0]->IsString()) - return NanThrowError("First parameter for Initialize must be a string"); - - // Third parameter must be a base64 encoded string - if(!args[1]->IsString()) - return NanThrowError("Second parameter for Initialize must be a string"); - - // Third parameter must be a base64 encoded string - if(!args[2]->IsFunction()) - return NanThrowError("Third parameter for Initialize must be a callback function"); - - // Let's unpack the values - Local service_principal_name = args[0]->ToString(); - service_principal_name_str = (char *)calloc(service_principal_name->Utf8Length() + 1, sizeof(char)); - service_principal_name->WriteUtf8(service_principal_name_str); - - // Unpack the user name - Local input = args[1]->ToString(); - - if(input->Utf8Length() > 0) { - input_str = (char *)calloc(input->Utf8Length() + 1, sizeof(char)); - input->WriteUtf8(input_str); - // Now let's get the base64 decoded string - decoded_input_str = (char *)base64_decode(input_str, &decoded_input_str_length); - // Free input string - free(input_str); - } - - // Unwrap the security context - SecurityContext *security_context = ObjectWrap::Unwrap(args.This()); - - // Create call structure - SecurityContextStepStaticInitializeCall *call = (SecurityContextStepStaticInitializeCall *)calloc(1, sizeof(SecurityContextStepStaticInitializeCall)); - call->context = security_context; - call->decoded_input_str = decoded_input_str; - call->decoded_input_str_length = decoded_input_str_length; - call->service_principal_name_str = service_principal_name_str; - - // Callback - Local callback = Local::Cast(args[2]); - - // Let's allocate some space - Worker *worker = new Worker(); - worker->error = false; - worker->request.data = worker; - worker->callback = new NanCallback(callback); - worker->parameters = call; - worker->execute = _initializeContextStep; - worker->mapper = _map_initializeContextStep; - - // Schedule the worker with lib_uv - uv_queue_work(uv_default_loop(), &worker->request, Process, (uv_after_work_cb)After); - - // Return no value as it's callback based - NanReturnValue(NanUndefined()); -} - -// -// Async EncryptMessage -// -typedef struct SecurityContextEncryptMessageCall { - SecurityContext *context; - SecurityBufferDescriptor *descriptor; - unsigned long flags; -} SecurityContextEncryptMessageCall; - -static void _encryptMessage(Worker *worker) { - SECURITY_STATUS status; - // Unpack call - SecurityContextEncryptMessageCall *call = (SecurityContextEncryptMessageCall *)worker->parameters; - // Unpack the security context - SecurityContext *context = call->context; - SecurityBufferDescriptor *descriptor = call->descriptor; - - // Let's execute encryption - status = _sspi_EncryptMessage( - &context->m_Context - , call->flags - , &descriptor->secBufferDesc - , 0 - ); - - // We've got ok - if(status == SEC_E_OK) { - int bytesToAllocate = (int)descriptor->bufferSize(); - // Free up existing payload - if(context->payload != NULL) free(context->payload); - // Save the payload - context->payload = base64_encode((unsigned char *)descriptor->toBuffer(), bytesToAllocate); - // Set result - worker->return_code = status; - worker->return_value = context; - } else { - worker->error = TRUE; - worker->error_code = status; - worker->error_message = DisplaySECError(status); - } -} - -static Handle _map_encryptMessage(Worker *worker) { - // Unwrap the security context - SecurityContext *context = (SecurityContext *)worker->return_value; - // Return the value - return NanObjectWrapHandle(context); -} - -NAN_METHOD(SecurityContext::EncryptMessage) { - NanScope(); - - if(args.Length() != 3) - return NanThrowError("EncryptMessage takes an instance of SecurityBufferDescriptor, an integer flag and a callback function"); - if(!SecurityBufferDescriptor::HasInstance(args[0])) - return NanThrowError("EncryptMessage takes an instance of SecurityBufferDescriptor, an integer flag and a callback function"); - if(!args[1]->IsUint32()) - return NanThrowError("EncryptMessage takes an instance of SecurityBufferDescriptor, an integer flag and a callback function"); - if(!args[2]->IsFunction()) - return NanThrowError("EncryptMessage takes an instance of SecurityBufferDescriptor, an integer flag and a callback function"); - - // Unpack the security context - SecurityContext *security_context = ObjectWrap::Unwrap(args.This()); - - // Unpack the descriptor - SecurityBufferDescriptor *descriptor = ObjectWrap::Unwrap(args[0]->ToObject()); - - // Create call structure - SecurityContextEncryptMessageCall *call = (SecurityContextEncryptMessageCall *)calloc(1, sizeof(SecurityContextEncryptMessageCall)); - call->context = security_context; - call->descriptor = descriptor; - call->flags = (unsigned long)args[1]->ToInteger()->Value(); - - // Callback - Local callback = Local::Cast(args[2]); - - // Let's allocate some space - Worker *worker = new Worker(); - worker->error = false; - worker->request.data = worker; - worker->callback = new NanCallback(callback); - worker->parameters = call; - worker->execute = _encryptMessage; - worker->mapper = _map_encryptMessage; - - // Schedule the worker with lib_uv - uv_queue_work(uv_default_loop(), &worker->request, Process, (uv_after_work_cb)After); - - // Return no value as it's callback based - NanReturnValue(NanUndefined()); -} - -// -// Async DecryptMessage -// -typedef struct SecurityContextDecryptMessageCall { - SecurityContext *context; - SecurityBufferDescriptor *descriptor; -} SecurityContextDecryptMessageCall; - -static void _decryptMessage(Worker *worker) { - unsigned long quality = 0; - SECURITY_STATUS status; - - // Unpack parameters - SecurityContextDecryptMessageCall *call = (SecurityContextDecryptMessageCall *)worker->parameters; - SecurityContext *context = call->context; - SecurityBufferDescriptor *descriptor = call->descriptor; - - // Let's execute encryption - status = _sspi_DecryptMessage( - &context->m_Context - , &descriptor->secBufferDesc - , 0 - , (unsigned long)&quality - ); - - // We've got ok - if(status == SEC_E_OK) { - int bytesToAllocate = (int)descriptor->bufferSize(); - // Free up existing payload - if(context->payload != NULL) free(context->payload); - // Save the payload - context->payload = base64_encode((unsigned char *)descriptor->toBuffer(), bytesToAllocate); - // Set return values - worker->return_code = status; - worker->return_value = context; - } else { - worker->error = TRUE; - worker->error_code = status; - worker->error_message = DisplaySECError(status); - } -} - -static Handle _map_decryptMessage(Worker *worker) { - // Unwrap the security context - SecurityContext *context = (SecurityContext *)worker->return_value; - // Return the value - return NanObjectWrapHandle(context); -} - -NAN_METHOD(SecurityContext::DecryptMessage) { - NanScope(); - - if(args.Length() != 2) - return NanThrowError("DecryptMessage takes an instance of SecurityBufferDescriptor and a callback function"); - if(!SecurityBufferDescriptor::HasInstance(args[0])) - return NanThrowError("DecryptMessage takes an instance of SecurityBufferDescriptor and a callback function"); - if(!args[1]->IsFunction()) - return NanThrowError("DecryptMessage takes an instance of SecurityBufferDescriptor and a callback function"); - - // Unpack the security context - SecurityContext *security_context = ObjectWrap::Unwrap(args.This()); - // Unpack the descriptor - SecurityBufferDescriptor *descriptor = ObjectWrap::Unwrap(args[0]->ToObject()); - // Create call structure - SecurityContextDecryptMessageCall *call = (SecurityContextDecryptMessageCall *)calloc(1, sizeof(SecurityContextDecryptMessageCall)); - call->context = security_context; - call->descriptor = descriptor; - - // Callback - Local callback = Local::Cast(args[1]); - - // Let's allocate some space - Worker *worker = new Worker(); - worker->error = false; - worker->request.data = worker; - worker->callback = new NanCallback(callback); - worker->parameters = call; - worker->execute = _decryptMessage; - worker->mapper = _map_decryptMessage; - - // Schedule the worker with lib_uv - uv_queue_work(uv_default_loop(), &worker->request, Process, (uv_after_work_cb)After); - - // Return no value as it's callback based - NanReturnValue(NanUndefined()); -} - -// -// Async QueryContextAttributes -// -typedef struct SecurityContextQueryContextAttributesCall { - SecurityContext *context; - uint32_t attribute; -} SecurityContextQueryContextAttributesCall; - -static void _queryContextAttributes(Worker *worker) { - SECURITY_STATUS status; - - // Cast to data structure - SecurityContextQueryContextAttributesCall *call = (SecurityContextQueryContextAttributesCall *)worker->parameters; - - // Allocate some space - SecPkgContext_Sizes *sizes = (SecPkgContext_Sizes *)calloc(1, sizeof(SecPkgContext_Sizes)); - // Let's grab the query context attribute - status = _sspi_QueryContextAttributes( - &call->context->m_Context, - call->attribute, - sizes - ); - - if(status == SEC_E_OK) { - worker->return_code = status; - worker->return_value = sizes; - } else { - worker->error = TRUE; - worker->error_code = status; - worker->error_message = DisplaySECError(status); - } -} - -static Handle _map_queryContextAttributes(Worker *worker) { - NanScope(); - - // Cast to data structure - SecurityContextQueryContextAttributesCall *call = (SecurityContextQueryContextAttributesCall *)worker->parameters; - // Unpack the attribute - uint32_t attribute = call->attribute; - - // Convert data - if(attribute == SECPKG_ATTR_SIZES) { - SecPkgContext_Sizes *sizes = (SecPkgContext_Sizes *)worker->return_value; - // Create object - Local value = Object::New(); - value->Set(String::New("maxToken"), Integer::New(sizes->cbMaxToken)); - value->Set(String::New("maxSignature"), Integer::New(sizes->cbMaxSignature)); - value->Set(String::New("blockSize"), Integer::New(sizes->cbBlockSize)); - value->Set(String::New("securityTrailer"), Integer::New(sizes->cbSecurityTrailer)); - NanReturnValue(value); - } - - // Return the value - NanReturnValue(NanNull()); -} - -NAN_METHOD(SecurityContext::QueryContextAttributes) { - NanScope(); - - if(args.Length() != 2) - return NanThrowError("QueryContextAttributes method takes a an integer Attribute specifier and a callback function"); - if(!args[0]->IsInt32()) - return NanThrowError("QueryContextAttributes method takes a an integer Attribute specifier and a callback function"); - if(!args[1]->IsFunction()) - return NanThrowError("QueryContextAttributes method takes a an integer Attribute specifier and a callback function"); - - // Unpack the security context - SecurityContext *security_context = ObjectWrap::Unwrap(args.This()); - - // Unpack the int value - uint32_t attribute = args[0]->ToInt32()->Value(); - - // Check that we have a supported attribute - if(attribute != SECPKG_ATTR_SIZES) - return NanThrowError("QueryContextAttributes only supports the SECPKG_ATTR_SIZES attribute"); - - // Create call structure - SecurityContextQueryContextAttributesCall *call = (SecurityContextQueryContextAttributesCall *)calloc(1, sizeof(SecurityContextQueryContextAttributesCall)); - call->attribute = attribute; - call->context = security_context; - - // Callback - Local callback = Local::Cast(args[1]); - - // Let's allocate some space - Worker *worker = new Worker(); - worker->error = false; - worker->request.data = worker; - worker->callback = new NanCallback(callback); - worker->parameters = call; - worker->execute = _queryContextAttributes; - worker->mapper = _map_queryContextAttributes; - - // Schedule the worker with lib_uv - uv_queue_work(uv_default_loop(), &worker->request, Process, (uv_after_work_cb)After); - - // Return no value as it's callback based - NanReturnValue(NanUndefined()); -} - -void SecurityContext::Initialize(Handle target) { - // Grab the scope of the call from Node - NanScope(); - - // Define a new function template - Local t = NanNew(New); - t->InstanceTemplate()->SetInternalFieldCount(1); - t->SetClassName(NanNew("SecurityContext")); - - // Class methods - NODE_SET_METHOD(t, "initialize", InitializeContext); - - // Set up method for the instance - NODE_SET_PROTOTYPE_METHOD(t, "initialize", InitalizeStep); - NODE_SET_PROTOTYPE_METHOD(t, "decryptMessage", DecryptMessage); - NODE_SET_PROTOTYPE_METHOD(t, "queryContextAttributes", QueryContextAttributes); - NODE_SET_PROTOTYPE_METHOD(t, "encryptMessage", EncryptMessage); - - // Get prototype - Local proto = t->PrototypeTemplate(); - - // Getter for the response - proto->SetAccessor(NanNew("payload"), SecurityContext::PayloadGetter); - proto->SetAccessor(NanNew("hasContext"), SecurityContext::HasContextGetter); - - // Set persistent - NanAssignPersistent(constructor_template, t); - - // Set the symbol - target->ForceSet(NanNew("SecurityContext"), t->GetFunction()); -} - -static LPSTR DisplaySECError(DWORD ErrCode) { - LPSTR pszName = NULL; // WinError.h - - switch(ErrCode) { - case SEC_E_BUFFER_TOO_SMALL: - pszName = "SEC_E_BUFFER_TOO_SMALL - The message buffer is too small. Used with the Digest SSP."; - break; - - case SEC_E_CRYPTO_SYSTEM_INVALID: - pszName = "SEC_E_CRYPTO_SYSTEM_INVALID - The cipher chosen for the security context is not supported. Used with the Digest SSP."; - break; - case SEC_E_INCOMPLETE_MESSAGE: - pszName = "SEC_E_INCOMPLETE_MESSAGE - The data in the input buffer is incomplete. The application needs to read more data from the server and call DecryptMessageSync (General) again."; - break; - - case SEC_E_INVALID_HANDLE: - pszName = "SEC_E_INVALID_HANDLE - A context handle that is not valid was specified in the phContext parameter. Used with the Digest and Schannel SSPs."; - break; - - case SEC_E_INVALID_TOKEN: - pszName = "SEC_E_INVALID_TOKEN - The buffers are of the wrong type or no buffer of type SECBUFFER_DATA was found. Used with the Schannel SSP."; - break; - - case SEC_E_MESSAGE_ALTERED: - pszName = "SEC_E_MESSAGE_ALTERED - The message has been altered. Used with the Digest and Schannel SSPs."; - break; - - case SEC_E_OUT_OF_SEQUENCE: - pszName = "SEC_E_OUT_OF_SEQUENCE - The message was not received in the correct sequence."; - break; - - case SEC_E_QOP_NOT_SUPPORTED: - pszName = "SEC_E_QOP_NOT_SUPPORTED - Neither confidentiality nor integrity are supported by the security context. Used with the Digest SSP."; - break; - - case SEC_I_CONTEXT_EXPIRED: - pszName = "SEC_I_CONTEXT_EXPIRED - The message sender has finished using the connection and has initiated a shutdown."; - break; - - case SEC_I_RENEGOTIATE: - pszName = "SEC_I_RENEGOTIATE - The remote party requires a new handshake sequence or the application has just initiated a shutdown."; - break; - - case SEC_E_ENCRYPT_FAILURE: - pszName = "SEC_E_ENCRYPT_FAILURE - The specified data could not be encrypted."; - break; - - case SEC_E_DECRYPT_FAILURE: - pszName = "SEC_E_DECRYPT_FAILURE - The specified data could not be decrypted."; - break; - case -1: - pszName = "Failed to load security.dll library"; - break; - } - - return pszName; -} - diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.h b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.h deleted file mode 100644 index cb7f331..0000000 --- a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.h +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef SECURITY_CONTEXT_H -#define SECURITY_CONTEXT_H - -#include -#include -#include - -#define SECURITY_WIN32 1 - -#include -#include -#include "security_credentials.h" -#include "../worker.h" -#include "nan.h" - -extern "C" { - #include "../kerberos_sspi.h" - #include "../base64.h" -} - -using namespace v8; -using namespace node; - -class SecurityContext : public ObjectWrap { - public: - SecurityContext(); - ~SecurityContext(); - - // Security info package - PSecPkgInfo m_PkgInfo; - // Do we have a context - bool hasContext; - // Reference to security credentials - SecurityCredentials *security_credentials; - // Security context - CtxtHandle m_Context; - // Attributes - DWORD CtxtAttr; - // Expiry time for ticket - TimeStamp Expiration; - // Payload - char *payload; - - // Has instance check - static inline bool HasInstance(Handle val) { - if (!val->IsObject()) return false; - Local obj = val->ToObject(); - return NanNew(constructor_template)->HasInstance(obj); - }; - - // Functions available from V8 - static void Initialize(Handle target); - static NAN_METHOD(InitializeContext); - static NAN_METHOD(InitalizeStep); - static NAN_METHOD(DecryptMessage); - static NAN_METHOD(QueryContextAttributes); - static NAN_METHOD(EncryptMessage); - - // Payload getter - static NAN_GETTER(PayloadGetter); - // hasContext getter - static NAN_GETTER(HasContextGetter); - - // Constructor used for creating new Long objects from C++ - static Persistent constructor_template; - - private: - // Create a new instance - static NAN_METHOD(New); -}; - -#endif diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.js b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.js deleted file mode 100644 index ef04e92..0000000 --- a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_context.js +++ /dev/null @@ -1,3 +0,0 @@ -var SecurityContextNative = require('../../../build/Release/kerberos').SecurityContext; -// Export the modified class -exports.SecurityContext = SecurityContextNative; \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.cc b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.cc deleted file mode 100644 index fc2a3d8..0000000 --- a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.cc +++ /dev/null @@ -1,351 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "security_credentials.h" - -#ifndef ARRAY_SIZE -# define ARRAY_SIZE(a) (sizeof((a)) / sizeof((a)[0])) -#endif - -static LPSTR DisplaySECError(DWORD ErrCode); - -Persistent SecurityCredentials::constructor_template; - -SecurityCredentials::SecurityCredentials() : ObjectWrap() { -} - -SecurityCredentials::~SecurityCredentials() { -} - -NAN_METHOD(SecurityCredentials::New) { - NanScope(); - // Create security credentials instance - SecurityCredentials *security_credentials = new SecurityCredentials(); - // Wrap it - security_credentials->Wrap(args.This()); - // Return the object - NanReturnValue(args.This()); -} - -// Call structs -typedef struct SecurityCredentialCall { - char *package_str; - char *username_str; - char *password_str; - char *domain_str; - SecurityCredentials *credentials; -} SecurityCredentialCall; - -// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -// authGSSClientInit -// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -static void _authSSPIAquire(Worker *worker) { - // Status of operation - SECURITY_STATUS status; - - // Unpack data - SecurityCredentialCall *call = (SecurityCredentialCall *)worker->parameters; - - // // Unwrap the credentials - // SecurityCredentials *security_credentials = (SecurityCredentials *)call->credentials; - SecurityCredentials *security_credentials = new SecurityCredentials(); - - // If we have domain string - if(call->domain_str != NULL) { - security_credentials->m_Identity.Domain = USTR(_tcsdup(call->domain_str)); - security_credentials->m_Identity.DomainLength = (unsigned long)_tcslen(call->domain_str); - } else { - security_credentials->m_Identity.Domain = NULL; - security_credentials->m_Identity.DomainLength = 0; - } - - // Set up the user - security_credentials->m_Identity.User = USTR(_tcsdup(call->username_str)); - security_credentials->m_Identity.UserLength = (unsigned long)_tcslen(call->username_str); - - // If we have a password string - if(call->password_str != NULL) { - // Set up the password - security_credentials->m_Identity.Password = USTR(_tcsdup(call->password_str)); - security_credentials->m_Identity.PasswordLength = (unsigned long)_tcslen(call->password_str); - } - - #ifdef _UNICODE - security_credentials->m_Identity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; - #else - security_credentials->m_Identity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; - #endif - - // Attempt to acquire credentials - status = _sspi_AcquireCredentialsHandle( - NULL, - call->package_str, - SECPKG_CRED_OUTBOUND, - NULL, - call->password_str != NULL ? &security_credentials->m_Identity : NULL, - NULL, NULL, - &security_credentials->m_Credentials, - &security_credentials->Expiration - ); - - // We have an error - if(status != SEC_E_OK) { - worker->error = TRUE; - worker->error_code = status; - worker->error_message = DisplaySECError(status); - } else { - worker->return_code = status; - worker->return_value = security_credentials; - } - - // Free up parameter structure - if(call->package_str != NULL) free(call->package_str); - if(call->domain_str != NULL) free(call->domain_str); - if(call->password_str != NULL) free(call->password_str); - if(call->username_str != NULL) free(call->username_str); - free(call); -} - -static Handle _map_authSSPIAquire(Worker *worker) { - return NanNull(); -} - -NAN_METHOD(SecurityCredentials::Aquire) { - NanScope(); - - char *package_str = NULL, *username_str = NULL, *password_str = NULL, *domain_str = NULL; - // Unpack the variables - if(args.Length() != 2 && args.Length() != 3 && args.Length() != 4 && args.Length() != 5) - return NanThrowError("Aquire must be called with either [package:string, username:string, [password:string, domain:string], callback:function]"); - - if(!args[0]->IsString()) - return NanThrowError("Aquire must be called with either [package:string, username:string, [password:string, domain:string], callback:function]"); - - if(!args[1]->IsString()) - return NanThrowError("Aquire must be called with either [package:string, username:string, [password:string, domain:string], callback:function]"); - - if(args.Length() == 3 && (!args[2]->IsString() && !args[2]->IsFunction())) - return NanThrowError("Aquire must be called with either [package:string, username:string, [password:string, domain:string], callback:function]"); - - if(args.Length() == 4 && (!args[3]->IsString() && !args[3]->IsUndefined() && !args[3]->IsNull()) && !args[3]->IsFunction()) - return NanThrowError("Aquire must be called with either [package:string, username:string, [password:string, domain:string], callback:function]"); - - if(args.Length() == 5 && !args[4]->IsFunction()) - return NanThrowError("Aquire must be called with either [package:string, username:string, [password:string, domain:string], callback:function]"); - - Local callbackHandle; - - // Figure out which parameter is the callback - if(args.Length() == 5) { - callbackHandle = Local::Cast(args[4]); - } else if(args.Length() == 4) { - callbackHandle = Local::Cast(args[3]); - } else if(args.Length() == 3) { - callbackHandle = Local::Cast(args[2]); - } - - // Unpack the package - Local package = args[0]->ToString(); - package_str = (char *)calloc(package->Utf8Length() + 1, sizeof(char)); - package->WriteUtf8(package_str); - - // Unpack the user name - Local username = args[1]->ToString(); - username_str = (char *)calloc(username->Utf8Length() + 1, sizeof(char)); - username->WriteUtf8(username_str); - - // If we have a password - if(args.Length() == 3 || args.Length() == 4 || args.Length() == 5) { - Local password = args[2]->ToString(); - password_str = (char *)calloc(password->Utf8Length() + 1, sizeof(char)); - password->WriteUtf8(password_str); - } - - // If we have a domain - if((args.Length() == 4 || args.Length() == 5) && args[3]->IsString()) { - Local domain = args[3]->ToString(); - domain_str = (char *)calloc(domain->Utf8Length() + 1, sizeof(char)); - domain->WriteUtf8(domain_str); - } - - // Allocate call structure - SecurityCredentialCall *call = (SecurityCredentialCall *)calloc(1, sizeof(SecurityCredentialCall)); - call->domain_str = domain_str; - call->package_str = package_str; - call->password_str = password_str; - call->username_str = username_str; - - // Unpack the callback - NanCallback *callback = new NanCallback(callbackHandle); - - // Let's allocate some space - Worker *worker = new Worker(); - worker->error = false; - worker->request.data = worker; - worker->callback = callback; - worker->parameters = call; - worker->execute = _authSSPIAquire; - worker->mapper = _map_authSSPIAquire; - - // Schedule the worker with lib_uv - uv_queue_work(uv_default_loop(), &worker->request, SecurityCredentials::Process, (uv_after_work_cb)SecurityCredentials::After); - - // Return no value as it's callback based - NanReturnValue(NanUndefined()); -} - -void SecurityCredentials::Initialize(Handle target) { - // Grab the scope of the call from Node - NanScope(); - - // Define a new function template - Local t = NanNew(New); - t->InstanceTemplate()->SetInternalFieldCount(1); - t->SetClassName(NanNew("SecurityCredentials")); - - // Class methods - NODE_SET_METHOD(t, "aquire", Aquire); - - // Set persistent - NanAssignPersistent(constructor_template, t); - - // Set the symbol - target->ForceSet(NanNew("SecurityCredentials"), t->GetFunction()); - - // Attempt to load the security.dll library - load_library(); -} - -static LPSTR DisplaySECError(DWORD ErrCode) { - LPSTR pszName = NULL; // WinError.h - - switch(ErrCode) { - case SEC_E_BUFFER_TOO_SMALL: - pszName = "SEC_E_BUFFER_TOO_SMALL - The message buffer is too small. Used with the Digest SSP."; - break; - - case SEC_E_CRYPTO_SYSTEM_INVALID: - pszName = "SEC_E_CRYPTO_SYSTEM_INVALID - The cipher chosen for the security context is not supported. Used with the Digest SSP."; - break; - case SEC_E_INCOMPLETE_MESSAGE: - pszName = "SEC_E_INCOMPLETE_MESSAGE - The data in the input buffer is incomplete. The application needs to read more data from the server and call DecryptMessage (General) again."; - break; - - case SEC_E_INVALID_HANDLE: - pszName = "SEC_E_INVALID_HANDLE - A context handle that is not valid was specified in the phContext parameter. Used with the Digest and Schannel SSPs."; - break; - - case SEC_E_INVALID_TOKEN: - pszName = "SEC_E_INVALID_TOKEN - The buffers are of the wrong type or no buffer of type SECBUFFER_DATA was found. Used with the Schannel SSP."; - break; - - case SEC_E_MESSAGE_ALTERED: - pszName = "SEC_E_MESSAGE_ALTERED - The message has been altered. Used with the Digest and Schannel SSPs."; - break; - - case SEC_E_OUT_OF_SEQUENCE: - pszName = "SEC_E_OUT_OF_SEQUENCE - The message was not received in the correct sequence."; - break; - - case SEC_E_QOP_NOT_SUPPORTED: - pszName = "SEC_E_QOP_NOT_SUPPORTED - Neither confidentiality nor integrity are supported by the security context. Used with the Digest SSP."; - break; - - case SEC_I_CONTEXT_EXPIRED: - pszName = "SEC_I_CONTEXT_EXPIRED - The message sender has finished using the connection and has initiated a shutdown."; - break; - - case SEC_I_RENEGOTIATE: - pszName = "SEC_I_RENEGOTIATE - The remote party requires a new handshake sequence or the application has just initiated a shutdown."; - break; - - case SEC_E_ENCRYPT_FAILURE: - pszName = "SEC_E_ENCRYPT_FAILURE - The specified data could not be encrypted."; - break; - - case SEC_E_DECRYPT_FAILURE: - pszName = "SEC_E_DECRYPT_FAILURE - The specified data could not be decrypted."; - break; - case -1: - pszName = "Failed to load security.dll library"; - break; - - } - - return pszName; -} - -// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -// UV Lib callbacks -// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -void SecurityCredentials::Process(uv_work_t* work_req) { - // Grab the worker - Worker *worker = static_cast(work_req->data); - // Execute the worker code - worker->execute(worker); -} - -void SecurityCredentials::After(uv_work_t* work_req) { - // Grab the scope of the call from Node - NanScope(); - - // Get the worker reference - Worker *worker = static_cast(work_req->data); - - // If we have an error - if(worker->error) { - Local err = v8::Exception::Error(NanNew(worker->error_message)); - Local obj = err->ToObject(); - obj->Set(NanNew("code"), NanNew(worker->error_code)); - Local args[2] = { err, NanNull() }; - // Execute the error - v8::TryCatch try_catch; - - // Call the callback - worker->callback->Call(ARRAY_SIZE(args), args); - - // If we have an exception handle it as a fatalexception - if (try_catch.HasCaught()) { - node::FatalException(try_catch); - } - } else { - SecurityCredentials *return_value = (SecurityCredentials *)worker->return_value; - // Create a new instance - Local result = NanNew(constructor_template)->GetFunction()->NewInstance(); - // Unwrap the credentials - SecurityCredentials *security_credentials = ObjectWrap::Unwrap(result); - // Set the values - security_credentials->m_Identity = return_value->m_Identity; - security_credentials->m_Credentials = return_value->m_Credentials; - security_credentials->Expiration = return_value->Expiration; - // Set up the callback with a null first - Handle args[2] = { NanNull(), result}; - // Wrap the callback function call in a TryCatch so that we can call - // node's FatalException afterwards. This makes it possible to catch - // the exception from JavaScript land using the - // process.on('uncaughtException') event. - v8::TryCatch try_catch; - - // Call the callback - worker->callback->Call(ARRAY_SIZE(args), args); - - // If we have an exception handle it as a fatalexception - if (try_catch.HasCaught()) { - node::FatalException(try_catch); - } - } - - // Clean up the memory - delete worker->callback; - delete worker; -} - diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.h b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.h deleted file mode 100644 index 41f4327..0000000 --- a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef SECURITY_CREDENTIALS_H -#define SECURITY_CREDENTIALS_H - -#include -#include -#include - -#define SECURITY_WIN32 1 - -#include -#include -#include -#include "nan.h" -#include "../worker.h" -#include - -extern "C" { - #include "../kerberos_sspi.h" -} - -// SEC_WINNT_AUTH_IDENTITY makes it unusually hard -// to compile for both Unicode and ansi, so I use this macro: -#ifdef _UNICODE -#define USTR(str) (str) -#else -#define USTR(str) ((unsigned char*)(str)) -#endif - -using namespace v8; -using namespace node; - -class SecurityCredentials : public ObjectWrap { - public: - SecurityCredentials(); - ~SecurityCredentials(); - - // Pointer to context object - SEC_WINNT_AUTH_IDENTITY m_Identity; - // credentials - CredHandle m_Credentials; - // Expiry time for ticket - TimeStamp Expiration; - - // Has instance check - static inline bool HasInstance(Handle val) { - if (!val->IsObject()) return false; - Local obj = val->ToObject(); - return NanNew(constructor_template)->HasInstance(obj); - }; - - // Functions available from V8 - static void Initialize(Handle target); - static NAN_METHOD(Aquire); - - // Constructor used for creating new Long objects from C++ - static Persistent constructor_template; - - private: - // Create a new instance - static NAN_METHOD(New); - // Handles the uv calls - static void Process(uv_work_t* work_req); - // Called after work is done - static void After(uv_work_t* work_req); -}; - -#endif \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.js b/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.js deleted file mode 100644 index 4215c92..0000000 --- a/node_modules/mongodb/node_modules/kerberos/lib/win32/wrappers/security_credentials.js +++ /dev/null @@ -1,22 +0,0 @@ -var SecurityCredentialsNative = require('../../../build/Release/kerberos').SecurityCredentials; - -// Add simple kebros helper -SecurityCredentialsNative.aquire_kerberos = function(username, password, domain, callback) { - if(typeof password == 'function') { - callback = password; - password = null; - } else if(typeof domain == 'function') { - callback = domain; - domain = null; - } - - // We are going to use the async version - if(typeof callback == 'function') { - return SecurityCredentialsNative.aquire('Kerberos', username, password, domain, callback); - } else { - return SecurityCredentialsNative.aquireSync('Kerberos', username, password, domain); - } -} - -// Export the modified class -exports.SecurityCredentials = SecurityCredentialsNative; \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/worker.cc b/node_modules/mongodb/node_modules/kerberos/lib/worker.cc deleted file mode 100644 index e7a472f..0000000 --- a/node_modules/mongodb/node_modules/kerberos/lib/worker.cc +++ /dev/null @@ -1,7 +0,0 @@ -#include "worker.h" - -Worker::Worker() { -} - -Worker::~Worker() { -} \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/lib/worker.h b/node_modules/mongodb/node_modules/kerberos/lib/worker.h deleted file mode 100644 index cbc7f6a..0000000 --- a/node_modules/mongodb/node_modules/kerberos/lib/worker.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef WORKER_H_ -#define WORKER_H_ - -#include -#include -#include -#include - -using namespace node; -using namespace v8; - -class Worker { - public: - Worker(); - virtual ~Worker(); - - // libuv's request struct. - uv_work_t request; - // Callback - NanCallback *callback; - // Parameters - void *parameters; - // Results - void *return_value; - // Did we raise an error - bool error; - // The error message - char *error_message; - // Error code if not message - int error_code; - // Any return code - int return_code; - // Method we are going to fire - void (*execute)(Worker *worker); - Handle (*mapper)(Worker *worker); -}; - -#endif // WORKER_H_ diff --git a/node_modules/mongodb/node_modules/kerberos/node_modules/nan/.dntrc b/node_modules/mongodb/node_modules/kerberos/node_modules/nan/.dntrc deleted file mode 100644 index 47971da..0000000 --- a/node_modules/mongodb/node_modules/kerberos/node_modules/nan/.dntrc +++ /dev/null @@ -1,30 +0,0 @@ -## DNT config file -## see https://github.com/rvagg/dnt - -NODE_VERSIONS="\ - master \ - v0.11.13 \ - v0.10.30 \ - v0.10.29 \ - v0.10.28 \ - v0.10.26 \ - v0.10.25 \ - v0.10.24 \ - v0.10.23 \ - v0.10.22 \ - v0.10.21 \ - v0.10.20 \ - v0.10.19 \ - v0.8.28 \ - v0.8.27 \ - v0.8.26 \ - v0.8.24 \ -" -OUTPUT_PREFIX="nan-" -TEST_CMD=" \ - cd /dnt/ && \ - npm install && \ - node_modules/.bin/node-gyp --nodedir /usr/src/node/ rebuild --directory test && \ - node_modules/.bin/tap --gc test/js/*-test.js \ -" - diff --git a/node_modules/mongodb/node_modules/kerberos/node_modules/nan/CHANGELOG.md b/node_modules/mongodb/node_modules/kerberos/node_modules/nan/CHANGELOG.md deleted file mode 100644 index 146cbb5..0000000 --- a/node_modules/mongodb/node_modules/kerberos/node_modules/nan/CHANGELOG.md +++ /dev/null @@ -1,200 +0,0 @@ -# NAN ChangeLog - -### Version 1.3.0: current Node unstable: 0.11.13, Node stable: 0.10.30 - - -**1.3.0 Aug 2 2014** - - - Added NanNew(std::string) - - Added NanNew(std::string&) - - Added NanAsciiString helper class - - Added NanUtf8String helper class - - Added NanUcs2String helper class - - Deprecated NanRawString() - - Deprecated NanCString() - - Added NanGetIsolateData(v8::Isolate *isolate) - - Added NanMakeCallback(v8::Handle target, v8::Handle func, int argc, v8::Handle* argv) - - Added NanMakeCallback(v8::Handle target, v8::Handle symbol, int argc, v8::Handle* argv) - - Added NanMakeCallback(v8::Handle target, const char* method, int argc, v8::Handle* argv) - - Added NanSetTemplate(v8::Handle templ, v8::Handle name , v8::Handle value, v8::PropertyAttribute attributes) - - Added NanSetPrototypeTemplate(v8::Local templ, v8::Handle name, v8::Handle value, v8::PropertyAttribute attributes) - - Added NanSetInstanceTemplate(v8::Local templ, const char *name, v8::Handle value) - - Added NanSetInstanceTemplate(v8::Local templ, v8::Handle name, v8::Handle value, v8::PropertyAttribute attributes) - -**1.2.0 Jun 5 2014** - - - Add NanSetPrototypeTemplate - - Changed NAN_WEAK_CALLBACK internals, switched _NanWeakCallbackData to class, - introduced _NanWeakCallbackDispatcher - - Removed -Wno-unused-local-typedefs from test builds - - Made test builds Windows compatible ('Sleep()') - -**1.1.2 May 28 2014** - - - Release to fix more stuff-ups in 1.1.1 - -**1.1.1 May 28 2014** - - - Release to fix version mismatch in nan.h and lack of changelog entry for 1.1.0 - -**1.1.0 May 25 2014** - - - Remove nan_isolate, use v8::Isolate::GetCurrent() internally instead - - Additional explicit overloads for NanNew(): (char*,int), (uint8_t*[,int]), - (uint16_t*[,int), double, int, unsigned int, bool, v8::String::ExternalStringResource*, - v8::String::ExternalAsciiStringResource* - - Deprecate NanSymbol() - - Added SetErrorMessage() and ErrorMessage() to NanAsyncWorker - -**1.0.0 May 4 2014** - - - Heavy API changes for V8 3.25 / Node 0.11.13 - - Use cpplint.py - - Removed NanInitPersistent - - Removed NanPersistentToLocal - - Removed NanFromV8String - - Removed NanMakeWeak - - Removed NanNewLocal - - Removed NAN_WEAK_CALLBACK_OBJECT - - Removed NAN_WEAK_CALLBACK_DATA - - Introduce NanNew, replaces NanNewLocal, NanPersistentToLocal, adds many overloaded typed versions - - Introduce NanUndefined, NanNull, NanTrue and NanFalse - - Introduce NanEscapableScope and NanEscapeScope - - Introduce NanMakeWeakPersistent (requires a special callback to work on both old and new node) - - Introduce NanMakeCallback for node::MakeCallback - - Introduce NanSetTemplate - - Introduce NanGetCurrentContext - - Introduce NanCompileScript and NanRunScript - - Introduce NanAdjustExternalMemory - - Introduce NanAddGCEpilogueCallback, NanAddGCPrologueCallback, NanRemoveGCEpilogueCallback, NanRemoveGCPrologueCallback - - Introduce NanGetHeapStatistics - - Rename NanAsyncWorker#SavePersistent() to SaveToPersistent() - -**0.8.0 Jan 9 2014** - - - NanDispose -> NanDisposePersistent, deprecate NanDispose - - Extract _NAN_*_RETURN_TYPE, pull up NAN_*() - -**0.7.1 Jan 9 2014** - - - Fixes to work against debug builds of Node - - Safer NanPersistentToLocal (avoid reinterpret_cast) - - Speed up common NanRawString case by only extracting flattened string when necessary - -**0.7.0 Dec 17 2013** - - - New no-arg form of NanCallback() constructor. - - NanCallback#Call takes Handle rather than Local - - Removed deprecated NanCallback#Run method, use NanCallback#Call instead - - Split off _NAN_*_ARGS_TYPE from _NAN_*_ARGS - - Restore (unofficial) Node 0.6 compatibility at NanCallback#Call() - - Introduce NanRawString() for char* (or appropriate void*) from v8::String - (replacement for NanFromV8String) - - Introduce NanCString() for null-terminated char* from v8::String - -**0.6.0 Nov 21 2013** - - - Introduce NanNewLocal(v8::Handle value) for use in place of - v8::Local::New(...) since v8 started requiring isolate in Node 0.11.9 - -**0.5.2 Nov 16 2013** - - - Convert SavePersistent and GetFromPersistent in NanAsyncWorker from protected and public - -**0.5.1 Nov 12 2013** - - - Use node::MakeCallback() instead of direct v8::Function::Call() - -**0.5.0 Nov 11 2013** - - - Added @TooTallNate as collaborator - - New, much simpler, "include_dirs" for binding.gyp - - Added full range of NAN_INDEX_* macros to match NAN_PROPERTY_* macros - -**0.4.4 Nov 2 2013** - - - Isolate argument from v8::Persistent::MakeWeak removed for 0.11.8+ - -**0.4.3 Nov 2 2013** - - - Include node_object_wrap.h, removed from node.h for Node 0.11.8. - -**0.4.2 Nov 2 2013** - - - Handle deprecation of v8::Persistent::Dispose(v8::Isolate* isolate)) for - Node 0.11.8 release. - -**0.4.1 Sep 16 2013** - - - Added explicit `#include ` as it was removed from node.h for v0.11.8 - -**0.4.0 Sep 2 2013** - - - Added NAN_INLINE and NAN_DEPRECATED and made use of them - - Added NanError, NanTypeError and NanRangeError - - Cleaned up code - -**0.3.2 Aug 30 2013** - - - Fix missing scope declaration in GetFromPersistent() and SaveToPersistent - in NanAsyncWorker - -**0.3.1 Aug 20 2013** - - - fix "not all control paths return a value" compile warning on some platforms - -**0.3.0 Aug 19 2013** - - - Made NAN work with NPM - - Lots of fixes to NanFromV8String, pulling in features from new Node core - - Changed node::encoding to Nan::Encoding in NanFromV8String to unify the API - - Added optional error number argument for NanThrowError() - - Added NanInitPersistent() - - Added NanReturnNull() and NanReturnEmptyString() - - Added NanLocker and NanUnlocker - - Added missing scopes - - Made sure to clear disposed Persistent handles - - Changed NanAsyncWorker to allocate error messages on the heap - - Changed NanThrowError(Local) to NanThrowError(Handle) - - Fixed leak in NanAsyncWorker when errmsg is used - -**0.2.2 Aug 5 2013** - - - Fixed usage of undefined variable with node::BASE64 in NanFromV8String() - -**0.2.1 Aug 5 2013** - - - Fixed 0.8 breakage, node::BUFFER encoding type not available in 0.8 for - NanFromV8String() - -**0.2.0 Aug 5 2013** - - - Added NAN_PROPERTY_GETTER, NAN_PROPERTY_SETTER, NAN_PROPERTY_ENUMERATOR, - NAN_PROPERTY_DELETER, NAN_PROPERTY_QUERY - - Extracted _NAN_METHOD_ARGS, _NAN_GETTER_ARGS, _NAN_SETTER_ARGS, - _NAN_PROPERTY_GETTER_ARGS, _NAN_PROPERTY_SETTER_ARGS, - _NAN_PROPERTY_ENUMERATOR_ARGS, _NAN_PROPERTY_DELETER_ARGS, - _NAN_PROPERTY_QUERY_ARGS - - Added NanGetInternalFieldPointer, NanSetInternalFieldPointer - - Added NAN_WEAK_CALLBACK, NAN_WEAK_CALLBACK_OBJECT, - NAN_WEAK_CALLBACK_DATA, NanMakeWeak - - Renamed THROW_ERROR to _NAN_THROW_ERROR - - Added NanNewBufferHandle(char*, size_t, node::smalloc::FreeCallback, void*) - - Added NanBufferUse(char*, uint32_t) - - Added NanNewContextHandle(v8::ExtensionConfiguration*, - v8::Handle, v8::Handle) - - Fixed broken NanCallback#GetFunction() - - Added optional encoding and size arguments to NanFromV8String() - - Added NanGetPointerSafe() and NanSetPointerSafe() - - Added initial test suite (to be expanded) - - Allow NanUInt32OptionValue to convert any Number object - -**0.1.0 Jul 21 2013** - - - Added `NAN_GETTER`, `NAN_SETTER` - - Added `NanThrowError` with single Local argument - - Added `NanNewBufferHandle` with single uint32_t argument - - Added `NanHasInstance(Persistent&, Handle)` - - Added `Local NanCallback#GetFunction()` - - Added `NanCallback#Call(int, Local[])` - - Deprecated `NanCallback#Run(int, Local[])` in favour of Call diff --git a/node_modules/mongodb/node_modules/kerberos/node_modules/nan/LICENSE b/node_modules/mongodb/node_modules/kerberos/node_modules/nan/LICENSE deleted file mode 100644 index d502e18..0000000 --- a/node_modules/mongodb/node_modules/kerberos/node_modules/nan/LICENSE +++ /dev/null @@ -1,46 +0,0 @@ -Copyright 2013, NAN contributors: - - Rod Vagg - - Benjamin Byholm - - Trevor Norris - - Nathan Rajlich - - Brett Lawson - - Ben Noordhuis -(the "Original Author") -All rights reserved. - -MIT +no-false-attribs 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. - -Distributions of all or part of the Software intended to be used -by the recipients as they would use the unmodified Software, -containing modifications that substantially alter, remove, or -disable functionality of the Software, outside of the documented -configuration mechanisms provided by the Software, shall be -modified such that the Original Author's bug reporting email -addresses and urls are either replaced with the contact information -of the parties responsible for the changes, or removed entirely. - -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. - - -Except where noted, this license applies to any and all software -programs and associated documentation files created by the -Original Author, when distributed with the Software. diff --git a/node_modules/mongodb/node_modules/kerberos/node_modules/nan/README.md b/node_modules/mongodb/node_modules/kerberos/node_modules/nan/README.md deleted file mode 100644 index 2904a38..0000000 --- a/node_modules/mongodb/node_modules/kerberos/node_modules/nan/README.md +++ /dev/null @@ -1,1054 +0,0 @@ -Native Abstractions for Node.js -=============================== - -**A header file filled with macro and utility goodness for making add-on development for Node.js easier across versions 0.8, 0.10 and 0.11, and eventually 0.12.** - -***Current version: 1.3.0*** - -*(See [nan.h](https://github.com/rvagg/nan/blob/master/CHANGELOG.md) for complete ChangeLog)* - -[![NPM](https://nodei.co/npm/nan.png?downloads=true)](https://nodei.co/npm/nan/) [![NPM](https://nodei.co/npm-dl/nan.png?months=6)](https://nodei.co/npm/nan/) - -[![Build Status](https://secure.travis-ci.org/rvagg/nan.png)](http://travis-ci.org/rvagg/nan) -[![Build status](https://ci.appveyor.com/api/projects/status/kh73pbm9dsju7fgh)](https://ci.appveyor.com/project/RodVagg/nan) - -Thanks to the crazy changes in V8 (and some in Node core), keeping native addons compiling happily across versions, particularly 0.10 to 0.11/0.12, is a minor nightmare. The goal of this project is to store all logic necessary to develop native Node.js addons without having to inspect `NODE_MODULE_VERSION` and get yourself into a macro-tangle. - -This project also contains some helper utilities that make addon development a bit more pleasant. - - * **[News & Updates](#news)** - * **[Usage](#usage)** - * **[Example](#example)** - * **[API](#api)** - - -## News & Updates - -### Aug-2014: 1.3.0 release - -* `NanCString()` and `NanRawString()` have been deprecated in favour of new NanAsciiString, NanUtf8String and NanUcs2String. These classes manage the underlying memory for you in a safer way than just handing off an allocated array. You should now `*NanAsciiString(handle)` to access the raw `char` data, you can also allocate on the heap if you need to keep a reference. -* Two more NanMakeCallback overloads have been added to for parity with Node core. -* You can now `NanNew(std::string)` (use `NanNew(std::string&)` to pass by reference) -* NanSetTemplate, NanSetPrototypeTemplate and NanSetInstanceTemplate have been added. - -### May-2014: 1.1.0 release - -* We've deprecated `NanSymbol()`, you should just use `NanNew()` now. -* `NanNull()`, `NanUndefined()`, `NanTrue()`, `NanFalse()` all return `Local`s now. -* `nan_isolate` is gone, it was intended to be internal-only but if you were using it then you should switch to `v8::Isolate::GetCurrent()`. -* `NanNew()` has received some additional overload-love so you should be able to give it many kinds of values without specifying the ``. -* Lots of small fixes and additions to expand the V8 API coverage, *use the source, Luke*. - - -### May-2014: Major changes for V8 3.25 / Node 0.11.13 - -Node 0.11.11 and 0.11.12 were both broken releases for native add-ons, you simply can't properly compile against either of them for different reasons. But we now have a 0.11.13 release that jumps a couple of versions of V8 ahead and includes some more, major (traumatic) API changes. - -Because we are now nearing Node 0.12 and estimate that the version of V8 we are using in Node 0.11.13 will be close to the API we get for 0.12, we have taken the opportunity to not only *fix* NAN for 0.11.13 but make some major changes to improve the NAN API. - -We have **removed support for Node 0.11 versions prior to 0.11.13**. As usual, our tests are run against (and pass) the last 5 versions of Node 0.8 and Node 0.10. We also include Node 0.11.13 obviously. - -The major change is something that [Benjamin Byholm](kkoopa) has put many hours in to. We now have a fantastic new `NanNew(args)` interface for creating new `Local`s, this replaces `NanNewLocal()` and much more. If you look in [./nan.h](nan.h) you'll see a large number of overloaded versions of this method. In general you should be able to `NanNew(arguments)` for any type you want to make a `Local` from. This includes `Persistent` types, so we now have a `Local NanNew(const Persistent arg)` to replace `NanPersistentToLocal()`. - -We also now have `NanUndefined()`, `NanNull()`, `NanTrue()` and `NanFalse()`. Mainly because of the new requirement for an `Isolate` argument for each of the native V8 versions of this. - -V8 has now introduced an `EscapableHandleScope` from which you `scope.Escape(Local value)` to *return* a value from a one scope to another. This replaces the standard `HandleScope` and `scope.Close(Local value)`, although `HandleScope` still exists for when you don't need to return a handle to the caller. For NAN we are exposing it as `NanEscapableScope()` and `NanEscapeScope()`, while `NanScope()` is still how you create a new scope that doesn't need to return handles. For older versions of Node/V8, it'll still map to the older `HandleScope` functionality. - -`NanFromV8String()` was deprecated and has now been removed. You should use `NanCString()` or `NanRawString()` instead. - -Because `node::MakeCallback()` now takes an `Isolate`, and because it doesn't exist in older versions of Node, we've introduced `NanMakeCallback()`. You should *always* use this when calling a JavaScript function from C++. - -There's lots more, check out the Changelog in nan.h or look through [#86](https://github.com/rvagg/nan/pull/86) for all the gory details. - -### Dec-2013: NanCString and NanRawString - -Two new functions have been introduced to replace the functionality that's been provided by `NanFromV8String` until now. NanCString has sensible defaults so it's super easy to fetch a null-terminated c-style string out of a `v8::String`. `NanFromV8String` is still around and has defaults that allow you to pass a single handle to fetch a `char*` while `NanRawString` requires a little more attention to arguments. - -### Nov-2013: Node 0.11.9+ breaking V8 change - -The version of V8 that's shipping with Node 0.11.9+ has changed the signature for new `Local`s to: `v8::Local::New(isolate, value)`, i.e. introducing the `isolate` argument and therefore breaking all new `Local` declarations for previous versions. NAN 0.6+ now includes a `NanNewLocal(value)` that can be used in place to work around this incompatibility and maintain compatibility with 0.8->0.11.9+ (minus a few early 0.11 releases). - -For example, if you wanted to return a `null` on a callback you will have to change the argument from `v8::Local::New(v8::Null())` to `NanNewLocal(v8::Null())`. - -### Nov-2013: Change to binding.gyp `"include_dirs"` for NAN - -Inclusion of NAN in a project's binding.gyp is now greatly simplified. You can now just use `" -## Usage - -Simply add **NAN** as a dependency in the *package.json* of your Node addon: - -``` bash -$ npm install --save nan -``` - -Pull in the path to **NAN** in your *binding.gyp* so that you can use `#include ` in your *.cpp* files: - -``` python -"include_dirs" : [ - "` when compiling your addon. - - -## Example - -See **[LevelDOWN](https://github.com/rvagg/node-leveldown/pull/48)** for a full example of **NAN** in use. - -For a simpler example, see the **[async pi estimation example](https://github.com/rvagg/nan/tree/master/examples/async_pi_estimate)** in the examples directory for full code and an explanation of what this Monte Carlo Pi estimation example does. Below are just some parts of the full example that illustrate the use of **NAN**. - -Compare to the current 0.10 version of this example, found in the [node-addon-examples](https://github.com/rvagg/node-addon-examples/tree/master/9_async_work) repository and also a 0.11 version of the same found [here](https://github.com/kkoopa/node-addon-examples/tree/5c01f58fc993377a567812597e54a83af69686d7/9_async_work). - -Note that there is no embedded version sniffing going on here and also the async work is made much simpler, see below for details on the `NanAsyncWorker` class. - -```c++ -// addon.cc -#include -#include -// ... - -using v8::FunctionTemplate; -using v8::Handle; -using v8::Object; -using v8::String; - -void InitAll(Handle exports) { - exports->Set(NanNew("calculateSync"), - NanNew(CalculateSync)->GetFunction()); - - exports->Set(NanNew("calculateAsync"), - NanNew(CalculateAsync)->GetFunction()); -} - -NODE_MODULE(addon, InitAll) -``` - -```c++ -// sync.h -#include -#include - -NAN_METHOD(CalculateSync); -``` - -```c++ -// sync.cc -#include -#include -#include "./sync.h" -// ... - -using v8::Number; - -// Simple synchronous access to the `Estimate()` function -NAN_METHOD(CalculateSync) { - NanScope(); - - // expect a number as the first argument - int points = args[0]->Uint32Value(); - double est = Estimate(points); - - NanReturnValue(NanNew(est)); -} -``` - -```c++ -// async.h -#include -#include - -NAN_METHOD(CalculateAsync); -``` - -```c++ -// async.cc -#include -#include -#include "./async.h" - -// ... - -using v8::Function; -using v8::Local; -using v8::Null; -using v8::Number; -using v8::Value; - -class PiWorker : public NanAsyncWorker { - public: - PiWorker(NanCallback *callback, int points) - : NanAsyncWorker(callback), points(points) {} - ~PiWorker() {} - - // Executed inside the worker-thread. - // It is not safe to access V8, or V8 data structures - // here, so everything we need for input and output - // should go on `this`. - void Execute () { - estimate = Estimate(points); - } - - // Executed when the async work is complete - // this function will be run inside the main event loop - // so it is safe to use V8 again - void HandleOKCallback () { - NanScope(); - - Local argv[] = { - NanNull() - , NanNew(estimate) - }; - - callback->Call(2, argv); - }; - - private: - int points; - double estimate; -}; - -// Asynchronous access to the `Estimate()` function -NAN_METHOD(CalculateAsync) { - NanScope(); - - int points = args[0]->Uint32Value(); - NanCallback *callback = new NanCallback(args[1].As()); - - NanAsyncQueueWorker(new PiWorker(callback, points)); - NanReturnUndefined(); -} -``` - - -## API - - * NAN_METHOD - * NAN_GETTER - * NAN_SETTER - * NAN_PROPERTY_GETTER - * NAN_PROPERTY_SETTER - * NAN_PROPERTY_ENUMERATOR - * NAN_PROPERTY_DELETER - * NAN_PROPERTY_QUERY - * NAN_INDEX_GETTER - * NAN_INDEX_SETTER - * NAN_INDEX_ENUMERATOR - * NAN_INDEX_DELETER - * NAN_INDEX_QUERY - * NAN_WEAK_CALLBACK - * NAN_DEPRECATED - * NAN_INLINE - * NanNew - * NanUndefined - * NanNull - * NanTrue - * NanFalse - * NanReturnValue - * NanReturnUndefined - * NanReturnNull - * NanReturnEmptyString - * NanScope - * NanEscapableScope - * NanEscapeScope - * NanLocker - * NanUnlocker - * NanGetInternalFieldPointer - * NanSetInternalFieldPointer - * NanObjectWrapHandle - * NanSymbol - * NanGetPointerSafe - * NanSetPointerSafe - * NanRawString - * NanCString - * NanAsciiString - * NanUtf8String - * NanUcs2String - * NanBooleanOptionValue - * NanUInt32OptionValue - * NanError, NanTypeError, NanRangeError - * NanThrowError, NanThrowTypeError, NanThrowRangeError, NanThrowError(Handle), NanThrowError(Handle, int) - * NanNewBufferHandle(char *, size_t, FreeCallback, void *), NanNewBufferHandle(char *, uint32_t), NanNewBufferHandle(uint32_t) - * NanBufferUse(char *, uint32_t) - * NanNewContextHandle - * NanGetCurrentContext - * NanHasInstance - * NanDisposePersistent - * NanAssignPersistent - * NanMakeWeakPersistent - * NanSetTemplate - * NanSetPrototypeTemplate - * NanSetInstanceTemplate - * NanMakeCallback - * NanCompileScript - * NanRunScript - * NanAdjustExternalMemory - * NanAddGCEpilogueCallback - * NanAddGCPrologueCallback - * NanRemoveGCEpilogueCallback - * NanRemoveGCPrologueCallback - * NanGetHeapStatistics - * NanCallback - * NanAsyncWorker - * NanAsyncQueueWorker - - -### NAN_METHOD(methodname) - -Use `NAN_METHOD` to define your V8 accessible methods: - -```c++ -// .h: -class Foo : public node::ObjectWrap { - ... - - static NAN_METHOD(Bar); - static NAN_METHOD(Baz); -} - - -// .cc: -NAN_METHOD(Foo::Bar) { - ... -} - -NAN_METHOD(Foo::Baz) { - ... -} -``` - -The reason for this macro is because of the method signature change in 0.11: - -```c++ -// 0.10 and below: -Handle name(const Arguments& args) - -// 0.11 and above -void name(const FunctionCallbackInfo& args) -``` - -The introduction of `FunctionCallbackInfo` brings additional complications: - - -### NAN_GETTER(methodname) - -Use `NAN_GETTER` to declare your V8 accessible getters. You get a `Local` `property` and an appropriately typed `args` object that can act like the `args` argument to a `NAN_METHOD` call. - -You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_GETTER`. - - -### NAN_SETTER(methodname) - -Use `NAN_SETTER` to declare your V8 accessible setters. Same as `NAN_GETTER` but you also get a `Local` `value` object to work with. - - -### NAN_PROPERTY_GETTER(cbname) -Use `NAN_PROPERTY_GETTER` to declare your V8 accessible property getters. You get a `Local` `property` and an appropriately typed `args` object that can act similar to the `args` argument to a `NAN_METHOD` call. - -You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_PROPERTY_GETTER`. - - -### NAN_PROPERTY_SETTER(cbname) -Use `NAN_PROPERTY_SETTER` to declare your V8 accessible property setters. Same as `NAN_PROPERTY_GETTER` but you also get a `Local` `value` object to work with. - - -### NAN_PROPERTY_ENUMERATOR(cbname) -Use `NAN_PROPERTY_ENUMERATOR` to declare your V8 accessible property enumerators. You get an appropriately typed `args` object like the `args` argument to a `NAN_PROPERTY_GETTER` call. - -You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_PROPERTY_ENUMERATOR`. - - -### NAN_PROPERTY_DELETER(cbname) -Use `NAN_PROPERTY_DELETER` to declare your V8 accessible property deleters. Same as `NAN_PROPERTY_GETTER`. - -You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_PROPERTY_DELETER`. - - -### NAN_PROPERTY_QUERY(cbname) -Use `NAN_PROPERTY_QUERY` to declare your V8 accessible property queries. Same as `NAN_PROPERTY_GETTER`. - -You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_PROPERTY_QUERY`. - - -### NAN_INDEX_GETTER(cbname) -Use `NAN_INDEX_GETTER` to declare your V8 accessible index getters. You get a `uint32_t` `index` and an appropriately typed `args` object that can act similar to the `args` argument to a `NAN_METHOD` call. - -You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_INDEX_GETTER`. - - -### NAN_INDEX_SETTER(cbname) -Use `NAN_INDEX_SETTER` to declare your V8 accessible index setters. Same as `NAN_INDEX_GETTER` but you also get a `Local` `value` object to work with. - - -### NAN_INDEX_ENUMERATOR(cbname) -Use `NAN_INDEX_ENUMERATOR` to declare your V8 accessible index enumerators. You get an appropriately typed `args` object like the `args` argument to a `NAN_INDEX_GETTER` call. - -You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_INDEX_ENUMERATOR`. - - -### NAN_INDEX_DELETER(cbname) -Use `NAN_INDEX_DELETER` to declare your V8 accessible index deleters. Same as `NAN_INDEX_GETTER`. - -You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_INDEX_DELETER`. - - -### NAN_INDEX_QUERY(cbname) -Use `NAN_INDEX_QUERY` to declare your V8 accessible index queries. Same as `NAN_INDEX_GETTER`. - -You can use `NanReturnNull()`, `NanReturnEmptyString()`, `NanReturnUndefined()` and `NanReturnValue()` in a `NAN_INDEX_QUERY`. - - -### NAN_WEAK_CALLBACK(cbname) - -Use `NAN_WEAK_CALLBACK` to define your V8 WeakReference callbacks. There is an argument object `const _NanWeakCallbackData &data` allowing access to the weak object and the supplied parameter through its `GetValue` and `GetParameter` methods. You can even access the weak callback info object through the `GetCallbackInfo()`method, but you probably should not. `Revive()` keeps the weak object alive until the next GC round. - -```c++ -NAN_WEAK_CALLBACK(weakCallback) { - int *parameter = data.GetParameter(); - NanMakeCallback(NanGetCurrentContext()->Global(), data.GetValue(), 0, NULL); - if ((*parameter)++ == 0) { - data.Revive(); - } else { - delete parameter; - } -} -``` - - -### NAN_DEPRECATED -Declares a function as deprecated. - -```c++ -static NAN_DEPRECATED NAN_METHOD(foo) { - ... -} -``` - - -### NAN_INLINE -Inlines a function. - -```c++ -NAN_INLINE int foo(int bar) { - ... -} -``` - - -### Local<T> NanNew<T>( ... ) - -Use `NanNew` to construct almost all v8 objects and make new local handles. - -Note: Using NanNew with an std::string is possible, however, you should ensure -to use the overload version (`NanNew(stdString)`) rather than the template -version (`NanNew(stdString)`) as there is an unnecessary -performance penalty to using the template version because of the inability for -compilers to appropriately deduce to reference types on template specialization. - -```c++ -Local s = NanNew("value"); - -... - -Persistent o; - -... - -Local lo = NanNew(o); - -``` - - -### Local<Primitive> NanUndefined() - -Use instead of `Undefined()` - - -### Local<Primitive> NanNull() - -Use instead of `Null()` - - -### Local<Boolean> NanTrue() - -Use instead of `True()` - - -### Local<Boolean> NanFalse() - -Use instead of `False()` - - -### NanReturnValue(Handle<Value>) - -Use `NanReturnValue` when you want to return a value from your V8 accessible method: - -```c++ -NAN_METHOD(Foo::Bar) { - ... - - NanReturnValue(NanNew("FooBar!")); -} -``` - -No `return` statement required. - - -### NanReturnUndefined() - -Use `NanReturnUndefined` when you don't want to return anything from your V8 accessible method: - -```c++ -NAN_METHOD(Foo::Baz) { - ... - - NanReturnUndefined(); -} -``` - - -### NanReturnNull() - -Use `NanReturnNull` when you want to return `Null` from your V8 accessible method: - -```c++ -NAN_METHOD(Foo::Baz) { - ... - - NanReturnNull(); -} -``` - - -### NanReturnEmptyString() - -Use `NanReturnEmptyString` when you want to return an empty `String` from your V8 accessible method: - -```c++ -NAN_METHOD(Foo::Baz) { - ... - - NanReturnEmptyString(); -} -``` - - -### NanScope() - -The introduction of `isolate` references for many V8 calls in Node 0.11 makes `NanScope()` necessary, use it in place of `HandleScope scope` when you do not wish to return handles (`Handle` or `Local`) to the surrounding scope (or in functions directly exposed to V8, as they do not return values in the normal sense): - -```c++ -NAN_METHOD(Foo::Bar) { - NanScope(); - - NanReturnValue(NanNew("FooBar!")); -} -``` - -This method is not directly exposed to V8, nor does it return a handle, so it uses an unescapable scope: - -```c++ -bool Foo::Bar() { - NanScope(); - - Local val = NanFalse(); - ... - return val->Value(); -} -``` - - -### NanEscapableScope() - -The separation of handle scopes into escapable and inescapable scopes makes `NanEscapableScope()` necessary, use it in place of `HandleScope scope` when you later wish to return a handle (`Handle` or `Local`) from the scope, this is for internal functions not directly exposed to V8: - -```c++ -Handle Foo::Bar() { - NanEscapableScope(); - - return NanEscapeScope(NanNew("FooBar!")); -} -``` - - -### Local<T> NanEscapeScope(Handle<T> value); -Use together with `NanEscapableScope` to escape the scope. Corresponds to `HandleScope::Close` or `EscapableHandleScope::Escape`. - - -### NanLocker() - -The introduction of `isolate` references for many V8 calls in Node 0.11 makes `NanLocker()` necessary, use it in place of `Locker locker`: - -```c++ -NAN_METHOD(Foo::Bar) { - NanLocker(); - ... - NanUnlocker(); -} -``` - - -### NanUnlocker() - -The introduction of `isolate` references for many V8 calls in Node 0.11 makes `NanUnlocker()` necessary, use it in place of `Unlocker unlocker`: - -```c++ -NAN_METHOD(Foo::Bar) { - NanLocker(); - ... - NanUnlocker(); -} -``` - - -### void * NanGetInternalFieldPointer(Handle<Object>, int) - -Gets a pointer to the internal field with at `index` from a V8 `Object` handle. - -```c++ -Local obj; -... -NanGetInternalFieldPointer(obj, 0); -``` - -### void NanSetInternalFieldPointer(Handle<Object>, int, void *) - -Sets the value of the internal field at `index` on a V8 `Object` handle. - -```c++ -static Persistent dataWrapperCtor; -... -Local wrapper = NanNew(dataWrapperCtor)->NewInstance(); -NanSetInternalFieldPointer(wrapper, 0, this); -``` - - -### Local<Object> NanObjectWrapHandle(Object) - -When you want to fetch the V8 object handle from a native object you've wrapped with Node's `ObjectWrap`, you should use `NanObjectWrapHandle`: - -```c++ -NanObjectWrapHandle(iterator)->Get(NanNew("end")) -``` - - -### Local<String> NanSymbol(const char *) - -Deprecated. Use `NanNew` instead. -Use to create string symbol objects (i.e. `v8::String::NewSymbol(x)`), for getting and setting object properties, or names of objects. - -```c++ -bool foo = false; -if (obj->Has(NanNew("foo"))) - foo = optionsObj->Get(NanNew("foo"))->BooleanValue() -``` - - -### Type NanGetPointerSafe(Type *[, Type]) - -A helper for getting values from optional pointers. If the pointer is `NULL`, the function returns the optional default value, which defaults to `0`. Otherwise, the function returns the value the pointer points to. - -```c++ -char *plugh(uint32_t *optional) { - char res[] = "xyzzy"; - uint32_t param = NanGetPointerSafe(optional, 0x1337); - switch (param) { - ... - } - NanSetPointerSafe(optional, 0xDEADBEEF); -} -``` - - -### bool NanSetPointerSafe(Type *, Type) - -A helper for setting optional argument pointers. If the pointer is `NULL`, the function simply returns `false`. Otherwise, the value is assigned to the variable the pointer points to. - -```c++ -const char *plugh(size_t *outputsize) { - char res[] = "xyzzy"; - if !(NanSetPointerSafe(outputsize, strlen(res) + 1)) { - ... - } - - ... -} -``` - - -### void* NanRawString(Handle<Value>, enum Nan::Encoding, size_t *, void *, size_t, int) - -Deprecated. Use something else. - -When you want to convert a V8 `String` to a `char*` buffer, use `NanRawString`. You have to supply an encoding as well as a pointer to a variable that will be assigned the number of bytes in the returned string. It is also possible to supply a buffer and its length to the function in order not to have a new buffer allocated. The final argument allows setting `String::WriteOptions`. -Just remember that you'll end up with an object that you'll need to `delete[]` at some point unless you supply your own buffer: - -```c++ -size_t count; -void* decoded = NanRawString(args[1], Nan::BASE64, &count, NULL, 0, String::HINT_MANY_WRITES_EXPECTED); -... -delete[] reinterpret_cast(decoded); -``` - - -### char* NanCString(Handle<Value>, size_t *[, char *, size_t, int]) - -Deprecated. Use `NanUtf8String` instead. - -When you want to convert a V8 `String` to a null-terminated C `char*` use `NanCString`. The resulting `char*` will be UTF-8-encoded, and you need to supply a pointer to a variable that will be assigned the number of bytes in the returned string. It is also possible to supply a buffer and its length to the function in order not to have a new buffer allocated. The final argument allows optionally setting `String::WriteOptions`, which default to `v8::String::NO_OPTIONS`. -Just remember that you'll end up with an object that you'll need to `delete[]` at some point unless you supply your own buffer: - -```c++ -size_t count; -char* name = NanCString(args[0], &count); -... -delete[] name; -``` - - -### NanAsciiString - -Convert a `String` to zero-terminated, Ascii-encoded `char *`. - -```c++ -NAN_METHOD(foo) { - NanScope(); - NanReturnValue(NanNew(*NanAsciiString(arg[0]))); -} -``` - - -### NanUtf8String - -Convert a `String` to zero-terminated, Utf8-encoded `char *`. - -```c++ -NAN_METHOD(foo) { - NanScope(); - NanReturnValue(NanNew(*NanUtf8String(arg[0]))); -} -``` - - -### NanUcs2String - -Convert a `String` to zero-terminated, Ucs2-encoded `uint16_t *`. - -```c++ -NAN_METHOD(foo) { - NanScope(); - NanReturnValue(NanNew(*NanUcs2String(arg[0]))); -} -``` - - -### bool NanBooleanOptionValue(Handle<Value>, Handle<String>[, bool]) - -When you have an "options" object that you need to fetch properties from, boolean options can be fetched with this pair. They check first if the object exists (`IsEmpty`), then if the object has the given property (`Has`) then they get and convert/coerce the property to a `bool`. - -The optional last parameter is the *default* value, which is `false` if left off: - -```c++ -// `foo` is false unless the user supplies a truthy value for it -bool foo = NanBooleanOptionValue(optionsObj, NanNew("foo")); -// `bar` is true unless the user supplies a falsy value for it -bool bar = NanBooleanOptionValueDefTrue(optionsObj, NanNew("bar"), true); -``` - - -### uint32_t NanUInt32OptionValue(Handle<Value>, Handle<String>, uint32_t) - -Similar to `NanBooleanOptionValue`, use `NanUInt32OptionValue` to fetch an integer option from your options object. Can be any kind of JavaScript `Number` and it will be coerced to an unsigned 32-bit integer. - -Requires all 3 arguments as a default is not optional: - -```c++ -uint32_t count = NanUInt32OptionValue(optionsObj, NanNew("count"), 1024); -``` - - -### NanError(message), NanTypeError(message), NanRangeError(message) - -For making `Error`, `TypeError` and `RangeError` objects. - -```c++ -Local res = NanError("you must supply a callback argument"); -``` - - -### NanThrowError(message), NanThrowTypeError(message), NanThrowRangeError(message), NanThrowError(Local<Value>), NanThrowError(Local<Value>, int) - -For throwing `Error`, `TypeError` and `RangeError` objects. - -```c++ -NanThrowError("you must supply a callback argument"); -``` - -Can also handle any custom object you may want to throw. If used with the error code argument, it will add the supplied error code to the error object as a property called `code`. - - -### Local<Object> NanNewBufferHandle(char *, uint32_t), Local<Object> NanNewBufferHandle(uint32_t) - -The `Buffer` API has changed a little in Node 0.11, this helper provides consistent access to `Buffer` creation: - -```c++ -NanNewBufferHandle((char*)value.data(), value.size()); -``` - -Can also be used to initialize a `Buffer` with just a `size` argument. - -Can also be supplied with a `NanFreeCallback` and a hint for the garbage collector. - - -### Local<Object> NanBufferUse(char*, uint32_t) - -`Buffer::New(char*, uint32_t)` prior to 0.11 would make a copy of the data. -While it was possible to get around this, it required a shim by passing a -callback. So the new API `Buffer::Use(char*, uint32_t)` was introduced to remove -needing to use this shim. - -`NanBufferUse` uses the `char*` passed as the backing data, and will free the -memory automatically when the weak callback is called. Keep this in mind, as -careless use can lead to "double free or corruption" and other cryptic failures. - - -### bool NanHasInstance(Persistent<FunctionTemplate>&, Handle<Value>) - -Can be used to check the type of an object to determine it is of a particular class you have already defined and have a `Persistent` handle for. - - -### Local<Context> NanNewContextHandle([ExtensionConfiguration*, Handle<ObjectTemplate>, Handle<Value>]) -Creates a new `Local` handle. - -```c++ -Local ftmpl = NanNew(); -Local otmpl = ftmpl->InstanceTemplate(); -Local ctx = NanNewContextHandle(NULL, otmpl); -``` - - -### Local<Context> NanGetCurrentContext() - -Gets the current context. - -```c++ -Local ctx = NanGetCurrentContext(); -``` - - -### void NanDisposePersistent(Persistent<T> &) - -Use `NanDisposePersistent` to dispose a `Persistent` handle. - -```c++ -NanDisposePersistent(persistentHandle); -``` - - -### NanAssignPersistent(handle, object) - -Use `NanAssignPersistent` to assign a non-`Persistent` handle to a `Persistent` one. You can no longer just declare a `Persistent` handle and assign directly to it later, you have to `Reset` it in Node 0.11, so this makes it easier. - -In general it is now better to place anything you want to protect from V8's garbage collector as properties of a generic `Object` and then assign that to a `Persistent`. This works in older versions of Node also if you use `NanAssignPersistent`: - -```c++ -Persistent persistentHandle; - -... - -Local obj = NanNew(); -obj->Set(NanNew("key"), keyHandle); // where keyHandle might be a Local -NanAssignPersistent(persistentHandle, obj) -``` - - -### _NanWeakCallbackInfo<T, P>* NanMakeWeakPersistent(Handle<T>, P*, _NanWeakCallbackInfo<T, P>::Callback) - -Creates a weak persistent handle with the supplied parameter and `NAN_WEAK_CALLBACK`. - -```c++ -NAN_WEAK_CALLBACK(weakCallback) { - -... - -} - -Local func; - -... - -int *parameter = new int(0); -NanMakeWeakPersistent(func, parameter, &weakCallback); -``` - - -### NanSetTemplate(templ, name, value [, attributes]) - -Use to add properties on object and function templates. - - -### NanSetPrototypeTemplate(templ, name, value [, attributes]) - -Use to add prototype properties on function templates. - - -### NanSetInstanceTemplate(templ, name, value [, attributes]) - -Use to add instance properties on function templates. - - -### NanMakeCallback(target, func, argc, argv) - -Use instead of `node::MakeCallback` to call javascript functions. This is the only proper way of calling functions. - - -### NanCompileScript(Handle s [, const ScriptOrigin& origin]) - -Use to create new scripts bound to the current context. - - -### NanRunScript(script) - -Use to run both bound and unbound scripts. - - -### NanAdjustExternalMemory(int change_in_bytes) - -Simply does `AdjustAmountOfExternalAllocatedMemory`, note that the argument and returned value have type `int`. - - -### NanAddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type_filter=kGCTypeAll) - -Simply does `AddGCEpilogueCallback` - - -### NanAddGCPrologueCallback(GCPrologueCallback callback, GCType gc_type_filter=kGCTypeAll) - -Simply does `AddGCPrologueCallback` - - -### NanRemoveGCEpilogueCallback(GCEpilogueCallback callback) - -Simply does `RemoveGCEpilogueCallback` - - -### NanRemoveGCPrologueCallback(GCPrologueCallback callback) - -Simply does `RemoveGCPrologueCallback` - - -### NanGetHeapStatistics(HeapStatistics *heap_statistics) - -Simply does `GetHeapStatistics` - - -### NanCallback - -Because of the difficulties imposed by the changes to `Persistent` handles in V8 in Node 0.11, creating `Persistent` versions of your `Handle` is annoyingly tricky. `NanCallback` makes it easier by taking your handle, making it persistent until the `NanCallback` is deleted and even providing a handy `Call()` method to fetch and execute the callback `Function`. - -```c++ -Local callbackHandle = args[0].As(); -NanCallback *callback = new NanCallback(callbackHandle); -// pass `callback` around and it's safe from GC until you: -delete callback; -``` - -You can execute the callback like so: - -```c++ -// no arguments: -callback->Call(0, NULL); - -// an error argument: -Handle argv[] = { - NanError(NanNew("fail!")) -}; -callback->Call(1, argv); - -// a success argument: -Handle argv[] = { - NanNull(), - NanNew("w00t!") -}; -callback->Call(2, argv); -``` - -`NanCallback` also has a `Local GetCallback()` method that you can use -to fetch a local handle to the underlying callback function, as well as a -`void SetFunction(Handle)` for setting the callback on the -`NanCallback`. You can check if a `NanCallback` is empty with the `bool IsEmpty()` method. Additionally a generic constructor is available for using -`NanCallback` without performing heap allocations. - - -### NanAsyncWorker - -`NanAsyncWorker` is an abstract class that you can subclass to have much of the annoying async queuing and handling taken care of for you. It can even store arbitrary V8 objects for you and have them persist while the async work is in progress. - -See a rough outline of the implementation: - -```c++ -class NanAsyncWorker { -public: - NanAsyncWorker (NanCallback *callback); - - // Clean up persistent handles and delete the *callback - virtual ~NanAsyncWorker (); - - // Check the `ErrorMessage()` and call HandleOKCallback() - // or HandleErrorCallback depending on whether it has been set or not - virtual void WorkComplete (); - - // You must implement this to do some async work. If there is an - // error then use `SetErrorMessage()` to set an error message and the callback will - // be passed that string in an Error object - virtual void Execute (); - - // Save a V8 object in a Persistent handle to protect it from GC - void SaveToPersistent(const char *key, Local &obj); - - // Fetch a stored V8 object (don't call from within `Execute()`) - Local GetFromPersistent(const char *key); - - // Get the error message (or NULL) - const char *ErrorMessage(); - - // Set an error message - void SetErrorMessage(const char *msg); - -protected: - // Default implementation calls the callback function with no arguments. - // Override this to return meaningful data - virtual void HandleOKCallback (); - - // Default implementation calls the callback function with an Error object - // wrapping the `errmsg` string - virtual void HandleErrorCallback (); -}; -``` - - -### NanAsyncQueueWorker(NanAsyncWorker *) - -`NanAsyncQueueWorker` will run a `NanAsyncWorker` asynchronously via libuv. Both the *execute* and *after_work* steps are taken care of for you—most of the logic for this is embedded in `NanAsyncWorker`. - -### Contributors - -NAN is only possible due to the excellent work of the following contributors: - - - - - - - - -
Rod VaggGitHub/rvaggTwitter/@rvagg
Benjamin ByholmGitHub/kkoopa-
Trevor NorrisGitHub/trevnorrisTwitter/@trevnorris
Nathan RajlichGitHub/TooTallNateTwitter/@TooTallNate
Brett LawsonGitHub/brett19Twitter/@brett19x
Ben NoordhuisGitHub/bnoordhuisTwitter/@bnoordhuis
- -Licence & copyright ------------------------ - -Copyright (c) 2014 NAN contributors (listed above). - -Native Abstractions for Node.js is licensed under an MIT +no-false-attribs license. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE file for more details. diff --git a/node_modules/mongodb/node_modules/kerberos/node_modules/nan/appveyor.yml b/node_modules/mongodb/node_modules/kerberos/node_modules/nan/appveyor.yml deleted file mode 100644 index 657eed6..0000000 --- a/node_modules/mongodb/node_modules/kerberos/node_modules/nan/appveyor.yml +++ /dev/null @@ -1,32 +0,0 @@ -# http://www.appveyor.com/docs/appveyor-yml - -# Test against these versions of Node.js. -environment: - matrix: - - nodejs_version: "0.8" - - nodejs_version: "0.10" - - nodejs_version: "0.11" - -# Install scripts. (runs after repo cloning) -install: - # Get the latest stable version of Node 0.STABLE.latest - - npm install npm - - move node_modules npm - - ps: Update-NodeJsInstallation (Get-NodeJsLatestBuild $env:nodejs_version) - # Typical npm stuff. - - npm/.bin/npm install - - npm/.bin/npm run rebuild-tests - -# Post-install test scripts. -test_script: - # Output useful info for debugging. - - node --version - - npm --version - - cmd: npm test - -# Don't actually build. -build: off - -# Set build version format here instead of in the admin panel. -version: "{build}" - diff --git a/node_modules/mongodb/node_modules/kerberos/node_modules/nan/include_dirs.js b/node_modules/mongodb/node_modules/kerberos/node_modules/nan/include_dirs.js deleted file mode 100644 index 4f1dfb4..0000000 --- a/node_modules/mongodb/node_modules/kerberos/node_modules/nan/include_dirs.js +++ /dev/null @@ -1 +0,0 @@ -console.log(require('path').relative('.', __dirname)); diff --git a/node_modules/mongodb/node_modules/kerberos/node_modules/nan/nan.h b/node_modules/mongodb/node_modules/kerberos/node_modules/nan/nan.h deleted file mode 100644 index 063de4e..0000000 --- a/node_modules/mongodb/node_modules/kerberos/node_modules/nan/nan.h +++ /dev/null @@ -1,2331 +0,0 @@ -/********************************************************************************** - * NAN - Native Abstractions for Node.js - * - * Copyright (c) 2014 NAN contributors: - * - Rod Vagg - * - Benjamin Byholm - * - Trevor Norris - * - Nathan Rajlich - * - Brett Lawson - * - Ben Noordhuis - * - * MIT +no-false-attribs License - * - * Version 1.3.0: current Node unstable: 0.11.13, Node stable: 0.10.30 - * - * See https://github.com/rvagg/nan for the latest update to this file - **********************************************************************************/ - -#ifndef NAN_H_ -#define NAN_H_ - -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(__GNUC__) && !defined(DEBUG) -# define NAN_INLINE inline __attribute__((always_inline)) -#elif defined(_MSC_VER) && !defined(DEBUG) -# define NAN_INLINE __forceinline -#else -# define NAN_INLINE inline -#endif - -#if defined(__GNUC__) && !V8_DISABLE_DEPRECATIONS -# define NAN_DEPRECATED __attribute__((deprecated)) -#elif defined(_MSC_VER) && !V8_DISABLE_DEPRECATIONS -# define NAN_DEPRECATED __declspec(deprecated) -#else -# define NAN_DEPRECATED -#endif - -// some generic helpers - -template NAN_INLINE bool NanSetPointerSafe( - T *var - , T val -) { - if (var) { - *var = val; - return true; - } else { - return false; - } -} - -template NAN_INLINE T NanGetPointerSafe( - T *var - , T fallback = reinterpret_cast(0) -) { - if (var) { - return *var; - } else { - return fallback; - } -} - -NAN_INLINE bool NanBooleanOptionValue( - v8::Local optionsObj - , v8::Handle opt, bool def -) { - if (def) { - return optionsObj.IsEmpty() - || !optionsObj->Has(opt) - || optionsObj->Get(opt)->BooleanValue(); - } else { - return !optionsObj.IsEmpty() - && optionsObj->Has(opt) - && optionsObj->Get(opt)->BooleanValue(); - } -} - -NAN_INLINE bool NanBooleanOptionValue( - v8::Local optionsObj - , v8::Handle opt -) { - return NanBooleanOptionValue(optionsObj, opt, false); -} - -NAN_INLINE uint32_t NanUInt32OptionValue( - v8::Local optionsObj - , v8::Handle opt - , uint32_t def -) { - return !optionsObj.IsEmpty() - && optionsObj->Has(opt) - && optionsObj->Get(opt)->IsNumber() - ? optionsObj->Get(opt)->Uint32Value() - : def; -} - -#if (NODE_MODULE_VERSION > 0x000B) -// Node 0.11+ (0.11.3 and below won't compile with these) - -# define _NAN_METHOD_ARGS_TYPE const v8::FunctionCallbackInfo& -# define _NAN_METHOD_ARGS _NAN_METHOD_ARGS_TYPE args -# define _NAN_METHOD_RETURN_TYPE void - -# define _NAN_GETTER_ARGS_TYPE const v8::PropertyCallbackInfo& -# define _NAN_GETTER_ARGS _NAN_GETTER_ARGS_TYPE args -# define _NAN_GETTER_RETURN_TYPE void - -# define _NAN_SETTER_ARGS_TYPE const v8::PropertyCallbackInfo& -# define _NAN_SETTER_ARGS _NAN_SETTER_ARGS_TYPE args -# define _NAN_SETTER_RETURN_TYPE void - -# define _NAN_PROPERTY_GETTER_ARGS_TYPE \ - const v8::PropertyCallbackInfo& -# define _NAN_PROPERTY_GETTER_ARGS _NAN_PROPERTY_GETTER_ARGS_TYPE args -# define _NAN_PROPERTY_GETTER_RETURN_TYPE void - -# define _NAN_PROPERTY_SETTER_ARGS_TYPE \ - const v8::PropertyCallbackInfo& -# define _NAN_PROPERTY_SETTER_ARGS _NAN_PROPERTY_SETTER_ARGS_TYPE args -# define _NAN_PROPERTY_SETTER_RETURN_TYPE void - -# define _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE \ - const v8::PropertyCallbackInfo& -# define _NAN_PROPERTY_ENUMERATOR_ARGS _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE args -# define _NAN_PROPERTY_ENUMERATOR_RETURN_TYPE void - -# define _NAN_PROPERTY_DELETER_ARGS_TYPE \ - const v8::PropertyCallbackInfo& -# define _NAN_PROPERTY_DELETER_ARGS \ - _NAN_PROPERTY_DELETER_ARGS_TYPE args -# define _NAN_PROPERTY_DELETER_RETURN_TYPE void - -# define _NAN_PROPERTY_QUERY_ARGS_TYPE \ - const v8::PropertyCallbackInfo& -# define _NAN_PROPERTY_QUERY_ARGS _NAN_PROPERTY_QUERY_ARGS_TYPE args -# define _NAN_PROPERTY_QUERY_RETURN_TYPE void - -# define _NAN_INDEX_GETTER_ARGS_TYPE \ - const v8::PropertyCallbackInfo& -# define _NAN_INDEX_GETTER_ARGS _NAN_INDEX_GETTER_ARGS_TYPE args -# define _NAN_INDEX_GETTER_RETURN_TYPE void - -# define _NAN_INDEX_SETTER_ARGS_TYPE \ - const v8::PropertyCallbackInfo& -# define _NAN_INDEX_SETTER_ARGS _NAN_INDEX_SETTER_ARGS_TYPE args -# define _NAN_INDEX_SETTER_RETURN_TYPE void - -# define _NAN_INDEX_ENUMERATOR_ARGS_TYPE \ - const v8::PropertyCallbackInfo& -# define _NAN_INDEX_ENUMERATOR_ARGS _NAN_INDEX_ENUMERATOR_ARGS_TYPE args -# define _NAN_INDEX_ENUMERATOR_RETURN_TYPE void - -# define _NAN_INDEX_DELETER_ARGS_TYPE \ - const v8::PropertyCallbackInfo& -# define _NAN_INDEX_DELETER_ARGS _NAN_INDEX_DELETER_ARGS_TYPE args -# define _NAN_INDEX_DELETER_RETURN_TYPE void - -# define _NAN_INDEX_QUERY_ARGS_TYPE \ - const v8::PropertyCallbackInfo& -# define _NAN_INDEX_QUERY_ARGS _NAN_INDEX_QUERY_ARGS_TYPE args -# define _NAN_INDEX_QUERY_RETURN_TYPE void - - typedef v8::FunctionCallback NanFunctionCallback; - - template - NAN_INLINE v8::Local NanNew() { - return T::New(v8::Isolate::GetCurrent()); - } - - template - NAN_INLINE v8::Local NanNew(P arg1) { - return T::New(v8::Isolate::GetCurrent(), arg1); - } - - template - NAN_INLINE v8::Local NanNew( - v8::Handle receiver - , int argc - , v8::Handle argv[] = 0) { - return v8::Signature::New(v8::Isolate::GetCurrent(), receiver, argc, argv); - } - - template - NAN_INLINE v8::Local NanNew( - NanFunctionCallback callback - , v8::Handle data = v8::Handle() - , v8::Handle signature = v8::Handle()) { - return T::New(v8::Isolate::GetCurrent(), callback, data, signature); - } - - template - NAN_INLINE v8::Local NanNew(v8::Handle arg1) { - return v8::Local::New(v8::Isolate::GetCurrent(), arg1); - } - - template - NAN_INLINE v8::Local NanNew(const v8::Persistent &arg1) { - return v8::Local::New(v8::Isolate::GetCurrent(), arg1); - } - - template - NAN_INLINE v8::Local NanNew(P arg1, int arg2) { - return T::New(v8::Isolate::GetCurrent(), arg1, arg2); - } - - template<> - NAN_INLINE v8::Local NanNew() { - return v8::Array::New(v8::Isolate::GetCurrent()); - } - - template<> - NAN_INLINE v8::Local NanNew(int length) { - return v8::Array::New(v8::Isolate::GetCurrent(), length); - } - - template<> - NAN_INLINE v8::Local NanNew(double time) { - return v8::Date::New(v8::Isolate::GetCurrent(), time).As(); - } - - template<> - NAN_INLINE v8::Local NanNew(int time) { - return v8::Date::New(v8::Isolate::GetCurrent(), time).As(); - } - - typedef v8::UnboundScript NanUnboundScript; - typedef v8::Script NanBoundScript; - - template - NAN_INLINE v8::Local NanNew( - P s - , const v8::ScriptOrigin& origin - ) { - v8::ScriptCompiler::Source source(s, origin); - return v8::ScriptCompiler::CompileUnbound( - v8::Isolate::GetCurrent(), &source); - } - - template<> - NAN_INLINE v8::Local NanNew( - v8::Local s - ) { - v8::ScriptCompiler::Source source(s); - return v8::ScriptCompiler::CompileUnbound( - v8::Isolate::GetCurrent(), &source); - } - - template<> - NAN_INLINE v8::Local NanNew(bool value) { - return v8::BooleanObject::New(value).As(); - } - - template<> - NAN_INLINE v8::Local - NanNew >( - v8::Local value) { - return v8::StringObject::New(value).As(); - } - - template<> - NAN_INLINE v8::Local - NanNew >( - v8::Handle value) { - return v8::StringObject::New(value).As(); - } - - template<> - NAN_INLINE v8::Local NanNew(double val) { - return v8::NumberObject::New( - v8::Isolate::GetCurrent(), val).As(); - } - - template - NAN_INLINE v8::Local NanNew( - v8::Handle pattern, v8::RegExp::Flags flags) { - return v8::RegExp::New(pattern, flags); - } - - template - NAN_INLINE v8::Local NanNew( - v8::Local pattern, v8::RegExp::Flags flags) { - return v8::RegExp::New(pattern, flags); - } - - template - NAN_INLINE v8::Local NanNew( - v8::Handle pattern, v8::RegExp::Flags flags) { - return v8::RegExp::New(pattern, flags); - } - - template - NAN_INLINE v8::Local NanNew( - v8::Local pattern, v8::RegExp::Flags flags) { - return v8::RegExp::New(pattern, flags); - } - - template<> - NAN_INLINE v8::Local NanNew(int32_t val) { - return v8::Uint32::NewFromUnsigned( - v8::Isolate::GetCurrent(), val)->ToUint32(); - } - - template<> - NAN_INLINE v8::Local NanNew(uint32_t val) { - return v8::Uint32::NewFromUnsigned( - v8::Isolate::GetCurrent(), val)->ToUint32(); - } - - template<> - NAN_INLINE v8::Local NanNew(int32_t val) { - return v8::Int32::New(v8::Isolate::GetCurrent(), val)->ToInt32(); - } - - template<> - NAN_INLINE v8::Local NanNew(uint32_t val) { - return v8::Int32::New(v8::Isolate::GetCurrent(), val)->ToInt32(); - } - - template<> - NAN_INLINE v8::Local NanNew( - char *arg - , int length) { - return v8::String::NewFromUtf8( - v8::Isolate::GetCurrent() - , arg - , v8::String::kNormalString - , length); - } - - template<> - NAN_INLINE v8::Local NanNew( - const char *arg - , int length) { - return v8::String::NewFromUtf8( - v8::Isolate::GetCurrent() - , arg - , v8::String::kNormalString - , length); - } - - template<> - NAN_INLINE v8::Local NanNew(char *arg) { - return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), arg); - } - - template<> - NAN_INLINE v8::Local NanNew( - const char *arg) { - return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), arg); - } - - template<> - NAN_INLINE v8::Local NanNew( - uint8_t *arg - , int length) { - return v8::String::NewFromOneByte( - v8::Isolate::GetCurrent() - , arg - , v8::String::kNormalString - , length); - } - - template<> - NAN_INLINE v8::Local NanNew( - const uint8_t *arg - , int length) { - return v8::String::NewFromOneByte( - v8::Isolate::GetCurrent() - , arg - , v8::String::kNormalString - , length); - } - - template<> - NAN_INLINE v8::Local NanNew(uint8_t *arg) { - return v8::String::NewFromOneByte(v8::Isolate::GetCurrent(), arg); - } - - template<> - NAN_INLINE v8::Local NanNew( - const uint8_t *arg) { - return v8::String::NewFromOneByte(v8::Isolate::GetCurrent(), arg); - } - - template<> - NAN_INLINE v8::Local NanNew( - uint16_t *arg - , int length) { - return v8::String::NewFromTwoByte( - v8::Isolate::GetCurrent() - , arg - , v8::String::kNormalString - , length); - } - - template<> - NAN_INLINE v8::Local NanNew( - const uint16_t *arg - , int length) { - return v8::String::NewFromTwoByte( - v8::Isolate::GetCurrent() - , arg - , v8::String::kNormalString - , length); - } - template<> - NAN_INLINE v8::Local NanNew( - uint16_t *arg) { - return v8::String::NewFromTwoByte(v8::Isolate::GetCurrent(), arg); - } - - template<> - NAN_INLINE v8::Local NanNew( - const uint16_t *arg) { - return v8::String::NewFromTwoByte(v8::Isolate::GetCurrent(), arg); - } - - template<> - NAN_INLINE v8::Local NanNew( - std::string arg) { - return NanNew(arg.c_str(), arg.size()); - } - - template<> - NAN_INLINE v8::Local NanNew() { - return v8::String::Empty(v8::Isolate::GetCurrent()); - } - - NAN_INLINE v8::Local NanNew(const char* arg, int length = -1) { - return NanNew(arg, length); - } - - NAN_INLINE v8::Local NanNew( - const uint8_t* arg - , int length = -1) { - return NanNew(arg, length); - } - - NAN_INLINE v8::Local NanNew( - const uint16_t* arg - , int length = -1) { - return NanNew(arg, length); - } - - NAN_INLINE v8::Local NanNew( - const std::string& arg) { - return NanNew(arg.c_str(), arg.size()); - } - - NAN_INLINE v8::Local NanNew(double val) { - return NanNew(val); - } - - NAN_INLINE v8::Local NanNew(int val) { - return NanNew(val); - } - - NAN_INLINE v8::Local NanNew(unsigned int val) { - return NanNew(val); - } - - NAN_INLINE v8::Local NanNew(bool val) { - return NanNew(val); - } - - NAN_INLINE v8::Local NanNew( - v8::String::ExternalStringResource *resource) { - return v8::String::NewExternal(v8::Isolate::GetCurrent(), resource); - } - - NAN_INLINE v8::Local NanNew( - v8::String::ExternalAsciiStringResource *resource) { - return v8::String::NewExternal(v8::Isolate::GetCurrent(), resource); - } - -# define NanScope() v8::HandleScope scope(v8::Isolate::GetCurrent()) -# define NanEscapableScope() \ - v8::EscapableHandleScope scope(v8::Isolate::GetCurrent()) - - template - NAN_INLINE v8::Local _NanEscapeScopeHelper(v8::Handle val) { - return NanNew(val); - } - - template - NAN_INLINE v8::Local _NanEscapeScopeHelper(v8::Local val) { - return val; - } - -# define NanEscapeScope(val) scope.Escape(_NanEscapeScopeHelper(val)) -# define NanLocker() v8::Locker locker(v8::Isolate::GetCurrent()) -# define NanUnlocker() v8::Unlocker unlocker(v8::Isolate::GetCurrent()) -# define NanReturnValue(value) return args.GetReturnValue().Set(value) -# define NanReturnUndefined() return -# define NanReturnNull() return args.GetReturnValue().SetNull() -# define NanReturnEmptyString() return args.GetReturnValue().SetEmptyString() - -# define NanObjectWrapHandle(obj) obj->handle() - - NAN_INLINE v8::Local NanUndefined() { - NanEscapableScope(); - return NanEscapeScope(NanNew(v8::Undefined(v8::Isolate::GetCurrent()))); - } - - NAN_INLINE v8::Local NanNull() { - NanEscapableScope(); - return NanEscapeScope(NanNew(v8::Null(v8::Isolate::GetCurrent()))); - } - - NAN_INLINE v8::Local NanTrue() { - NanEscapableScope(); - return NanEscapeScope(NanNew(v8::True(v8::Isolate::GetCurrent()))); - } - - NAN_INLINE v8::Local NanFalse() { - NanEscapableScope(); - return NanEscapeScope(NanNew(v8::False(v8::Isolate::GetCurrent()))); - } - - NAN_INLINE int NanAdjustExternalMemory(int bc) { - return static_cast( - v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(bc)); - } - - NAN_INLINE void NanSetTemplate( - v8::Handle templ - , const char *name - , v8::Handle value) { - templ->Set(v8::Isolate::GetCurrent(), name, value); - } - - NAN_INLINE void NanSetTemplate( - v8::Handle templ - , v8::Handle name - , v8::Handle value - , v8::PropertyAttribute attributes) { - templ->Set(name, value, attributes); - } - - NAN_INLINE v8::Local NanGetCurrentContext() { - return v8::Isolate::GetCurrent()->GetCurrentContext(); - } - - NAN_INLINE void* NanGetInternalFieldPointer( - v8::Handle object - , int index) { - return object->GetAlignedPointerFromInternalField(index); - } - - NAN_INLINE void NanSetInternalFieldPointer( - v8::Handle object - , int index - , void* value) { - object->SetAlignedPointerInInternalField(index, value); - } - - NAN_INLINE void NanAddGCEpilogueCallback( - v8::Isolate::GCEpilogueCallback callback - , v8::GCType gc_type_filter = v8::kGCTypeAll) { - v8::Isolate::GetCurrent()->AddGCEpilogueCallback(callback, gc_type_filter); - } - - NAN_INLINE void NanRemoveGCEpilogueCallback( - v8::Isolate::GCEpilogueCallback callback) { - v8::Isolate::GetCurrent()->RemoveGCEpilogueCallback(callback); - } - - NAN_INLINE void NanAddGCPrologueCallback( - v8::Isolate::GCPrologueCallback callback - , v8::GCType gc_type_filter = v8::kGCTypeAll) { - v8::Isolate::GetCurrent()->AddGCPrologueCallback(callback, gc_type_filter); - } - - NAN_INLINE void NanRemoveGCPrologueCallback( - v8::Isolate::GCPrologueCallback callback) { - v8::Isolate::GetCurrent()->RemoveGCPrologueCallback(callback); - } - - NAN_INLINE void NanGetHeapStatistics( - v8::HeapStatistics *heap_statistics) { - v8::Isolate::GetCurrent()->GetHeapStatistics(heap_statistics); - } - - NAN_DEPRECATED NAN_INLINE v8::Local NanSymbol( - const char* data, int length = -1) { - return NanNew(data, length); - } - - template - NAN_INLINE void NanAssignPersistent( - v8::Persistent& handle - , v8::Handle obj) { - handle.Reset(v8::Isolate::GetCurrent(), obj); - } - - template - NAN_INLINE void NanAssignPersistent( - v8::Persistent& handle - , const v8::Persistent& obj) { - handle.Reset(v8::Isolate::GetCurrent(), obj); - } - - template - class _NanWeakCallbackData; - - template - struct _NanWeakCallbackInfo { - typedef void (*Callback)(const _NanWeakCallbackData& data); - NAN_INLINE _NanWeakCallbackInfo(v8::Handle handle, P* param, Callback cb) - : parameter(param), callback(cb) { - NanAssignPersistent(persistent, handle); - } - - NAN_INLINE ~_NanWeakCallbackInfo() { - persistent.Reset(); - } - - P* const parameter; - Callback const callback; - v8::Persistent persistent; - }; - - template - class _NanWeakCallbackData { - public: - NAN_INLINE _NanWeakCallbackData(_NanWeakCallbackInfo *info) - : info_(info) { } - - NAN_INLINE v8::Local GetValue() const { - return NanNew(info_->persistent); - } - - NAN_INLINE P* GetParameter() const { return info_->parameter; } - - NAN_INLINE bool IsNearDeath() const { - return info_->persistent.IsNearDeath(); - } - - NAN_INLINE void Revive() const; - - NAN_INLINE _NanWeakCallbackInfo* GetCallbackInfo() const { - return info_; - } - - NAN_DEPRECATED NAN_INLINE void Dispose() const { - } - - private: - _NanWeakCallbackInfo* info_; - }; - - template - static void _NanWeakCallbackDispatcher( - const v8::WeakCallbackData > &data) { - _NanWeakCallbackInfo *info = data.GetParameter(); - _NanWeakCallbackData wcbd(info); - info->callback(wcbd); - if (wcbd.IsNearDeath()) { - delete wcbd.GetCallbackInfo(); - } - } - - template - NAN_INLINE void _NanWeakCallbackData::Revive() const { - info_->persistent.SetWeak(info_, &_NanWeakCallbackDispatcher); - } - -template -NAN_INLINE _NanWeakCallbackInfo* NanMakeWeakPersistent( - v8::Handle handle - , P* parameter - , typename _NanWeakCallbackInfo::Callback callback) { - _NanWeakCallbackInfo *cbinfo = - new _NanWeakCallbackInfo(handle, parameter, callback); - cbinfo->persistent.SetWeak(cbinfo, &_NanWeakCallbackDispatcher); - return cbinfo; -} - -# define NAN_WEAK_CALLBACK(name) \ - template \ - static void name(const _NanWeakCallbackData &data) - -# define _NAN_ERROR(fun, errmsg) fun(NanNew(errmsg)) - -# define _NAN_THROW_ERROR(fun, errmsg) \ - do { \ - NanScope(); \ - v8::Isolate::GetCurrent()->ThrowException(_NAN_ERROR(fun, errmsg)); \ - } while (0); - - NAN_INLINE v8::Local NanError(const char* errmsg) { - return _NAN_ERROR(v8::Exception::Error, errmsg); - } - - NAN_INLINE void NanThrowError(const char* errmsg) { - _NAN_THROW_ERROR(v8::Exception::Error, errmsg); - } - - NAN_INLINE void NanThrowError(v8::Handle error) { - NanScope(); - v8::Isolate::GetCurrent()->ThrowException(error); - } - - NAN_INLINE v8::Local NanError( - const char *msg - , const int errorNumber - ) { - v8::Local err = v8::Exception::Error(NanNew(msg)); - v8::Local obj = err.As(); - obj->Set(NanNew("code"), NanNew(errorNumber)); - return err; - } - - NAN_INLINE void NanThrowError( - const char *msg - , const int errorNumber - ) { - NanThrowError(NanError(msg, errorNumber)); - } - - NAN_INLINE v8::Local NanTypeError(const char* errmsg) { - return _NAN_ERROR(v8::Exception::TypeError, errmsg); - } - - NAN_INLINE void NanThrowTypeError(const char* errmsg) { - _NAN_THROW_ERROR(v8::Exception::TypeError, errmsg); - } - - NAN_INLINE v8::Local NanRangeError(const char* errmsg) { - return _NAN_ERROR(v8::Exception::RangeError, errmsg); - } - - NAN_INLINE void NanThrowRangeError(const char* errmsg) { - _NAN_THROW_ERROR(v8::Exception::RangeError, errmsg); - } - - template NAN_INLINE void NanDisposePersistent( - v8::Persistent &handle - ) { - handle.Reset(); - } - - NAN_INLINE v8::Local NanNewBufferHandle ( - char *data - , size_t length - , node::smalloc::FreeCallback callback - , void *hint - ) { - return node::Buffer::New( - v8::Isolate::GetCurrent(), data, length, callback, hint); - } - - NAN_INLINE v8::Local NanNewBufferHandle ( - const char *data - , uint32_t size - ) { - return node::Buffer::New(v8::Isolate::GetCurrent(), data, size); - } - - NAN_INLINE v8::Local NanNewBufferHandle (uint32_t size) { - return node::Buffer::New(v8::Isolate::GetCurrent(), size); - } - - NAN_INLINE v8::Local NanBufferUse( - char* data - , uint32_t size - ) { - return node::Buffer::Use(v8::Isolate::GetCurrent(), data, size); - } - - NAN_INLINE bool NanHasInstance( - v8::Persistent& function_template - , v8::Handle value - ) { - return NanNew(function_template)->HasInstance(value); - } - - NAN_INLINE v8::Local NanNewContextHandle( - v8::ExtensionConfiguration* extensions = NULL - , v8::Handle tmpl = v8::Handle() - , v8::Handle obj = v8::Handle() - ) { - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - return v8::Local::New( - isolate - , v8::Context::New(isolate, extensions, tmpl, obj) - ); - } - - NAN_INLINE v8::Local NanCompileScript( - v8::Local s - , const v8::ScriptOrigin& origin - ) { - v8::ScriptCompiler::Source source(s, origin); - return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &source); - } - - NAN_INLINE v8::Local NanCompileScript( - v8::Local s - ) { - v8::ScriptCompiler::Source source(s); - return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &source); - } - - NAN_INLINE v8::Local NanRunScript( - v8::Handle script - ) { - return script->BindToCurrentContext()->Run(); - } - - NAN_INLINE v8::Local NanRunScript( - v8::Handle script - ) { - return script->Run(); - } - - NAN_INLINE v8::Local NanMakeCallback( - v8::Handle target - , v8::Handle func - , int argc - , v8::Handle* argv) { - return NanNew(node::MakeCallback( - v8::Isolate::GetCurrent(), target, func, argc, argv)); - } - - NAN_INLINE v8::Local NanMakeCallback( - v8::Handle target - , v8::Handle symbol - , int argc - , v8::Handle* argv) { - return NanNew(node::MakeCallback( - v8::Isolate::GetCurrent(), target, symbol, argc, argv)); - } - - NAN_INLINE v8::Local NanMakeCallback( - v8::Handle target - , const char* method - , int argc - , v8::Handle* argv) { - return NanNew(node::MakeCallback( - v8::Isolate::GetCurrent(), target, method, argc, argv)); - } - - template - NAN_INLINE void NanSetIsolateData( - v8::Isolate *isolate - , T *data - ) { - isolate->SetData(0, data); - } - - template - NAN_INLINE T *NanGetIsolateData( - v8::Isolate *isolate - ) { - return static_cast(isolate->GetData(0)); - } - - class NanAsciiString { - public: - NAN_INLINE explicit NanAsciiString(v8::Handle from) { - v8::Local toStr = from->ToString(); - int buf_size = toStr->Length() + 1; - buf = new char[buf_size]; - size = toStr->WriteOneByte( - reinterpret_cast(buf), 0, buf_size); - } - - NAN_INLINE int Size() const { - return size; - } - - NAN_INLINE char* operator*() { return buf; } - - NAN_INLINE ~NanAsciiString() { - delete[] buf; - } - - private: - char *buf; - int size; - }; - - class NanUtf8String { - public: - NAN_INLINE explicit NanUtf8String(v8::Handle from) { - v8::Local toStr = from->ToString(); - int buf_size = toStr->Utf8Length() + 1; - buf = new char[buf_size]; - size = toStr->WriteUtf8(buf, buf_size); - } - - NAN_INLINE int Size() const { - return size; - } - - NAN_INLINE char* operator*() { return buf; } - - NAN_INLINE ~NanUtf8String() { - delete[] buf; - } - - private: - char *buf; - int size; - }; - - class NanUcs2String { - public: - NAN_INLINE explicit NanUcs2String(v8::Handle from) { - v8::Local toStr = from->ToString(); - int buf_size = toStr->Length() + 1; - buf = new uint16_t[buf_size]; - size = toStr->Write(buf, 0, buf_size); - } - - NAN_INLINE int Size() const { - return size; - } - - NAN_INLINE uint16_t* operator*() { return buf; } - - NAN_INLINE ~NanUcs2String() { - delete[] buf; - } - - private: - uint16_t *buf; - int size; - }; - -#else -// Node 0.8 and 0.10 - -# define _NAN_METHOD_ARGS_TYPE const v8::Arguments& -# define _NAN_METHOD_ARGS _NAN_METHOD_ARGS_TYPE args -# define _NAN_METHOD_RETURN_TYPE v8::Handle - -# define _NAN_GETTER_ARGS_TYPE const v8::AccessorInfo & -# define _NAN_GETTER_ARGS _NAN_GETTER_ARGS_TYPE args -# define _NAN_GETTER_RETURN_TYPE v8::Handle - -# define _NAN_SETTER_ARGS_TYPE const v8::AccessorInfo & -# define _NAN_SETTER_ARGS _NAN_SETTER_ARGS_TYPE args -# define _NAN_SETTER_RETURN_TYPE void - -# define _NAN_PROPERTY_GETTER_ARGS_TYPE const v8::AccessorInfo& -# define _NAN_PROPERTY_GETTER_ARGS _NAN_PROPERTY_GETTER_ARGS_TYPE args -# define _NAN_PROPERTY_GETTER_RETURN_TYPE v8::Handle - -# define _NAN_PROPERTY_SETTER_ARGS_TYPE const v8::AccessorInfo& -# define _NAN_PROPERTY_SETTER_ARGS _NAN_PROPERTY_SETTER_ARGS_TYPE args -# define _NAN_PROPERTY_SETTER_RETURN_TYPE v8::Handle - -# define _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE const v8::AccessorInfo& -# define _NAN_PROPERTY_ENUMERATOR_ARGS _NAN_PROPERTY_ENUMERATOR_ARGS_TYPE args -# define _NAN_PROPERTY_ENUMERATOR_RETURN_TYPE v8::Handle - -# define _NAN_PROPERTY_DELETER_ARGS_TYPE const v8::AccessorInfo& -# define _NAN_PROPERTY_DELETER_ARGS _NAN_PROPERTY_DELETER_ARGS_TYPE args -# define _NAN_PROPERTY_DELETER_RETURN_TYPE v8::Handle - -# define _NAN_PROPERTY_QUERY_ARGS_TYPE const v8::AccessorInfo& -# define _NAN_PROPERTY_QUERY_ARGS _NAN_PROPERTY_QUERY_ARGS_TYPE args -# define _NAN_PROPERTY_QUERY_RETURN_TYPE v8::Handle - -# define _NAN_INDEX_GETTER_ARGS_TYPE const v8::AccessorInfo& -# define _NAN_INDEX_GETTER_ARGS _NAN_INDEX_GETTER_ARGS_TYPE args -# define _NAN_INDEX_GETTER_RETURN_TYPE v8::Handle - -# define _NAN_INDEX_SETTER_ARGS_TYPE const v8::AccessorInfo& -# define _NAN_INDEX_SETTER_ARGS _NAN_INDEX_SETTER_ARGS_TYPE args -# define _NAN_INDEX_SETTER_RETURN_TYPE v8::Handle - -# define _NAN_INDEX_ENUMERATOR_ARGS_TYPE const v8::AccessorInfo& -# define _NAN_INDEX_ENUMERATOR_ARGS _NAN_INDEX_ENUMERATOR_ARGS_TYPE args -# define _NAN_INDEX_ENUMERATOR_RETURN_TYPE v8::Handle - -# define _NAN_INDEX_DELETER_ARGS_TYPE const v8::AccessorInfo& -# define _NAN_INDEX_DELETER_ARGS _NAN_INDEX_DELETER_ARGS_TYPE args -# define _NAN_INDEX_DELETER_RETURN_TYPE v8::Handle - -# define _NAN_INDEX_QUERY_ARGS_TYPE const v8::AccessorInfo& -# define _NAN_INDEX_QUERY_ARGS _NAN_INDEX_QUERY_ARGS_TYPE args -# define _NAN_INDEX_QUERY_RETURN_TYPE v8::Handle - - typedef v8::InvocationCallback NanFunctionCallback; - - NAN_DEPRECATED NAN_INLINE v8::Local NanSymbol( - const char* data, int length = -1) { - return v8::String::NewSymbol(data, length); - } - - template - NAN_INLINE v8::Local NanNew() { - return v8::Local::New(T::New()); - } - - template - NAN_INLINE v8::Local NanNew(v8::Handle arg) { - return v8::Local::New(arg); - } - - template - NAN_INLINE v8::Local NanNew( - v8::Handle receiver - , int argc - , v8::Handle argv[] = 0) { - return v8::Signature::New(receiver, argc, argv); - } - - template - NAN_INLINE v8::Local NanNew( - NanFunctionCallback callback - , v8::Handle data = v8::Handle() - , v8::Handle signature = v8::Handle()) { - return T::New(callback, data, signature); - } - - template - NAN_INLINE v8::Local NanNew(const v8::Persistent &arg) { - return v8::Local::New(arg); - } - - template - NAN_INLINE v8::Local NanNew(P arg) { - return v8::Local::New(T::New(arg)); - } - - template - NAN_INLINE v8::Local NanNew(P arg, int length) { - return v8::Local::New(T::New(arg, length)); - } - - template - NAN_INLINE v8::Local NanNew( - v8::Handle pattern, v8::RegExp::Flags flags) { - return v8::RegExp::New(pattern, flags); - } - - template - NAN_INLINE v8::Local NanNew( - v8::Local pattern, v8::RegExp::Flags flags) { - return v8::RegExp::New(pattern, flags); - } - - template - NAN_INLINE v8::Local NanNew( - v8::Handle pattern, v8::RegExp::Flags flags) { - return v8::RegExp::New(pattern, flags); - } - - template - NAN_INLINE v8::Local NanNew( - v8::Local pattern, v8::RegExp::Flags flags) { - return v8::RegExp::New(pattern, flags); - } - - template<> - NAN_INLINE v8::Local NanNew() { - return v8::Array::New(); - } - - template<> - NAN_INLINE v8::Local NanNew(int length) { - return v8::Array::New(length); - } - - template<> - NAN_INLINE v8::Local NanNew(double time) { - return v8::Date::New(time).As(); - } - - template<> - NAN_INLINE v8::Local NanNew(int time) { - return v8::Date::New(time).As(); - } - - typedef v8::Script NanUnboundScript; - typedef v8::Script NanBoundScript; - - template - NAN_INLINE v8::Local NanNew( - P s - , const v8::ScriptOrigin& origin - ) { - return v8::Script::New(s, const_cast(&origin)); - } - - template<> - NAN_INLINE v8::Local NanNew( - v8::Local s - ) { - return v8::Script::New(s); - } - - template<> - NAN_INLINE v8::Local NanNew(bool value) { - return v8::BooleanObject::New(value).As(); - } - - template<> - NAN_INLINE v8::Local - NanNew >( - v8::Local value) { - return v8::StringObject::New(value).As(); - } - - template<> - NAN_INLINE v8::Local - NanNew >( - v8::Handle value) { - return v8::StringObject::New(value).As(); - } - - template<> - NAN_INLINE v8::Local NanNew(double val) { - return v8::NumberObject::New(val).As(); - } - - template<> - NAN_INLINE v8::Local NanNew(int32_t val) { - return v8::Uint32::NewFromUnsigned(val)->ToUint32(); - } - - template<> - NAN_INLINE v8::Local NanNew(uint32_t val) { - return v8::Uint32::NewFromUnsigned(val)->ToUint32(); - } - - template<> - NAN_INLINE v8::Local NanNew(int32_t val) { - return v8::Int32::New(val)->ToInt32(); - } - - template<> - NAN_INLINE v8::Local NanNew(uint32_t val) { - return v8::Int32::New(val)->ToInt32(); - } - - template<> - NAN_INLINE v8::Local NanNew( - uint8_t *arg - , int length) { - int len = length; - if (len < 0) { - size_t temp = strlen(reinterpret_cast(arg)); - assert(temp <= INT_MAX && "too long string"); - len = static_cast(temp); - } - uint16_t *warg = new uint16_t[len]; - for (int i = 0; i < len; i++) { - warg[i] = arg[i]; - } - v8::Local retval = v8::String::New(warg, len); - delete[] warg; - return retval; - } - - template<> - NAN_INLINE v8::Local NanNew( - const uint8_t *arg - , int length) { - int len = length; - if (len < 0) { - size_t temp = strlen(reinterpret_cast(arg)); - assert(temp <= INT_MAX && "too long string"); - len = static_cast(temp); - } - uint16_t *warg = new uint16_t[len]; - for (int i = 0; i < len; i++) { - warg[i] = arg[i]; - } - v8::Local retval = v8::String::New(warg, len); - delete[] warg; - return retval; - } - - template<> - NAN_INLINE v8::Local NanNew(uint8_t *arg) { - size_t temp = strlen(reinterpret_cast(arg)); - assert(temp <= INT_MAX && "too long string"); - int length = static_cast(temp); - uint16_t *warg = new uint16_t[length]; - for (int i = 0; i < length; i++) { - warg[i] = arg[i]; - } - - v8::Local retval = v8::String::New(warg, length); - delete[] warg; - return retval; - } - - template<> - NAN_INLINE v8::Local NanNew( - const uint8_t *arg) { - size_t temp = strlen(reinterpret_cast(arg)); - assert(temp <= INT_MAX && "too long string"); - int length = static_cast(temp); - uint16_t *warg = new uint16_t[length]; - for (int i = 0; i < length; i++) { - warg[i] = arg[i]; - } - v8::Local retval = v8::String::New(warg, length); - delete[] warg; - return retval; - } - - template<> - NAN_INLINE v8::Local NanNew( - std::string arg) { - return NanNew(arg.c_str(), arg.size()); - } - - template<> - NAN_INLINE v8::Local NanNew() { - return v8::String::Empty(); - } - - NAN_INLINE v8::Local NanNew(const char* arg, int length = -1) { - return NanNew(arg, length); - } - - NAN_INLINE v8::Local NanNew( - const uint8_t* arg - , int length = -1) { - return NanNew(arg, length); - } - - NAN_INLINE v8::Local NanNew( - const uint16_t* arg - , int length = -1) { - return NanNew(arg, length); - } - - NAN_INLINE v8::Local NanNew( - std::string& arg) { - return NanNew(arg.c_str(), arg.size()); - } - - NAN_INLINE v8::Local NanNew(double val) { - return NanNew(val); - } - - NAN_INLINE v8::Local NanNew(int val) { - return NanNew(val); - } - - NAN_INLINE v8::Local NanNew(unsigned int val) { - return NanNew(val); - } - - NAN_INLINE v8::Local NanNew(bool val) { - return NanNew(val); - } - - NAN_INLINE v8::Local NanNew( - v8::String::ExternalStringResource *resource) { - return v8::String::NewExternal(resource); - } - - NAN_INLINE v8::Local NanNew( - v8::String::ExternalAsciiStringResource *resource) { - return v8::String::NewExternal(resource); - } - -# define NanScope() v8::HandleScope scope -# define NanEscapableScope() v8::HandleScope scope -# define NanEscapeScope(val) scope.Close(val) -# define NanLocker() v8::Locker locker -# define NanUnlocker() v8::Unlocker unlocker -# define NanReturnValue(value) return scope.Close(value) -# define NanReturnUndefined() return v8::Undefined() -# define NanReturnNull() return v8::Null() -# define NanReturnEmptyString() return v8::String::Empty() -# define NanObjectWrapHandle(obj) v8::Local::New(obj->handle_) - - NAN_INLINE v8::Local NanUndefined() { - NanEscapableScope(); - return NanEscapeScope(NanNew(v8::Undefined())); - } - - NAN_INLINE v8::Local NanNull() { - NanEscapableScope(); - return NanEscapeScope(NanNew(v8::Null())); - } - - NAN_INLINE v8::Local NanTrue() { - NanEscapableScope(); - return NanEscapeScope(NanNew(v8::True())); - } - - NAN_INLINE v8::Local NanFalse() { - NanEscapableScope(); - return NanEscapeScope(NanNew(v8::False())); - } - - NAN_INLINE int NanAdjustExternalMemory(int bc) { - return static_cast(v8::V8::AdjustAmountOfExternalAllocatedMemory(bc)); - } - - NAN_INLINE void NanSetTemplate( - v8::Handle templ - , const char *name - , v8::Handle value) { - templ->Set(name, value); - } - - NAN_INLINE void NanSetTemplate( - v8::Handle templ - , v8::Handle name - , v8::Handle value - , v8::PropertyAttribute attributes) { - templ->Set(name, value, attributes); - } - - NAN_INLINE v8::Local NanGetCurrentContext() { - return v8::Context::GetCurrent(); - } - - NAN_INLINE void* NanGetInternalFieldPointer( - v8::Handle object - , int index) { - return object->GetPointerFromInternalField(index); - } - - NAN_INLINE void NanSetInternalFieldPointer( - v8::Handle object - , int index - , void* value) { - object->SetPointerInInternalField(index, value); - } - - NAN_INLINE void NanAddGCEpilogueCallback( - v8::GCEpilogueCallback callback - , v8::GCType gc_type_filter = v8::kGCTypeAll) { - v8::V8::AddGCEpilogueCallback(callback, gc_type_filter); - } - NAN_INLINE void NanRemoveGCEpilogueCallback( - v8::GCEpilogueCallback callback) { - v8::V8::RemoveGCEpilogueCallback(callback); - } - NAN_INLINE void NanAddGCPrologueCallback( - v8::GCPrologueCallback callback - , v8::GCType gc_type_filter = v8::kGCTypeAll) { - v8::V8::AddGCPrologueCallback(callback, gc_type_filter); - } - NAN_INLINE void NanRemoveGCPrologueCallback( - v8::GCPrologueCallback callback) { - v8::V8::RemoveGCPrologueCallback(callback); - } - NAN_INLINE void NanGetHeapStatistics( - v8::HeapStatistics *heap_statistics) { - v8::V8::GetHeapStatistics(heap_statistics); - } - - template - NAN_INLINE void NanAssignPersistent( - v8::Persistent& handle - , v8::Handle obj) { - handle.Dispose(); - handle = v8::Persistent::New(obj); - } - - template - class _NanWeakCallbackData; - - template - struct _NanWeakCallbackInfo { - typedef void (*Callback)(const _NanWeakCallbackData &data); - NAN_INLINE _NanWeakCallbackInfo(v8::Handle handle, P* param, Callback cb) - : parameter(param) - , callback(cb) - , persistent(v8::Persistent::New(handle)) { } - - NAN_INLINE ~_NanWeakCallbackInfo() { - persistent.Dispose(); - persistent.Clear(); - } - - P* const parameter; - Callback const callback; - v8::Persistent persistent; - }; - - template - class _NanWeakCallbackData { - public: - NAN_INLINE _NanWeakCallbackData(_NanWeakCallbackInfo *info) - : info_(info) { } - - NAN_INLINE v8::Local GetValue() const { - return NanNew(info_->persistent); - } - - NAN_INLINE P* GetParameter() const { return info_->parameter; } - - NAN_INLINE bool IsNearDeath() const { - return info_->persistent.IsNearDeath(); - } - - NAN_INLINE void Revive() const; - - NAN_INLINE _NanWeakCallbackInfo* GetCallbackInfo() const { - return info_; - } - - NAN_DEPRECATED NAN_INLINE void Dispose() const { - } - - private: - _NanWeakCallbackInfo* info_; - }; - - template - static void _NanWeakPersistentDispatcher( - v8::Persistent object, void *data) { - _NanWeakCallbackInfo* info = - static_cast<_NanWeakCallbackInfo*>(data); - _NanWeakCallbackData wcbd(info); - info->callback(wcbd); - if (wcbd.IsNearDeath()) { - delete wcbd.GetCallbackInfo(); - } - } - - template - NAN_INLINE void _NanWeakCallbackData::Revive() const { - info_->persistent.MakeWeak( - info_ - , &_NanWeakPersistentDispatcher); - } - - template - NAN_INLINE _NanWeakCallbackInfo* NanMakeWeakPersistent( - v8::Handle handle - , P* parameter - , typename _NanWeakCallbackInfo::Callback callback) { - _NanWeakCallbackInfo *cbinfo = - new _NanWeakCallbackInfo(handle, parameter, callback); - cbinfo->persistent.MakeWeak( - cbinfo - , &_NanWeakPersistentDispatcher); - return cbinfo; - } - -# define NAN_WEAK_CALLBACK(name) \ - template \ - static void name(const _NanWeakCallbackData &data) - -# define _NAN_ERROR(fun, errmsg) \ - fun(v8::String::New(errmsg)) - -# define _NAN_THROW_ERROR(fun, errmsg) \ - do { \ - NanScope(); \ - return v8::Local::New( \ - v8::ThrowException(_NAN_ERROR(fun, errmsg))); \ - } while (0); - - NAN_INLINE v8::Local NanError(const char* errmsg) { - return _NAN_ERROR(v8::Exception::Error, errmsg); - } - - NAN_INLINE v8::Local NanThrowError(const char* errmsg) { - _NAN_THROW_ERROR(v8::Exception::Error, errmsg); - } - - NAN_INLINE v8::Local NanThrowError( - v8::Handle error - ) { - NanScope(); - return v8::Local::New(v8::ThrowException(error)); - } - - NAN_INLINE v8::Local NanError( - const char *msg - , const int errorNumber - ) { - v8::Local err = v8::Exception::Error(v8::String::New(msg)); - v8::Local obj = err.As(); - obj->Set(v8::String::New("code"), v8::Int32::New(errorNumber)); - return err; - } - - NAN_INLINE v8::Local NanThrowError( - const char *msg - , const int errorNumber - ) { - return NanThrowError(NanError(msg, errorNumber)); - } - - NAN_INLINE v8::Local NanTypeError(const char* errmsg) { - return _NAN_ERROR(v8::Exception::TypeError, errmsg); - } - - NAN_INLINE v8::Local NanThrowTypeError( - const char* errmsg - ) { - _NAN_THROW_ERROR(v8::Exception::TypeError, errmsg); - } - - NAN_INLINE v8::Local NanRangeError( - const char* errmsg - ) { - return _NAN_ERROR(v8::Exception::RangeError, errmsg); - } - - NAN_INLINE v8::Local NanThrowRangeError( - const char* errmsg - ) { - _NAN_THROW_ERROR(v8::Exception::RangeError, errmsg); - } - - template - NAN_INLINE void NanDisposePersistent( - v8::Persistent &handle) { // NOLINT(runtime/references) - handle.Dispose(); - handle.Clear(); - } - - NAN_INLINE v8::Local NanNewBufferHandle ( - char *data - , size_t length - , node::Buffer::free_callback callback - , void *hint - ) { - return NanNew( - node::Buffer::New(data, length, callback, hint)->handle_); - } - - NAN_INLINE v8::Local NanNewBufferHandle ( - const char *data - , uint32_t size - ) { -#if NODE_MODULE_VERSION >= 0x000B - return NanNew(node::Buffer::New(data, size)->handle_); -#else - return NanNew( - node::Buffer::New(const_cast(data), size)->handle_); -#endif - } - - NAN_INLINE v8::Local NanNewBufferHandle (uint32_t size) { - return NanNew(node::Buffer::New(size)->handle_); - } - - NAN_INLINE void FreeData(char *data, void *hint) { - delete[] data; - } - - NAN_INLINE v8::Local NanBufferUse( - char* data - , uint32_t size - ) { - return NanNew( - node::Buffer::New(data, size, FreeData, NULL)->handle_); - } - - NAN_INLINE bool NanHasInstance( - v8::Persistent& function_template - , v8::Handle value - ) { - return function_template->HasInstance(value); - } - - NAN_INLINE v8::Local NanNewContextHandle( - v8::ExtensionConfiguration* extensions = NULL - , v8::Handle tmpl = v8::Handle() - , v8::Handle obj = v8::Handle() - ) { - v8::Persistent ctx = v8::Context::New(extensions, tmpl, obj); - v8::Local lctx = NanNew(ctx); - ctx.Dispose(); - return lctx; - } - - NAN_INLINE v8::Local NanCompileScript( - v8::Local s - , const v8::ScriptOrigin& origin - ) { - return v8::Script::Compile(s, const_cast(&origin)); - } - - NAN_INLINE v8::Local NanCompileScript( - v8::Local s - ) { - return v8::Script::Compile(s); - } - - NAN_INLINE v8::Local NanRunScript(v8::Handle script) { - return script->Run(); - } - - NAN_INLINE v8::Local NanMakeCallback( - v8::Handle target - , v8::Handle func - , int argc - , v8::Handle* argv) { -# if NODE_VERSION_AT_LEAST(0, 8, 0) - return NanNew(node::MakeCallback(target, func, argc, argv)); -# else - v8::TryCatch try_catch; - v8::Local result = NanNew(func->Call(target, argc, argv)); - if (try_catch.HasCaught()) { - node::FatalException(try_catch); - } - return result; -# endif - } - - NAN_INLINE v8::Local NanMakeCallback( - v8::Handle target - , v8::Handle symbol - , int argc - , v8::Handle* argv) { -# if NODE_VERSION_AT_LEAST(0, 8, 0) - return NanNew(node::MakeCallback(target, symbol, argc, argv)); -# else - v8::Local callback = target->Get(symbol).As(); - return NanMakeCallback(target, callback, argc, argv); -# endif - } - - NAN_INLINE v8::Local NanMakeCallback( - v8::Handle target - , const char* method - , int argc - , v8::Handle* argv) { -# if NODE_VERSION_AT_LEAST(0, 8, 0) - return NanNew(node::MakeCallback(target, method, argc, argv)); -# else - return NanMakeCallback(target, NanNew(method), argc, argv); -# endif - } - - template - NAN_INLINE void NanSetIsolateData( - v8::Isolate *isolate - , T *data - ) { - isolate->SetData(data); - } - - template - NAN_INLINE T *NanGetIsolateData( - v8::Isolate *isolate - ) { - return static_cast(isolate->GetData()); - } - - class NanAsciiString { - public: - NAN_INLINE explicit NanAsciiString(v8::Handle from) { - v8::Local toStr = from->ToString(); - int buf_size = toStr->Length() + 1; - buf = new char[buf_size]; - size = toStr->WriteAscii(buf, 0, buf_size); - } - - NAN_INLINE int Size() const { - return size; - } - - NAN_INLINE char* operator*() { return buf; } - - NAN_INLINE ~NanAsciiString() { - delete[] buf; - } - - private: - char *buf; - int size; - }; - - class NanUtf8String { - public: - NAN_INLINE explicit NanUtf8String(v8::Handle from) { - v8::Local toStr = from->ToString(); - int buf_size = toStr->Utf8Length() + 1; - buf = new char[buf_size]; - size = toStr->WriteUtf8(buf, buf_size); - } - - NAN_INLINE int Size() const { - return size; - } - - NAN_INLINE char* operator*() { return buf; } - - NAN_INLINE ~NanUtf8String() { - delete[] buf; - } - - private: - char *buf; - int size; - }; - - class NanUcs2String { - public: - NAN_INLINE explicit NanUcs2String(v8::Handle from) { - v8::Local toStr = from->ToString(); - int buf_size = toStr->Length() + 1; - buf = new uint16_t[buf_size]; - size = toStr->Write(buf, 0, buf_size); - } - - NAN_INLINE int Size() const { - return size; - } - - NAN_INLINE uint16_t* operator*() { return buf; } - - NAN_INLINE ~NanUcs2String() { - delete[] buf; - } - - private: - uint16_t *buf; - int size; - }; - -#endif // NODE_MODULE_VERSION - -typedef void (*NanFreeCallback)(char *data, void *hint); - -#define NAN_METHOD(name) _NAN_METHOD_RETURN_TYPE name(_NAN_METHOD_ARGS) -#define NAN_GETTER(name) \ - _NAN_GETTER_RETURN_TYPE name( \ - v8::Local property \ - , _NAN_GETTER_ARGS) -#define NAN_SETTER(name) \ - _NAN_SETTER_RETURN_TYPE name( \ - v8::Local property \ - , v8::Local value \ - , _NAN_SETTER_ARGS) -#define NAN_PROPERTY_GETTER(name) \ - _NAN_PROPERTY_GETTER_RETURN_TYPE name( \ - v8::Local property \ - , _NAN_PROPERTY_GETTER_ARGS) -#define NAN_PROPERTY_SETTER(name) \ - _NAN_PROPERTY_SETTER_RETURN_TYPE name( \ - v8::Local property \ - , v8::Local value \ - , _NAN_PROPERTY_SETTER_ARGS) -#define NAN_PROPERTY_ENUMERATOR(name) \ - _NAN_PROPERTY_ENUMERATOR_RETURN_TYPE name(_NAN_PROPERTY_ENUMERATOR_ARGS) -#define NAN_PROPERTY_DELETER(name) \ - _NAN_PROPERTY_DELETER_RETURN_TYPE name( \ - v8::Local property \ - , _NAN_PROPERTY_DELETER_ARGS) -#define NAN_PROPERTY_QUERY(name) \ - _NAN_PROPERTY_QUERY_RETURN_TYPE name( \ - v8::Local property \ - , _NAN_PROPERTY_QUERY_ARGS) -# define NAN_INDEX_GETTER(name) \ - _NAN_INDEX_GETTER_RETURN_TYPE name(uint32_t index, _NAN_INDEX_GETTER_ARGS) -#define NAN_INDEX_SETTER(name) \ - _NAN_INDEX_SETTER_RETURN_TYPE name( \ - uint32_t index \ - , v8::Local value \ - , _NAN_INDEX_SETTER_ARGS) -#define NAN_INDEX_ENUMERATOR(name) \ - _NAN_INDEX_ENUMERATOR_RETURN_TYPE name(_NAN_INDEX_ENUMERATOR_ARGS) -#define NAN_INDEX_DELETER(name) \ - _NAN_INDEX_DELETER_RETURN_TYPE name( \ - uint32_t index \ - , _NAN_INDEX_DELETER_ARGS) -#define NAN_INDEX_QUERY(name) \ - _NAN_INDEX_QUERY_RETURN_TYPE name(uint32_t index, _NAN_INDEX_QUERY_ARGS) - -class NanCallback { - public: - NanCallback() { - NanScope(); - v8::Local obj = NanNew(); - NanAssignPersistent(handle, obj); - } - - explicit NanCallback(const v8::Handle &fn) { - NanScope(); - v8::Local obj = NanNew(); - NanAssignPersistent(handle, obj); - SetFunction(fn); - } - - ~NanCallback() { - if (handle.IsEmpty()) return; - NanDisposePersistent(handle); - } - - NAN_INLINE void SetFunction(const v8::Handle &fn) { - NanScope(); - NanNew(handle)->Set(kCallbackIndex, fn); - } - - NAN_INLINE v8::Local GetFunction() const { - NanEscapableScope(); - return NanEscapeScope(NanNew(handle)->Get(kCallbackIndex) - .As()); - } - - NAN_INLINE bool IsEmpty() const { - NanScope(); - return NanNew(handle)->Get(kCallbackIndex)->IsUndefined(); - } - - v8::Handle Call(int argc, v8::Handle argv[]) const { - NanEscapableScope(); -#if (NODE_MODULE_VERSION > 0x000B) // 0.11.12+ - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - v8::Local callback = NanNew(handle)-> - Get(kCallbackIndex).As(); - return NanEscapeScope(node::MakeCallback( - isolate - , isolate->GetCurrentContext()->Global() - , callback - , argc - , argv - )); -#else -#if NODE_VERSION_AT_LEAST(0, 8, 0) - v8::Local callback = handle-> - Get(kCallbackIndex).As(); - return NanEscapeScope(node::MakeCallback( - v8::Context::GetCurrent()->Global() - , callback - , argc - , argv - )); -#else - v8::Local callback = handle-> - Get(kCallbackIndex).As(); - return NanEscapeScope(NanMakeCallback( - v8::Context::GetCurrent()->Global(), callback, argc, argv)); -#endif -#endif - } - - private: - v8::Persistent handle; - static const uint32_t kCallbackIndex = 0; -}; - -/* abstract */ class NanAsyncWorker { - public: - explicit NanAsyncWorker(NanCallback *callback) - : callback(callback), errmsg_(NULL) { - request.data = this; - - NanScope(); - v8::Local obj = NanNew(); - NanAssignPersistent(persistentHandle, obj); - } - - virtual ~NanAsyncWorker() { - NanScope(); - - if (!persistentHandle.IsEmpty()) - NanDisposePersistent(persistentHandle); - if (callback) - delete callback; - if (errmsg_) - delete[] errmsg_; - } - - virtual void WorkComplete() { - NanScope(); - - if (errmsg_ == NULL) - HandleOKCallback(); - else - HandleErrorCallback(); - delete callback; - callback = NULL; - } - - NAN_INLINE void SaveToPersistent( - const char *key, const v8::Local &obj) { - v8::Local handle = NanNew(persistentHandle); - handle->Set(NanNew(key), obj); - } - - v8::Local GetFromPersistent(const char *key) const { - NanEscapableScope(); - v8::Local handle = NanNew(persistentHandle); - return NanEscapeScope(handle->Get(NanNew(key)).As()); - } - - virtual void Execute() = 0; - - uv_work_t request; - - protected: - v8::Persistent persistentHandle; - NanCallback *callback; - - virtual void HandleOKCallback() { - NanScope(); - - callback->Call(0, NULL); - } - - virtual void HandleErrorCallback() { - NanScope(); - - v8::Local argv[] = { - v8::Exception::Error(NanNew(ErrorMessage())) - }; - callback->Call(1, argv); - } - - void SetErrorMessage(const char *msg) { - if (errmsg_) { - delete[] errmsg_; - } - - size_t size = strlen(msg) + 1; - errmsg_ = new char[size]; - memcpy(errmsg_, msg, size); - } - - const char* ErrorMessage() const { - return errmsg_; - } - - private: - char *errmsg_; -}; - -NAN_INLINE void NanAsyncExecute (uv_work_t* req) { - NanAsyncWorker *worker = static_cast(req->data); - worker->Execute(); -} - -NAN_INLINE void NanAsyncExecuteComplete (uv_work_t* req) { - NanAsyncWorker* worker = static_cast(req->data); - worker->WorkComplete(); - delete worker; -} - -NAN_INLINE void NanAsyncQueueWorker (NanAsyncWorker* worker) { - uv_queue_work( - uv_default_loop() - , &worker->request - , NanAsyncExecute - , (uv_after_work_cb)NanAsyncExecuteComplete - ); -} - -//// Base 64 //// - -#define _nan_base64_encoded_size(size) ((size + 2 - ((size + 2) % 3)) / 3 * 4) - -// Doesn't check for padding at the end. Can be 1-2 bytes over. -NAN_INLINE size_t _nan_base64_decoded_size_fast(size_t size) { - size_t remainder = size % 4; - - size = (size / 4) * 3; - if (remainder) { - if (size == 0 && remainder == 1) { - // special case: 1-byte input cannot be decoded - size = 0; - } else { - // non-padded input, add 1 or 2 extra bytes - size += 1 + (remainder == 3); - } - } - - return size; -} - -template -NAN_INLINE size_t _nan_base64_decoded_size( - const T* src - , size_t size -) { - if (size == 0) - return 0; - - if (src[size - 1] == '=') - size--; - if (size > 0 && src[size - 1] == '=') - size--; - - return _nan_base64_decoded_size_fast(size); -} - -// supports regular and URL-safe base64 -static const int _nan_unbase64_table[] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -1, -1, -2, -1, -1 - , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 - , -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 62, -1, 63 - , 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1 - , -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 - , 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63 - , -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 - , 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 - , -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 - , -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 - , -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 -}; - -#define _nan_unbase64(x) _nan_unbase64_table[(uint8_t)(x)] - -template static size_t _nan_base64_decode( - char* buf - , size_t len - , const T* src - , const size_t srcLen -) { - char* dst = buf; - char* dstEnd = buf + len; - const T* srcEnd = src + srcLen; - - while (src < srcEnd && dst < dstEnd) { - ptrdiff_t remaining = srcEnd - src; - char a, b, c, d; - - while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--; - if (remaining == 0 || *src == '=') break; - a = _nan_unbase64(*src++); - - while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--; - if (remaining <= 1 || *src == '=') break; - b = _nan_unbase64(*src++); - - *dst++ = (a << 2) | ((b & 0x30) >> 4); - if (dst == dstEnd) break; - - while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--; - if (remaining <= 2 || *src == '=') break; - c = _nan_unbase64(*src++); - - *dst++ = ((b & 0x0F) << 4) | ((c & 0x3C) >> 2); - if (dst == dstEnd) break; - - while (_nan_unbase64(*src) < 0 && src < srcEnd) src++, remaining--; - if (remaining <= 3 || *src == '=') break; - d = _nan_unbase64(*src++); - - *dst++ = ((c & 0x03) << 6) | (d & 0x3F); - } - - return dst - buf; -} - -//// HEX //// - -template unsigned _nan_hex2bin(T c) { - if (c >= '0' && c <= '9') return c - '0'; - if (c >= 'A' && c <= 'F') return 10 + (c - 'A'); - if (c >= 'a' && c <= 'f') return 10 + (c - 'a'); - return static_cast(-1); -} - -template static size_t _nan_hex_decode( - char* buf - , size_t len - , const T* src - , const size_t srcLen -) { - size_t i; - for (i = 0; i < len && i * 2 + 1 < srcLen; ++i) { - unsigned a = _nan_hex2bin(src[i * 2 + 0]); - unsigned b = _nan_hex2bin(src[i * 2 + 1]); - if (!~a || !~b) return i; - buf[i] = a * 16 + b; - } - - return i; -} - -static bool _NanGetExternalParts( - v8::Handle val - , const char** data - , size_t* len -) { - if (node::Buffer::HasInstance(val)) { - *data = node::Buffer::Data(val.As()); - *len = node::Buffer::Length(val.As()); - return true; - } - - assert(val->IsString()); - v8::Local str = NanNew(val.As()); - - if (str->IsExternalAscii()) { - const v8::String::ExternalAsciiStringResource* ext; - ext = str->GetExternalAsciiStringResource(); - *data = ext->data(); - *len = ext->length(); - return true; - - } else if (str->IsExternal()) { - const v8::String::ExternalStringResource* ext; - ext = str->GetExternalStringResource(); - *data = reinterpret_cast(ext->data()); - *len = ext->length(); - return true; - } - - return false; -} - -namespace Nan { - enum Encoding {ASCII, UTF8, BASE64, UCS2, BINARY, HEX, BUFFER}; -} - -/* NAN_DEPRECATED */ NAN_INLINE void* _NanRawString( - v8::Handle from - , enum Nan::Encoding encoding - , size_t *datalen - , void *buf - , size_t buflen - , int flags -) { - NanScope(); - - size_t sz_; - size_t term_len = !(flags & v8::String::NO_NULL_TERMINATION); - char *data = NULL; - size_t len; - bool is_extern = _NanGetExternalParts( - from - , const_cast(&data) - , &len); - - if (is_extern && !term_len) { - NanSetPointerSafe(datalen, len); - return data; - } - - v8::Local toStr = from->ToString(); - - char *to = static_cast(buf); - - switch (encoding) { - case Nan::ASCII: -#if NODE_MODULE_VERSION < 0x000C - sz_ = toStr->Length(); - if (to == NULL) { - to = new char[sz_ + term_len]; - } else { - assert(buflen >= sz_ + term_len && "too small buffer"); - } - NanSetPointerSafe( - datalen - , toStr->WriteAscii(to, 0, static_cast(sz_ + term_len), flags)); - return to; -#endif - case Nan::BINARY: - case Nan::BUFFER: - sz_ = toStr->Length(); - if (to == NULL) { - to = new char[sz_ + term_len]; - } else { - assert(buflen >= sz_ + term_len && "too small buffer"); - } -#if NODE_MODULE_VERSION < 0x000C - { - uint16_t* twobytebuf = new uint16_t[sz_ + term_len]; - - size_t len = toStr->Write(twobytebuf, 0, - static_cast(sz_ + term_len), flags); - - for (size_t i = 0; i < sz_ + term_len && i < len + term_len; i++) { - unsigned char *b = reinterpret_cast(&twobytebuf[i]); - to[i] = *b; - } - - NanSetPointerSafe(datalen, len); - - delete[] twobytebuf; - return to; - } -#else - NanSetPointerSafe( - datalen, - toStr->WriteOneByte( - reinterpret_cast(to) - , 0 - , static_cast(sz_ + term_len) - , flags)); - return to; -#endif - case Nan::UTF8: - sz_ = toStr->Utf8Length(); - if (to == NULL) { - to = new char[sz_ + term_len]; - } else { - assert(buflen >= sz_ + term_len && "too small buffer"); - } - NanSetPointerSafe( - datalen - , toStr->WriteUtf8(to, static_cast(sz_ + term_len) - , NULL, flags) - - term_len); - return to; - case Nan::BASE64: - { - v8::String::Value value(toStr); - sz_ = _nan_base64_decoded_size(*value, value.length()); - if (to == NULL) { - to = new char[sz_ + term_len]; - } else { - assert(buflen >= sz_ + term_len); - } - NanSetPointerSafe( - datalen - , _nan_base64_decode(to, sz_, *value, value.length())); - if (term_len) { - to[sz_] = '\0'; - } - return to; - } - case Nan::UCS2: - { - sz_ = toStr->Length(); - if (to == NULL) { - to = new char[(sz_ + term_len) * 2]; - } else { - assert(buflen >= (sz_ + term_len) * 2 && "too small buffer"); - } - - int bc = 2 * toStr->Write( - reinterpret_cast(to) - , 0 - , static_cast(sz_ + term_len) - , flags); - NanSetPointerSafe(datalen, bc); - return to; - } - case Nan::HEX: - { - v8::String::Value value(toStr); - sz_ = value.length(); - assert(!(sz_ & 1) && "bad hex data"); - if (to == NULL) { - to = new char[sz_ / 2 + term_len]; - } else { - assert(buflen >= sz_ / 2 + term_len && "too small buffer"); - } - NanSetPointerSafe( - datalen - , _nan_hex_decode(to, sz_ / 2, *value, value.length())); - } - if (term_len) { - to[sz_ / 2] = '\0'; - } - return to; - default: - assert(0 && "unknown encoding"); - } - return to; -} - -NAN_DEPRECATED NAN_INLINE void* NanRawString( - v8::Handle from - , enum Nan::Encoding encoding - , size_t *datalen - , void *buf - , size_t buflen - , int flags -) { - return _NanRawString(from, encoding, datalen, buf, buflen, flags); -} - - -NAN_DEPRECATED NAN_INLINE char* NanCString( - v8::Handle from - , size_t *datalen - , char *buf = NULL - , size_t buflen = 0 - , int flags = v8::String::NO_OPTIONS -) { - return static_cast( - _NanRawString(from, Nan::UTF8, datalen, buf, buflen, flags) - ); -} - -NAN_INLINE void NanSetPrototypeTemplate( - v8::Local templ - , const char *name - , v8::Handle value -) { - NanSetTemplate(templ->PrototypeTemplate(), name, value); -} - -NAN_INLINE void NanSetPrototypeTemplate( - v8::Local templ - , v8::Handle name - , v8::Handle value - , v8::PropertyAttribute attributes -) { - NanSetTemplate(templ->PrototypeTemplate(), name, value, attributes); -} - -NAN_INLINE void NanSetInstanceTemplate( - v8::Local templ - , const char *name - , v8::Handle value -) { - NanSetTemplate(templ->InstanceTemplate(), name, value); -} - -NAN_INLINE void NanSetInstanceTemplate( - v8::Local templ - , v8::Handle name - , v8::Handle value - , v8::PropertyAttribute attributes -) { - NanSetTemplate(templ->InstanceTemplate(), name, value, attributes); -} - -#endif // NAN_H_ diff --git a/node_modules/mongodb/node_modules/kerberos/node_modules/nan/package.json b/node_modules/mongodb/node_modules/kerberos/node_modules/nan/package.json deleted file mode 100644 index 25a90e8..0000000 --- a/node_modules/mongodb/node_modules/kerberos/node_modules/nan/package.json +++ /dev/null @@ -1,79 +0,0 @@ -{ - "name": "nan", - "version": "1.3.0", - "description": "Native Abstractions for Node.js: C++ header for Node 0.8->0.12 compatibility", - "main": "include_dirs.js", - "repository": { - "type": "git", - "url": "git://github.com/rvagg/nan.git" - }, - "scripts": { - "test": "tap --gc test/js/*-test.js", - "rebuild-tests": "node-gyp rebuild --directory test" - }, - "contributors": [ - { - "name": "Rod Vagg", - "email": "r@va.gg", - "url": "https://github.com/rvagg" - }, - { - "name": "Benjamin Byholm", - "email": "bbyholm@abo.fi", - "url": "https://github.com/kkoopa/" - }, - { - "name": "Trevor Norris", - "email": "trev.norris@gmail.com", - "url": "https://github.com/trevnorris" - }, - { - "name": "Nathan Rajlich", - "email": "nathan@tootallnate.net", - "url": "https://github.com/TooTallNate" - }, - { - "name": "Brett Lawson", - "email": "brett19@gmail.com", - "url": "https://github.com/brett19" - }, - { - "name": "Ben Noordhuis", - "email": "info@bnoordhuis.nl", - "url": "https://github.com/bnoordhuis" - } - ], - "devDependencies": { - "bindings": "~1.2.1", - "node-gyp": "~1.0.1", - "tap": "~0.4.12", - "xtend": "~4.0.0" - }, - "license": "MIT", - "gitHead": "e482fbe142e58373d5a24f4e5a60c61e22a13f83", - "bugs": { - "url": "https://github.com/rvagg/nan/issues" - }, - "homepage": "https://github.com/rvagg/nan", - "_id": "nan@1.3.0", - "_shasum": "9a5b8d5ef97a10df3050e59b2c362d3baf779742", - "_from": "nan@1.3.0", - "_npmVersion": "1.4.21", - "_npmUser": { - "name": "rvagg", - "email": "rod@vagg.org" - }, - "maintainers": [ - { - "name": "rvagg", - "email": "rod@vagg.org" - } - ], - "dist": { - "shasum": "9a5b8d5ef97a10df3050e59b2c362d3baf779742", - "tarball": "http://registry.npmjs.org/nan/-/nan-1.3.0.tgz" - }, - "directories": {}, - "_resolved": "https://registry.npmjs.org/nan/-/nan-1.3.0.tgz", - "readme": "ERROR: No README data found!" -} diff --git a/node_modules/mongodb/node_modules/kerberos/package.json b/node_modules/mongodb/node_modules/kerberos/package.json deleted file mode 100644 index 8c78d94..0000000 --- a/node_modules/mongodb/node_modules/kerberos/package.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "name": "kerberos", - "version": "0.0.6", - "description": "Kerberos library for Node.js", - "main": "index.js", - "repository": { - "type": "git", - "url": "https://github.com/christkv/kerberos.git" - }, - "keywords": [ - "kerberos", - "security", - "authentication" - ], - "dependencies": { - "nan": "1.3.0" - }, - "devDependencies": { - "nodeunit": "latest" - }, - "scripts": { - "install": "(node-gyp rebuild 2> builderror.log) || (exit 0)", - "test": "nodeunit ./test" - }, - "author": { - "name": "Christian Amor Kvalheim" - }, - "license": "Apache 2.0", - "gitHead": "bb01d4fe322e022999aca19da564e7d9db59a8ed", - "bugs": { - "url": "https://github.com/christkv/kerberos/issues" - }, - "homepage": "https://github.com/christkv/kerberos", - "_id": "kerberos@0.0.6", - "_shasum": "271ac4c0fd6e3162a68ff42d8d97a28fe9e161c8", - "_from": "kerberos@0.0.6", - "_npmVersion": "2.0.0", - "_npmUser": { - "name": "christkv", - "email": "christkv@gmail.com" - }, - "maintainers": [ - { - "name": "christkv", - "email": "christkv@gmail.com" - } - ], - "dist": { - "shasum": "271ac4c0fd6e3162a68ff42d8d97a28fe9e161c8", - "tarball": "http://registry.npmjs.org/kerberos/-/kerberos-0.0.6.tgz" - }, - "directories": {}, - "_resolved": "https://registry.npmjs.org/kerberos/-/kerberos-0.0.6.tgz", - "readme": "ERROR: No README data found!" -} diff --git a/node_modules/mongodb/node_modules/kerberos/test/kerberos_tests.js b/node_modules/mongodb/node_modules/kerberos/test/kerberos_tests.js deleted file mode 100644 index a06c5fd..0000000 --- a/node_modules/mongodb/node_modules/kerberos/test/kerberos_tests.js +++ /dev/null @@ -1,34 +0,0 @@ -exports.setUp = function(callback) { - callback(); -} - -exports.tearDown = function(callback) { - callback(); -} - -exports['Simple initialize of Kerberos object'] = function(test) { - var Kerberos = require('../lib/kerberos.js').Kerberos; - var kerberos = new Kerberos(); - // console.dir(kerberos) - - // Initiate kerberos client - kerberos.authGSSClientInit('mongodb@kdc.10gen.me', Kerberos.GSS_C_MUTUAL_FLAG, function(err, context) { - console.log("===================================== authGSSClientInit") - test.equal(null, err); - test.ok(context != null && typeof context == 'object'); - // console.log("===================================== authGSSClientInit") - console.dir(err) - console.dir(context) - // console.dir(typeof result) - - // Perform the first step - kerberos.authGSSClientStep(context, function(err, result) { - console.log("===================================== authGSSClientStep") - console.dir(err) - console.dir(result) - console.dir(context) - - test.done(); - }); - }); -} \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/test/kerberos_win32_test.js b/node_modules/mongodb/node_modules/kerberos/test/kerberos_win32_test.js deleted file mode 100644 index d2f7046..0000000 --- a/node_modules/mongodb/node_modules/kerberos/test/kerberos_win32_test.js +++ /dev/null @@ -1,19 +0,0 @@ -exports.setUp = function(callback) { - callback(); -} - -exports.tearDown = function(callback) { - callback(); -} - -exports['Simple initialize of Kerberos win32 object'] = function(test) { - var KerberosNative = require('../build/Release/kerberos').Kerberos; - // console.dir(KerberosNative) - var kerberos = new KerberosNative(); - console.log("=========================================== 0") - console.dir(kerberos.acquireAlternateCredentials("dev1@10GEN.ME", "a")); - console.log("=========================================== 1") - console.dir(kerberos.prepareOutboundPackage("mongodb/kdc.10gen.com")); - console.log("=========================================== 2") - test.done(); -} diff --git a/node_modules/mongodb/node_modules/kerberos/test/win32/security_buffer_descriptor_tests.js b/node_modules/mongodb/node_modules/kerberos/test/win32/security_buffer_descriptor_tests.js deleted file mode 100644 index 3531b6b..0000000 --- a/node_modules/mongodb/node_modules/kerberos/test/win32/security_buffer_descriptor_tests.js +++ /dev/null @@ -1,41 +0,0 @@ -exports.setUp = function(callback) { - callback(); -} - -exports.tearDown = function(callback) { - callback(); -} - -exports['Initialize a security Buffer Descriptor'] = function(test) { - var SecurityBufferDescriptor = require('../../lib/sspi.js').SecurityBufferDescriptor - SecurityBuffer = require('../../lib/sspi.js').SecurityBuffer; - - // Create descriptor with single Buffer - var securityDescriptor = new SecurityBufferDescriptor(100); - try { - // Fail to work due to no valid Security Buffer - securityDescriptor = new SecurityBufferDescriptor(["hello"]); - test.ok(false); - } catch(err){} - - // Should Correctly construct SecurityBuffer - var buffer = new SecurityBuffer(SecurityBuffer.DATA, 100); - securityDescriptor = new SecurityBufferDescriptor([buffer]); - // Should correctly return a buffer - var result = securityDescriptor.toBuffer(); - test.equal(100, result.length); - - // Should Correctly construct SecurityBuffer - var buffer = new SecurityBuffer(SecurityBuffer.DATA, new Buffer("hello world")); - securityDescriptor = new SecurityBufferDescriptor([buffer]); - var result = securityDescriptor.toBuffer(); - test.equal("hello world", result.toString()); - - // Test passing in more than one Buffer - var buffer = new SecurityBuffer(SecurityBuffer.DATA, new Buffer("hello world")); - var buffer2 = new SecurityBuffer(SecurityBuffer.STREAM, new Buffer("adam and eve")); - securityDescriptor = new SecurityBufferDescriptor([buffer, buffer2]); - var result = securityDescriptor.toBuffer(); - test.equal("hello worldadam and eve", result.toString()); - test.done(); -} \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/test/win32/security_buffer_tests.js b/node_modules/mongodb/node_modules/kerberos/test/win32/security_buffer_tests.js deleted file mode 100644 index b52b959..0000000 --- a/node_modules/mongodb/node_modules/kerberos/test/win32/security_buffer_tests.js +++ /dev/null @@ -1,22 +0,0 @@ -exports.setUp = function(callback) { - callback(); -} - -exports.tearDown = function(callback) { - callback(); -} - -exports['Initialize a security Buffer'] = function(test) { - var SecurityBuffer = require('../../lib/sspi.js').SecurityBuffer; - // Create empty buffer - var securityBuffer = new SecurityBuffer(SecurityBuffer.DATA, 100); - var buffer = securityBuffer.toBuffer(); - test.equal(100, buffer.length); - - // Access data passed in - var allocated_buffer = new Buffer(256); - securityBuffer = new SecurityBuffer(SecurityBuffer.DATA, allocated_buffer); - buffer = securityBuffer.toBuffer(); - test.deepEqual(allocated_buffer, buffer); - test.done(); -} \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/kerberos/test/win32/security_credentials_tests.js b/node_modules/mongodb/node_modules/kerberos/test/win32/security_credentials_tests.js deleted file mode 100644 index 7758180..0000000 --- a/node_modules/mongodb/node_modules/kerberos/test/win32/security_credentials_tests.js +++ /dev/null @@ -1,55 +0,0 @@ -exports.setUp = function(callback) { - callback(); -} - -exports.tearDown = function(callback) { - callback(); -} - -exports['Initialize a set of security credentials'] = function(test) { - var SecurityCredentials = require('../../lib/sspi.js').SecurityCredentials; - - // Aquire some credentials - try { - var credentials = SecurityCredentials.aquire('Kerberos', 'dev1@10GEN.ME', 'a'); - } catch(err) { - console.dir(err) - test.ok(false); - } - - - - // console.dir(SecurityCredentials); - - // var SecurityBufferDescriptor = require('../../lib/sspi.js').SecurityBufferDescriptor - // SecurityBuffer = require('../../lib/sspi.js').SecurityBuffer; - - // // Create descriptor with single Buffer - // var securityDescriptor = new SecurityBufferDescriptor(100); - // try { - // // Fail to work due to no valid Security Buffer - // securityDescriptor = new SecurityBufferDescriptor(["hello"]); - // test.ok(false); - // } catch(err){} - - // // Should Correctly construct SecurityBuffer - // var buffer = new SecurityBuffer(SecurityBuffer.DATA, 100); - // securityDescriptor = new SecurityBufferDescriptor([buffer]); - // // Should correctly return a buffer - // var result = securityDescriptor.toBuffer(); - // test.equal(100, result.length); - - // // Should Correctly construct SecurityBuffer - // var buffer = new SecurityBuffer(SecurityBuffer.DATA, new Buffer("hello world")); - // securityDescriptor = new SecurityBufferDescriptor([buffer]); - // var result = securityDescriptor.toBuffer(); - // test.equal("hello world", result.toString()); - - // // Test passing in more than one Buffer - // var buffer = new SecurityBuffer(SecurityBuffer.DATA, new Buffer("hello world")); - // var buffer2 = new SecurityBuffer(SecurityBuffer.STREAM, new Buffer("adam and eve")); - // securityDescriptor = new SecurityBufferDescriptor([buffer, buffer2]); - // var result = securityDescriptor.toBuffer(); - // test.equal("hello worldadam and eve", result.toString()); - test.done(); -} \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/readable-stream/.npmignore b/node_modules/mongodb/node_modules/readable-stream/.npmignore deleted file mode 100644 index 38344f8..0000000 --- a/node_modules/mongodb/node_modules/readable-stream/.npmignore +++ /dev/null @@ -1,5 +0,0 @@ -build/ -test/ -examples/ -fs.js -zlib.js \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/readable-stream/LICENSE b/node_modules/mongodb/node_modules/readable-stream/LICENSE deleted file mode 100644 index e3d4e69..0000000 --- a/node_modules/mongodb/node_modules/readable-stream/LICENSE +++ /dev/null @@ -1,18 +0,0 @@ -Copyright Joyent, Inc. and other Node 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/mongodb/node_modules/readable-stream/README.md b/node_modules/mongodb/node_modules/readable-stream/README.md deleted file mode 100644 index 3fb3e80..0000000 --- a/node_modules/mongodb/node_modules/readable-stream/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# readable-stream - -***Node-core streams for userland*** - -[![NPM](https://nodei.co/npm/readable-stream.png?downloads=true&downloadRank=true)](https://nodei.co/npm/readable-stream/) -[![NPM](https://nodei.co/npm-dl/readable-stream.png?&months=6&height=3)](https://nodei.co/npm/readable-stream/) - -This package is a mirror of the Streams2 and Streams3 implementations in Node-core. - -If you want to guarantee a stable streams base, regardless of what version of Node you, or the users of your libraries are using, use **readable-stream** *only* and avoid the *"stream"* module in Node-core. - -**readable-stream** comes in two major versions, v1.0.x and v1.1.x. The former tracks the Streams2 implementation in Node 0.10, including bug-fixes and minor improvements as they are added. The latter tracks Streams3 as it develops in Node 0.11; we will likely see a v1.2.x branch for Node 0.12. - -**readable-stream** uses proper patch-level versioning so if you pin to `"~1.0.0"` you’ll get the latest Node 0.10 Streams2 implementation, including any fixes and minor non-breaking improvements. The patch-level versions of 1.0.x and 1.1.x should mirror the patch-level versions of Node-core releases. You should prefer the **1.0.x** releases for now and when you’re ready to start using Streams3, pin to `"~1.1.0"` - diff --git a/node_modules/mongodb/node_modules/readable-stream/duplex.js b/node_modules/mongodb/node_modules/readable-stream/duplex.js deleted file mode 100644 index ca807af..0000000 --- a/node_modules/mongodb/node_modules/readable-stream/duplex.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require("./lib/_stream_duplex.js") diff --git a/node_modules/mongodb/node_modules/readable-stream/lib/_stream_duplex.js b/node_modules/mongodb/node_modules/readable-stream/lib/_stream_duplex.js deleted file mode 100644 index b513d61..0000000 --- a/node_modules/mongodb/node_modules/readable-stream/lib/_stream_duplex.js +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -// a duplex stream is just a stream that is both readable and writable. -// Since JS doesn't have multiple prototypal inheritance, this class -// prototypally inherits from Readable, and then parasitically from -// Writable. - -module.exports = Duplex; - -/**/ -var objectKeys = Object.keys || function (obj) { - var keys = []; - for (var key in obj) keys.push(key); - return keys; -} -/**/ - - -/**/ -var util = require('core-util-is'); -util.inherits = require('inherits'); -/**/ - -var Readable = require('./_stream_readable'); -var Writable = require('./_stream_writable'); - -util.inherits(Duplex, Readable); - -forEach(objectKeys(Writable.prototype), function(method) { - if (!Duplex.prototype[method]) - Duplex.prototype[method] = Writable.prototype[method]; -}); - -function Duplex(options) { - if (!(this instanceof Duplex)) - return new Duplex(options); - - Readable.call(this, options); - Writable.call(this, options); - - if (options && options.readable === false) - this.readable = false; - - if (options && options.writable === false) - this.writable = false; - - this.allowHalfOpen = true; - if (options && options.allowHalfOpen === false) - this.allowHalfOpen = false; - - this.once('end', onend); -} - -// the no-half-open enforcer -function onend() { - // if we allow half-open state, or if the writable side ended, - // then we're ok. - if (this.allowHalfOpen || this._writableState.ended) - return; - - // no more data can be written. - // But allow more writes to happen in this tick. - process.nextTick(this.end.bind(this)); -} - -function forEach (xs, f) { - for (var i = 0, l = xs.length; i < l; i++) { - f(xs[i], i); - } -} diff --git a/node_modules/mongodb/node_modules/readable-stream/lib/_stream_passthrough.js b/node_modules/mongodb/node_modules/readable-stream/lib/_stream_passthrough.js deleted file mode 100644 index 895ca50..0000000 --- a/node_modules/mongodb/node_modules/readable-stream/lib/_stream_passthrough.js +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -// a passthrough stream. -// basically just the most minimal sort of Transform stream. -// Every written chunk gets output as-is. - -module.exports = PassThrough; - -var Transform = require('./_stream_transform'); - -/**/ -var util = require('core-util-is'); -util.inherits = require('inherits'); -/**/ - -util.inherits(PassThrough, Transform); - -function PassThrough(options) { - if (!(this instanceof PassThrough)) - return new PassThrough(options); - - Transform.call(this, options); -} - -PassThrough.prototype._transform = function(chunk, encoding, cb) { - cb(null, chunk); -}; diff --git a/node_modules/mongodb/node_modules/readable-stream/lib/_stream_readable.js b/node_modules/mongodb/node_modules/readable-stream/lib/_stream_readable.js deleted file mode 100644 index 6307220..0000000 --- a/node_modules/mongodb/node_modules/readable-stream/lib/_stream_readable.js +++ /dev/null @@ -1,982 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -module.exports = Readable; - -/**/ -var isArray = require('isarray'); -/**/ - - -/**/ -var Buffer = require('buffer').Buffer; -/**/ - -Readable.ReadableState = ReadableState; - -var EE = require('events').EventEmitter; - -/**/ -if (!EE.listenerCount) EE.listenerCount = function(emitter, type) { - return emitter.listeners(type).length; -}; -/**/ - -var Stream = require('stream'); - -/**/ -var util = require('core-util-is'); -util.inherits = require('inherits'); -/**/ - -var StringDecoder; - -util.inherits(Readable, Stream); - -function ReadableState(options, stream) { - options = options || {}; - - // the point at which it stops calling _read() to fill the buffer - // Note: 0 is a valid value, means "don't call _read preemptively ever" - var hwm = options.highWaterMark; - this.highWaterMark = (hwm || hwm === 0) ? hwm : 16 * 1024; - - // cast to ints. - this.highWaterMark = ~~this.highWaterMark; - - this.buffer = []; - this.length = 0; - this.pipes = null; - this.pipesCount = 0; - this.flowing = false; - this.ended = false; - this.endEmitted = false; - this.reading = false; - - // In streams that never have any data, and do push(null) right away, - // the consumer can miss the 'end' event if they do some I/O before - // consuming the stream. So, we don't emit('end') until some reading - // happens. - this.calledRead = false; - - // a flag to be able to tell if the onwrite cb is called immediately, - // or on a later tick. We set this to true at first, becuase any - // actions that shouldn't happen until "later" should generally also - // not happen before the first write call. - this.sync = true; - - // whenever we return null, then we set a flag to say - // that we're awaiting a 'readable' event emission. - this.needReadable = false; - this.emittedReadable = false; - this.readableListening = false; - - - // object stream flag. Used to make read(n) ignore n and to - // make all the buffer merging and length checks go away - this.objectMode = !!options.objectMode; - - // Crypto is kind of old and crusty. Historically, its default string - // encoding is 'binary' so we have to make this configurable. - // Everything else in the universe uses 'utf8', though. - this.defaultEncoding = options.defaultEncoding || 'utf8'; - - // when piping, we only care about 'readable' events that happen - // after read()ing all the bytes and not getting any pushback. - this.ranOut = false; - - // the number of writers that are awaiting a drain event in .pipe()s - this.awaitDrain = 0; - - // if true, a maybeReadMore has been scheduled - this.readingMore = false; - - this.decoder = null; - this.encoding = null; - if (options.encoding) { - if (!StringDecoder) - StringDecoder = require('string_decoder/').StringDecoder; - this.decoder = new StringDecoder(options.encoding); - this.encoding = options.encoding; - } -} - -function Readable(options) { - if (!(this instanceof Readable)) - return new Readable(options); - - this._readableState = new ReadableState(options, this); - - // legacy - this.readable = true; - - Stream.call(this); -} - -// Manually shove something into the read() buffer. -// This returns true if the highWaterMark has not been hit yet, -// similar to how Writable.write() returns true if you should -// write() some more. -Readable.prototype.push = function(chunk, encoding) { - var state = this._readableState; - - if (typeof chunk === 'string' && !state.objectMode) { - encoding = encoding || state.defaultEncoding; - if (encoding !== state.encoding) { - chunk = new Buffer(chunk, encoding); - encoding = ''; - } - } - - return readableAddChunk(this, state, chunk, encoding, false); -}; - -// Unshift should *always* be something directly out of read() -Readable.prototype.unshift = function(chunk) { - var state = this._readableState; - return readableAddChunk(this, state, chunk, '', true); -}; - -function readableAddChunk(stream, state, chunk, encoding, addToFront) { - var er = chunkInvalid(state, chunk); - if (er) { - stream.emit('error', er); - } else if (chunk === null || chunk === undefined) { - state.reading = false; - if (!state.ended) - onEofChunk(stream, state); - } else if (state.objectMode || chunk && chunk.length > 0) { - if (state.ended && !addToFront) { - var e = new Error('stream.push() after EOF'); - stream.emit('error', e); - } else if (state.endEmitted && addToFront) { - var e = new Error('stream.unshift() after end event'); - stream.emit('error', e); - } else { - if (state.decoder && !addToFront && !encoding) - chunk = state.decoder.write(chunk); - - // update the buffer info. - state.length += state.objectMode ? 1 : chunk.length; - if (addToFront) { - state.buffer.unshift(chunk); - } else { - state.reading = false; - state.buffer.push(chunk); - } - - if (state.needReadable) - emitReadable(stream); - - maybeReadMore(stream, state); - } - } else if (!addToFront) { - state.reading = false; - } - - return needMoreData(state); -} - - - -// if it's past the high water mark, we can push in some more. -// Also, if we have no data yet, we can stand some -// more bytes. This is to work around cases where hwm=0, -// such as the repl. Also, if the push() triggered a -// readable event, and the user called read(largeNumber) such that -// needReadable was set, then we ought to push more, so that another -// 'readable' event will be triggered. -function needMoreData(state) { - return !state.ended && - (state.needReadable || - state.length < state.highWaterMark || - state.length === 0); -} - -// backwards compatibility. -Readable.prototype.setEncoding = function(enc) { - if (!StringDecoder) - StringDecoder = require('string_decoder/').StringDecoder; - this._readableState.decoder = new StringDecoder(enc); - this._readableState.encoding = enc; -}; - -// Don't raise the hwm > 128MB -var MAX_HWM = 0x800000; -function roundUpToNextPowerOf2(n) { - if (n >= MAX_HWM) { - n = MAX_HWM; - } else { - // Get the next highest power of 2 - n--; - for (var p = 1; p < 32; p <<= 1) n |= n >> p; - n++; - } - return n; -} - -function howMuchToRead(n, state) { - if (state.length === 0 && state.ended) - return 0; - - if (state.objectMode) - return n === 0 ? 0 : 1; - - if (n === null || isNaN(n)) { - // only flow one buffer at a time - if (state.flowing && state.buffer.length) - return state.buffer[0].length; - else - return state.length; - } - - if (n <= 0) - return 0; - - // If we're asking for more than the target buffer level, - // then raise the water mark. Bump up to the next highest - // power of 2, to prevent increasing it excessively in tiny - // amounts. - if (n > state.highWaterMark) - state.highWaterMark = roundUpToNextPowerOf2(n); - - // don't have that much. return null, unless we've ended. - if (n > state.length) { - if (!state.ended) { - state.needReadable = true; - return 0; - } else - return state.length; - } - - return n; -} - -// you can override either this method, or the async _read(n) below. -Readable.prototype.read = function(n) { - var state = this._readableState; - state.calledRead = true; - var nOrig = n; - var ret; - - if (typeof n !== 'number' || n > 0) - state.emittedReadable = false; - - // if we're doing read(0) to trigger a readable event, but we - // already have a bunch of data in the buffer, then just trigger - // the 'readable' event and move on. - if (n === 0 && - state.needReadable && - (state.length >= state.highWaterMark || state.ended)) { - emitReadable(this); - return null; - } - - n = howMuchToRead(n, state); - - // if we've ended, and we're now clear, then finish it up. - if (n === 0 && state.ended) { - ret = null; - - // In cases where the decoder did not receive enough data - // to produce a full chunk, then immediately received an - // EOF, state.buffer will contain [, ]. - // howMuchToRead will see this and coerce the amount to - // read to zero (because it's looking at the length of the - // first in state.buffer), and we'll end up here. - // - // This can only happen via state.decoder -- no other venue - // exists for pushing a zero-length chunk into state.buffer - // and triggering this behavior. In this case, we return our - // remaining data and end the stream, if appropriate. - if (state.length > 0 && state.decoder) { - ret = fromList(n, state); - state.length -= ret.length; - } - - if (state.length === 0) - endReadable(this); - - return ret; - } - - // All the actual chunk generation logic needs to be - // *below* the call to _read. The reason is that in certain - // synthetic stream cases, such as passthrough streams, _read - // may be a completely synchronous operation which may change - // the state of the read buffer, providing enough data when - // before there was *not* enough. - // - // So, the steps are: - // 1. Figure out what the state of things will be after we do - // a read from the buffer. - // - // 2. If that resulting state will trigger a _read, then call _read. - // Note that this may be asynchronous, or synchronous. Yes, it is - // deeply ugly to write APIs this way, but that still doesn't mean - // that the Readable class should behave improperly, as streams are - // designed to be sync/async agnostic. - // Take note if the _read call is sync or async (ie, if the read call - // has returned yet), so that we know whether or not it's safe to emit - // 'readable' etc. - // - // 3. Actually pull the requested chunks out of the buffer and return. - - // if we need a readable event, then we need to do some reading. - var doRead = state.needReadable; - - // if we currently have less than the highWaterMark, then also read some - if (state.length - n <= state.highWaterMark) - doRead = true; - - // however, if we've ended, then there's no point, and if we're already - // reading, then it's unnecessary. - if (state.ended || state.reading) - doRead = false; - - if (doRead) { - state.reading = true; - state.sync = true; - // if the length is currently zero, then we *need* a readable event. - if (state.length === 0) - state.needReadable = true; - // call internal read method - this._read(state.highWaterMark); - state.sync = false; - } - - // If _read called its callback synchronously, then `reading` - // will be false, and we need to re-evaluate how much data we - // can return to the user. - if (doRead && !state.reading) - n = howMuchToRead(nOrig, state); - - if (n > 0) - ret = fromList(n, state); - else - ret = null; - - if (ret === null) { - state.needReadable = true; - n = 0; - } - - state.length -= n; - - // If we have nothing in the buffer, then we want to know - // as soon as we *do* get something into the buffer. - if (state.length === 0 && !state.ended) - state.needReadable = true; - - // If we happened to read() exactly the remaining amount in the - // buffer, and the EOF has been seen at this point, then make sure - // that we emit 'end' on the very next tick. - if (state.ended && !state.endEmitted && state.length === 0) - endReadable(this); - - return ret; -}; - -function chunkInvalid(state, chunk) { - var er = null; - if (!Buffer.isBuffer(chunk) && - 'string' !== typeof chunk && - chunk !== null && - chunk !== undefined && - !state.objectMode) { - er = new TypeError('Invalid non-string/buffer chunk'); - } - return er; -} - - -function onEofChunk(stream, state) { - if (state.decoder && !state.ended) { - var chunk = state.decoder.end(); - if (chunk && chunk.length) { - state.buffer.push(chunk); - state.length += state.objectMode ? 1 : chunk.length; - } - } - state.ended = true; - - // if we've ended and we have some data left, then emit - // 'readable' now to make sure it gets picked up. - if (state.length > 0) - emitReadable(stream); - else - endReadable(stream); -} - -// Don't emit readable right away in sync mode, because this can trigger -// another read() call => stack overflow. This way, it might trigger -// a nextTick recursion warning, but that's not so bad. -function emitReadable(stream) { - var state = stream._readableState; - state.needReadable = false; - if (state.emittedReadable) - return; - - state.emittedReadable = true; - if (state.sync) - process.nextTick(function() { - emitReadable_(stream); - }); - else - emitReadable_(stream); -} - -function emitReadable_(stream) { - stream.emit('readable'); -} - - -// at this point, the user has presumably seen the 'readable' event, -// and called read() to consume some data. that may have triggered -// in turn another _read(n) call, in which case reading = true if -// it's in progress. -// However, if we're not ended, or reading, and the length < hwm, -// then go ahead and try to read some more preemptively. -function maybeReadMore(stream, state) { - if (!state.readingMore) { - state.readingMore = true; - process.nextTick(function() { - maybeReadMore_(stream, state); - }); - } -} - -function maybeReadMore_(stream, state) { - var len = state.length; - while (!state.reading && !state.flowing && !state.ended && - state.length < state.highWaterMark) { - stream.read(0); - if (len === state.length) - // didn't get any data, stop spinning. - break; - else - len = state.length; - } - state.readingMore = false; -} - -// abstract method. to be overridden in specific implementation classes. -// call cb(er, data) where data is <= n in length. -// for virtual (non-string, non-buffer) streams, "length" is somewhat -// arbitrary, and perhaps not very meaningful. -Readable.prototype._read = function(n) { - this.emit('error', new Error('not implemented')); -}; - -Readable.prototype.pipe = function(dest, pipeOpts) { - var src = this; - var state = this._readableState; - - switch (state.pipesCount) { - case 0: - state.pipes = dest; - break; - case 1: - state.pipes = [state.pipes, dest]; - break; - default: - state.pipes.push(dest); - break; - } - state.pipesCount += 1; - - var doEnd = (!pipeOpts || pipeOpts.end !== false) && - dest !== process.stdout && - dest !== process.stderr; - - var endFn = doEnd ? onend : cleanup; - if (state.endEmitted) - process.nextTick(endFn); - else - src.once('end', endFn); - - dest.on('unpipe', onunpipe); - function onunpipe(readable) { - if (readable !== src) return; - cleanup(); - } - - function onend() { - dest.end(); - } - - // when the dest drains, it reduces the awaitDrain counter - // on the source. This would be more elegant with a .once() - // handler in flow(), but adding and removing repeatedly is - // too slow. - var ondrain = pipeOnDrain(src); - dest.on('drain', ondrain); - - function cleanup() { - // cleanup event handlers once the pipe is broken - dest.removeListener('close', onclose); - dest.removeListener('finish', onfinish); - dest.removeListener('drain', ondrain); - dest.removeListener('error', onerror); - dest.removeListener('unpipe', onunpipe); - src.removeListener('end', onend); - src.removeListener('end', cleanup); - - // if the reader is waiting for a drain event from this - // specific writer, then it would cause it to never start - // flowing again. - // So, if this is awaiting a drain, then we just call it now. - // If we don't know, then assume that we are waiting for one. - if (!dest._writableState || dest._writableState.needDrain) - ondrain(); - } - - // if the dest has an error, then stop piping into it. - // however, don't suppress the throwing behavior for this. - function onerror(er) { - unpipe(); - dest.removeListener('error', onerror); - if (EE.listenerCount(dest, 'error') === 0) - dest.emit('error', er); - } - // This is a brutally ugly hack to make sure that our error handler - // is attached before any userland ones. NEVER DO THIS. - if (!dest._events || !dest._events.error) - dest.on('error', onerror); - else if (isArray(dest._events.error)) - dest._events.error.unshift(onerror); - else - dest._events.error = [onerror, dest._events.error]; - - - - // Both close and finish should trigger unpipe, but only once. - function onclose() { - dest.removeListener('finish', onfinish); - unpipe(); - } - dest.once('close', onclose); - function onfinish() { - dest.removeListener('close', onclose); - unpipe(); - } - dest.once('finish', onfinish); - - function unpipe() { - src.unpipe(dest); - } - - // tell the dest that it's being piped to - dest.emit('pipe', src); - - // start the flow if it hasn't been started already. - if (!state.flowing) { - // the handler that waits for readable events after all - // the data gets sucked out in flow. - // This would be easier to follow with a .once() handler - // in flow(), but that is too slow. - this.on('readable', pipeOnReadable); - - state.flowing = true; - process.nextTick(function() { - flow(src); - }); - } - - return dest; -}; - -function pipeOnDrain(src) { - return function() { - var dest = this; - var state = src._readableState; - state.awaitDrain--; - if (state.awaitDrain === 0) - flow(src); - }; -} - -function flow(src) { - var state = src._readableState; - var chunk; - state.awaitDrain = 0; - - function write(dest, i, list) { - var written = dest.write(chunk); - if (false === written) { - state.awaitDrain++; - } - } - - while (state.pipesCount && null !== (chunk = src.read())) { - - if (state.pipesCount === 1) - write(state.pipes, 0, null); - else - forEach(state.pipes, write); - - src.emit('data', chunk); - - // if anyone needs a drain, then we have to wait for that. - if (state.awaitDrain > 0) - return; - } - - // if every destination was unpiped, either before entering this - // function, or in the while loop, then stop flowing. - // - // NB: This is a pretty rare edge case. - if (state.pipesCount === 0) { - state.flowing = false; - - // if there were data event listeners added, then switch to old mode. - if (EE.listenerCount(src, 'data') > 0) - emitDataEvents(src); - return; - } - - // at this point, no one needed a drain, so we just ran out of data - // on the next readable event, start it over again. - state.ranOut = true; -} - -function pipeOnReadable() { - if (this._readableState.ranOut) { - this._readableState.ranOut = false; - flow(this); - } -} - - -Readable.prototype.unpipe = function(dest) { - var state = this._readableState; - - // if we're not piping anywhere, then do nothing. - if (state.pipesCount === 0) - return this; - - // just one destination. most common case. - if (state.pipesCount === 1) { - // passed in one, but it's not the right one. - if (dest && dest !== state.pipes) - return this; - - if (!dest) - dest = state.pipes; - - // got a match. - state.pipes = null; - state.pipesCount = 0; - this.removeListener('readable', pipeOnReadable); - state.flowing = false; - if (dest) - dest.emit('unpipe', this); - return this; - } - - // slow case. multiple pipe destinations. - - if (!dest) { - // remove all. - var dests = state.pipes; - var len = state.pipesCount; - state.pipes = null; - state.pipesCount = 0; - this.removeListener('readable', pipeOnReadable); - state.flowing = false; - - for (var i = 0; i < len; i++) - dests[i].emit('unpipe', this); - return this; - } - - // try to find the right one. - var i = indexOf(state.pipes, dest); - if (i === -1) - return this; - - state.pipes.splice(i, 1); - state.pipesCount -= 1; - if (state.pipesCount === 1) - state.pipes = state.pipes[0]; - - dest.emit('unpipe', this); - - return this; -}; - -// set up data events if they are asked for -// Ensure readable listeners eventually get something -Readable.prototype.on = function(ev, fn) { - var res = Stream.prototype.on.call(this, ev, fn); - - if (ev === 'data' && !this._readableState.flowing) - emitDataEvents(this); - - if (ev === 'readable' && this.readable) { - var state = this._readableState; - if (!state.readableListening) { - state.readableListening = true; - state.emittedReadable = false; - state.needReadable = true; - if (!state.reading) { - this.read(0); - } else if (state.length) { - emitReadable(this, state); - } - } - } - - return res; -}; -Readable.prototype.addListener = Readable.prototype.on; - -// pause() and resume() are remnants of the legacy readable stream API -// If the user uses them, then switch into old mode. -Readable.prototype.resume = function() { - emitDataEvents(this); - this.read(0); - this.emit('resume'); -}; - -Readable.prototype.pause = function() { - emitDataEvents(this, true); - this.emit('pause'); -}; - -function emitDataEvents(stream, startPaused) { - var state = stream._readableState; - - if (state.flowing) { - // https://github.com/isaacs/readable-stream/issues/16 - throw new Error('Cannot switch to old mode now.'); - } - - var paused = startPaused || false; - var readable = false; - - // convert to an old-style stream. - stream.readable = true; - stream.pipe = Stream.prototype.pipe; - stream.on = stream.addListener = Stream.prototype.on; - - stream.on('readable', function() { - readable = true; - - var c; - while (!paused && (null !== (c = stream.read()))) - stream.emit('data', c); - - if (c === null) { - readable = false; - stream._readableState.needReadable = true; - } - }); - - stream.pause = function() { - paused = true; - this.emit('pause'); - }; - - stream.resume = function() { - paused = false; - if (readable) - process.nextTick(function() { - stream.emit('readable'); - }); - else - this.read(0); - this.emit('resume'); - }; - - // now make it start, just in case it hadn't already. - stream.emit('readable'); -} - -// wrap an old-style stream as the async data source. -// This is *not* part of the readable stream interface. -// It is an ugly unfortunate mess of history. -Readable.prototype.wrap = function(stream) { - var state = this._readableState; - var paused = false; - - var self = this; - stream.on('end', function() { - if (state.decoder && !state.ended) { - var chunk = state.decoder.end(); - if (chunk && chunk.length) - self.push(chunk); - } - - self.push(null); - }); - - stream.on('data', function(chunk) { - if (state.decoder) - chunk = state.decoder.write(chunk); - - // don't skip over falsy values in objectMode - //if (state.objectMode && util.isNullOrUndefined(chunk)) - if (state.objectMode && (chunk === null || chunk === undefined)) - return; - else if (!state.objectMode && (!chunk || !chunk.length)) - return; - - var ret = self.push(chunk); - if (!ret) { - paused = true; - stream.pause(); - } - }); - - // proxy all the other methods. - // important when wrapping filters and duplexes. - for (var i in stream) { - if (typeof stream[i] === 'function' && - typeof this[i] === 'undefined') { - this[i] = function(method) { return function() { - return stream[method].apply(stream, arguments); - }}(i); - } - } - - // proxy certain important events. - var events = ['error', 'close', 'destroy', 'pause', 'resume']; - forEach(events, function(ev) { - stream.on(ev, self.emit.bind(self, ev)); - }); - - // when we try to consume some more bytes, simply unpause the - // underlying stream. - self._read = function(n) { - if (paused) { - paused = false; - stream.resume(); - } - }; - - return self; -}; - - - -// exposed for testing purposes only. -Readable._fromList = fromList; - -// Pluck off n bytes from an array of buffers. -// Length is the combined lengths of all the buffers in the list. -function fromList(n, state) { - var list = state.buffer; - var length = state.length; - var stringMode = !!state.decoder; - var objectMode = !!state.objectMode; - var ret; - - // nothing in the list, definitely empty. - if (list.length === 0) - return null; - - if (length === 0) - ret = null; - else if (objectMode) - ret = list.shift(); - else if (!n || n >= length) { - // read it all, truncate the array. - if (stringMode) - ret = list.join(''); - else - ret = Buffer.concat(list, length); - list.length = 0; - } else { - // read just some of it. - if (n < list[0].length) { - // just take a part of the first list item. - // slice is the same for buffers and strings. - var buf = list[0]; - ret = buf.slice(0, n); - list[0] = buf.slice(n); - } else if (n === list[0].length) { - // first list is a perfect match - ret = list.shift(); - } else { - // complex case. - // we have enough to cover it, but it spans past the first buffer. - if (stringMode) - ret = ''; - else - ret = new Buffer(n); - - var c = 0; - for (var i = 0, l = list.length; i < l && c < n; i++) { - var buf = list[0]; - var cpy = Math.min(n - c, buf.length); - - if (stringMode) - ret += buf.slice(0, cpy); - else - buf.copy(ret, c, 0, cpy); - - if (cpy < buf.length) - list[0] = buf.slice(cpy); - else - list.shift(); - - c += cpy; - } - } - } - - return ret; -} - -function endReadable(stream) { - var state = stream._readableState; - - // If we get here before consuming all the bytes, then that is a - // bug in node. Should never happen. - if (state.length > 0) - throw new Error('endReadable called on non-empty stream'); - - if (!state.endEmitted && state.calledRead) { - state.ended = true; - process.nextTick(function() { - // Check that we didn't get one last unshift. - if (!state.endEmitted && state.length === 0) { - state.endEmitted = true; - stream.readable = false; - stream.emit('end'); - } - }); - } -} - -function forEach (xs, f) { - for (var i = 0, l = xs.length; i < l; i++) { - f(xs[i], i); - } -} - -function indexOf (xs, x) { - for (var i = 0, l = xs.length; i < l; i++) { - if (xs[i] === x) return i; - } - return -1; -} diff --git a/node_modules/mongodb/node_modules/readable-stream/lib/_stream_transform.js b/node_modules/mongodb/node_modules/readable-stream/lib/_stream_transform.js deleted file mode 100644 index eb188df..0000000 --- a/node_modules/mongodb/node_modules/readable-stream/lib/_stream_transform.js +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - - -// a transform stream is a readable/writable stream where you do -// something with the data. Sometimes it's called a "filter", -// but that's not a great name for it, since that implies a thing where -// some bits pass through, and others are simply ignored. (That would -// be a valid example of a transform, of course.) -// -// While the output is causally related to the input, it's not a -// necessarily symmetric or synchronous transformation. For example, -// a zlib stream might take multiple plain-text writes(), and then -// emit a single compressed chunk some time in the future. -// -// Here's how this works: -// -// The Transform stream has all the aspects of the readable and writable -// stream classes. When you write(chunk), that calls _write(chunk,cb) -// internally, and returns false if there's a lot of pending writes -// buffered up. When you call read(), that calls _read(n) until -// there's enough pending readable data buffered up. -// -// In a transform stream, the written data is placed in a buffer. When -// _read(n) is called, it transforms the queued up data, calling the -// buffered _write cb's as it consumes chunks. If consuming a single -// written chunk would result in multiple output chunks, then the first -// outputted bit calls the readcb, and subsequent chunks just go into -// the read buffer, and will cause it to emit 'readable' if necessary. -// -// This way, back-pressure is actually determined by the reading side, -// since _read has to be called to start processing a new chunk. However, -// a pathological inflate type of transform can cause excessive buffering -// here. For example, imagine a stream where every byte of input is -// interpreted as an integer from 0-255, and then results in that many -// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in -// 1kb of data being output. In this case, you could write a very small -// amount of input, and end up with a very large amount of output. In -// such a pathological inflating mechanism, there'd be no way to tell -// the system to stop doing the transform. A single 4MB write could -// cause the system to run out of memory. -// -// However, even in such a pathological case, only a single written chunk -// would be consumed, and then the rest would wait (un-transformed) until -// the results of the previous transformed chunk were consumed. - -module.exports = Transform; - -var Duplex = require('./_stream_duplex'); - -/**/ -var util = require('core-util-is'); -util.inherits = require('inherits'); -/**/ - -util.inherits(Transform, Duplex); - - -function TransformState(options, stream) { - this.afterTransform = function(er, data) { - return afterTransform(stream, er, data); - }; - - this.needTransform = false; - this.transforming = false; - this.writecb = null; - this.writechunk = null; -} - -function afterTransform(stream, er, data) { - var ts = stream._transformState; - ts.transforming = false; - - var cb = ts.writecb; - - if (!cb) - return stream.emit('error', new Error('no writecb in Transform class')); - - ts.writechunk = null; - ts.writecb = null; - - if (data !== null && data !== undefined) - stream.push(data); - - if (cb) - cb(er); - - var rs = stream._readableState; - rs.reading = false; - if (rs.needReadable || rs.length < rs.highWaterMark) { - stream._read(rs.highWaterMark); - } -} - - -function Transform(options) { - if (!(this instanceof Transform)) - return new Transform(options); - - Duplex.call(this, options); - - var ts = this._transformState = new TransformState(options, this); - - // when the writable side finishes, then flush out anything remaining. - var stream = this; - - // start out asking for a readable event once data is transformed. - this._readableState.needReadable = true; - - // we have implemented the _read method, and done the other things - // that Readable wants before the first _read call, so unset the - // sync guard flag. - this._readableState.sync = false; - - this.once('finish', function() { - if ('function' === typeof this._flush) - this._flush(function(er) { - done(stream, er); - }); - else - done(stream); - }); -} - -Transform.prototype.push = function(chunk, encoding) { - this._transformState.needTransform = false; - return Duplex.prototype.push.call(this, chunk, encoding); -}; - -// This is the part where you do stuff! -// override this function in implementation classes. -// 'chunk' is an input chunk. -// -// Call `push(newChunk)` to pass along transformed output -// to the readable side. You may call 'push' zero or more times. -// -// Call `cb(err)` when you are done with this chunk. If you pass -// an error, then that'll put the hurt on the whole operation. If you -// never call cb(), then you'll never get another chunk. -Transform.prototype._transform = function(chunk, encoding, cb) { - throw new Error('not implemented'); -}; - -Transform.prototype._write = function(chunk, encoding, cb) { - var ts = this._transformState; - ts.writecb = cb; - ts.writechunk = chunk; - ts.writeencoding = encoding; - if (!ts.transforming) { - var rs = this._readableState; - if (ts.needTransform || - rs.needReadable || - rs.length < rs.highWaterMark) - this._read(rs.highWaterMark); - } -}; - -// Doesn't matter what the args are here. -// _transform does all the work. -// That we got here means that the readable side wants more data. -Transform.prototype._read = function(n) { - var ts = this._transformState; - - if (ts.writechunk !== null && ts.writecb && !ts.transforming) { - ts.transforming = true; - this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform); - } else { - // mark that we need a transform, so that any data that comes in - // will get processed, now that we've asked for it. - ts.needTransform = true; - } -}; - - -function done(stream, er) { - if (er) - return stream.emit('error', er); - - // if there's nothing in the write buffer, then that means - // that nothing more will ever be provided - var ws = stream._writableState; - var rs = stream._readableState; - var ts = stream._transformState; - - if (ws.length) - throw new Error('calling transform done when ws.length != 0'); - - if (ts.transforming) - throw new Error('calling transform done when still transforming'); - - return stream.push(null); -} diff --git a/node_modules/mongodb/node_modules/readable-stream/lib/_stream_writable.js b/node_modules/mongodb/node_modules/readable-stream/lib/_stream_writable.js deleted file mode 100644 index 4bdaa4f..0000000 --- a/node_modules/mongodb/node_modules/readable-stream/lib/_stream_writable.js +++ /dev/null @@ -1,386 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -// A bit simpler than readable streams. -// Implement an async ._write(chunk, cb), and it'll handle all -// the drain event emission and buffering. - -module.exports = Writable; - -/**/ -var Buffer = require('buffer').Buffer; -/**/ - -Writable.WritableState = WritableState; - - -/**/ -var util = require('core-util-is'); -util.inherits = require('inherits'); -/**/ - -var Stream = require('stream'); - -util.inherits(Writable, Stream); - -function WriteReq(chunk, encoding, cb) { - this.chunk = chunk; - this.encoding = encoding; - this.callback = cb; -} - -function WritableState(options, stream) { - options = options || {}; - - // the point at which write() starts returning false - // Note: 0 is a valid value, means that we always return false if - // the entire buffer is not flushed immediately on write() - var hwm = options.highWaterMark; - this.highWaterMark = (hwm || hwm === 0) ? hwm : 16 * 1024; - - // object stream flag to indicate whether or not this stream - // contains buffers or objects. - this.objectMode = !!options.objectMode; - - // cast to ints. - this.highWaterMark = ~~this.highWaterMark; - - this.needDrain = false; - // at the start of calling end() - this.ending = false; - // when end() has been called, and returned - this.ended = false; - // when 'finish' is emitted - this.finished = false; - - // should we decode strings into buffers before passing to _write? - // this is here so that some node-core streams can optimize string - // handling at a lower level. - var noDecode = options.decodeStrings === false; - this.decodeStrings = !noDecode; - - // Crypto is kind of old and crusty. Historically, its default string - // encoding is 'binary' so we have to make this configurable. - // Everything else in the universe uses 'utf8', though. - this.defaultEncoding = options.defaultEncoding || 'utf8'; - - // not an actual buffer we keep track of, but a measurement - // of how much we're waiting to get pushed to some underlying - // socket or file. - this.length = 0; - - // a flag to see when we're in the middle of a write. - this.writing = false; - - // a flag to be able to tell if the onwrite cb is called immediately, - // or on a later tick. We set this to true at first, becuase any - // actions that shouldn't happen until "later" should generally also - // not happen before the first write call. - this.sync = true; - - // a flag to know if we're processing previously buffered items, which - // may call the _write() callback in the same tick, so that we don't - // end up in an overlapped onwrite situation. - this.bufferProcessing = false; - - // the callback that's passed to _write(chunk,cb) - this.onwrite = function(er) { - onwrite(stream, er); - }; - - // the callback that the user supplies to write(chunk,encoding,cb) - this.writecb = null; - - // the amount that is being written when _write is called. - this.writelen = 0; - - this.buffer = []; - - // True if the error was already emitted and should not be thrown again - this.errorEmitted = false; -} - -function Writable(options) { - var Duplex = require('./_stream_duplex'); - - // Writable ctor is applied to Duplexes, though they're not - // instanceof Writable, they're instanceof Readable. - if (!(this instanceof Writable) && !(this instanceof Duplex)) - return new Writable(options); - - this._writableState = new WritableState(options, this); - - // legacy. - this.writable = true; - - Stream.call(this); -} - -// Otherwise people can pipe Writable streams, which is just wrong. -Writable.prototype.pipe = function() { - this.emit('error', new Error('Cannot pipe. Not readable.')); -}; - - -function writeAfterEnd(stream, state, cb) { - var er = new Error('write after end'); - // TODO: defer error events consistently everywhere, not just the cb - stream.emit('error', er); - process.nextTick(function() { - cb(er); - }); -} - -// If we get something that is not a buffer, string, null, or undefined, -// and we're not in objectMode, then that's an error. -// Otherwise stream chunks are all considered to be of length=1, and the -// watermarks determine how many objects to keep in the buffer, rather than -// how many bytes or characters. -function validChunk(stream, state, chunk, cb) { - var valid = true; - if (!Buffer.isBuffer(chunk) && - 'string' !== typeof chunk && - chunk !== null && - chunk !== undefined && - !state.objectMode) { - var er = new TypeError('Invalid non-string/buffer chunk'); - stream.emit('error', er); - process.nextTick(function() { - cb(er); - }); - valid = false; - } - return valid; -} - -Writable.prototype.write = function(chunk, encoding, cb) { - var state = this._writableState; - var ret = false; - - if (typeof encoding === 'function') { - cb = encoding; - encoding = null; - } - - if (Buffer.isBuffer(chunk)) - encoding = 'buffer'; - else if (!encoding) - encoding = state.defaultEncoding; - - if (typeof cb !== 'function') - cb = function() {}; - - if (state.ended) - writeAfterEnd(this, state, cb); - else if (validChunk(this, state, chunk, cb)) - ret = writeOrBuffer(this, state, chunk, encoding, cb); - - return ret; -}; - -function decodeChunk(state, chunk, encoding) { - if (!state.objectMode && - state.decodeStrings !== false && - typeof chunk === 'string') { - chunk = new Buffer(chunk, encoding); - } - return chunk; -} - -// if we're already writing something, then just put this -// in the queue, and wait our turn. Otherwise, call _write -// If we return false, then we need a drain event, so set that flag. -function writeOrBuffer(stream, state, chunk, encoding, cb) { - chunk = decodeChunk(state, chunk, encoding); - if (Buffer.isBuffer(chunk)) - encoding = 'buffer'; - var len = state.objectMode ? 1 : chunk.length; - - state.length += len; - - var ret = state.length < state.highWaterMark; - // we must ensure that previous needDrain will not be reset to false. - if (!ret) - state.needDrain = true; - - if (state.writing) - state.buffer.push(new WriteReq(chunk, encoding, cb)); - else - doWrite(stream, state, len, chunk, encoding, cb); - - return ret; -} - -function doWrite(stream, state, len, chunk, encoding, cb) { - state.writelen = len; - state.writecb = cb; - state.writing = true; - state.sync = true; - stream._write(chunk, encoding, state.onwrite); - state.sync = false; -} - -function onwriteError(stream, state, sync, er, cb) { - if (sync) - process.nextTick(function() { - cb(er); - }); - else - cb(er); - - stream._writableState.errorEmitted = true; - stream.emit('error', er); -} - -function onwriteStateUpdate(state) { - state.writing = false; - state.writecb = null; - state.length -= state.writelen; - state.writelen = 0; -} - -function onwrite(stream, er) { - var state = stream._writableState; - var sync = state.sync; - var cb = state.writecb; - - onwriteStateUpdate(state); - - if (er) - onwriteError(stream, state, sync, er, cb); - else { - // Check if we're actually ready to finish, but don't emit yet - var finished = needFinish(stream, state); - - if (!finished && !state.bufferProcessing && state.buffer.length) - clearBuffer(stream, state); - - if (sync) { - process.nextTick(function() { - afterWrite(stream, state, finished, cb); - }); - } else { - afterWrite(stream, state, finished, cb); - } - } -} - -function afterWrite(stream, state, finished, cb) { - if (!finished) - onwriteDrain(stream, state); - cb(); - if (finished) - finishMaybe(stream, state); -} - -// Must force callback to be called on nextTick, so that we don't -// emit 'drain' before the write() consumer gets the 'false' return -// value, and has a chance to attach a 'drain' listener. -function onwriteDrain(stream, state) { - if (state.length === 0 && state.needDrain) { - state.needDrain = false; - stream.emit('drain'); - } -} - - -// if there's something in the buffer waiting, then process it -function clearBuffer(stream, state) { - state.bufferProcessing = true; - - for (var c = 0; c < state.buffer.length; c++) { - var entry = state.buffer[c]; - var chunk = entry.chunk; - var encoding = entry.encoding; - var cb = entry.callback; - var len = state.objectMode ? 1 : chunk.length; - - doWrite(stream, state, len, chunk, encoding, cb); - - // if we didn't call the onwrite immediately, then - // it means that we need to wait until it does. - // also, that means that the chunk and cb are currently - // being processed, so move the buffer counter past them. - if (state.writing) { - c++; - break; - } - } - - state.bufferProcessing = false; - if (c < state.buffer.length) - state.buffer = state.buffer.slice(c); - else - state.buffer.length = 0; -} - -Writable.prototype._write = function(chunk, encoding, cb) { - cb(new Error('not implemented')); -}; - -Writable.prototype.end = function(chunk, encoding, cb) { - var state = this._writableState; - - if (typeof chunk === 'function') { - cb = chunk; - chunk = null; - encoding = null; - } else if (typeof encoding === 'function') { - cb = encoding; - encoding = null; - } - - if (typeof chunk !== 'undefined' && chunk !== null) - this.write(chunk, encoding); - - // ignore unnecessary end() calls. - if (!state.ending && !state.finished) - endWritable(this, state, cb); -}; - - -function needFinish(stream, state) { - return (state.ending && - state.length === 0 && - !state.finished && - !state.writing); -} - -function finishMaybe(stream, state) { - var need = needFinish(stream, state); - if (need) { - state.finished = true; - stream.emit('finish'); - } - return need; -} - -function endWritable(stream, state, cb) { - state.ending = true; - finishMaybe(stream, state); - if (cb) { - if (state.finished) - process.nextTick(cb); - else - stream.once('finish', cb); - } - state.ended = true; -} diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/README.md b/node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/README.md deleted file mode 100644 index 5a76b41..0000000 --- a/node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# core-util-is - -The `util.is*` functions introduced in Node v0.12. diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/float.patch b/node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/float.patch deleted file mode 100644 index a06d5c0..0000000 --- a/node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/float.patch +++ /dev/null @@ -1,604 +0,0 @@ -diff --git a/lib/util.js b/lib/util.js -index a03e874..9074e8e 100644 ---- a/lib/util.js -+++ b/lib/util.js -@@ -19,430 +19,6 @@ - // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - // USE OR OTHER DEALINGS IN THE SOFTWARE. - --var formatRegExp = /%[sdj%]/g; --exports.format = function(f) { -- if (!isString(f)) { -- var objects = []; -- for (var i = 0; i < arguments.length; i++) { -- objects.push(inspect(arguments[i])); -- } -- return objects.join(' '); -- } -- -- var i = 1; -- var args = arguments; -- var len = args.length; -- var str = String(f).replace(formatRegExp, function(x) { -- if (x === '%%') return '%'; -- if (i >= len) return x; -- switch (x) { -- case '%s': return String(args[i++]); -- case '%d': return Number(args[i++]); -- case '%j': -- try { -- return JSON.stringify(args[i++]); -- } catch (_) { -- return '[Circular]'; -- } -- default: -- return x; -- } -- }); -- for (var x = args[i]; i < len; x = args[++i]) { -- if (isNull(x) || !isObject(x)) { -- str += ' ' + x; -- } else { -- str += ' ' + inspect(x); -- } -- } -- return str; --}; -- -- --// Mark that a method should not be used. --// Returns a modified function which warns once by default. --// If --no-deprecation is set, then it is a no-op. --exports.deprecate = function(fn, msg) { -- // Allow for deprecating things in the process of starting up. -- if (isUndefined(global.process)) { -- return function() { -- return exports.deprecate(fn, msg).apply(this, arguments); -- }; -- } -- -- if (process.noDeprecation === true) { -- return fn; -- } -- -- var warned = false; -- function deprecated() { -- if (!warned) { -- if (process.throwDeprecation) { -- throw new Error(msg); -- } else if (process.traceDeprecation) { -- console.trace(msg); -- } else { -- console.error(msg); -- } -- warned = true; -- } -- return fn.apply(this, arguments); -- } -- -- return deprecated; --}; -- -- --var debugs = {}; --var debugEnviron; --exports.debuglog = function(set) { -- if (isUndefined(debugEnviron)) -- debugEnviron = process.env.NODE_DEBUG || ''; -- set = set.toUpperCase(); -- if (!debugs[set]) { -- if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { -- var pid = process.pid; -- debugs[set] = function() { -- var msg = exports.format.apply(exports, arguments); -- console.error('%s %d: %s', set, pid, msg); -- }; -- } else { -- debugs[set] = function() {}; -- } -- } -- return debugs[set]; --}; -- -- --/** -- * Echos the value of a value. Trys to print the value out -- * in the best way possible given the different types. -- * -- * @param {Object} obj The object to print out. -- * @param {Object} opts Optional options object that alters the output. -- */ --/* legacy: obj, showHidden, depth, colors*/ --function inspect(obj, opts) { -- // default options -- var ctx = { -- seen: [], -- stylize: stylizeNoColor -- }; -- // legacy... -- if (arguments.length >= 3) ctx.depth = arguments[2]; -- if (arguments.length >= 4) ctx.colors = arguments[3]; -- if (isBoolean(opts)) { -- // legacy... -- ctx.showHidden = opts; -- } else if (opts) { -- // got an "options" object -- exports._extend(ctx, opts); -- } -- // set default options -- if (isUndefined(ctx.showHidden)) ctx.showHidden = false; -- if (isUndefined(ctx.depth)) ctx.depth = 2; -- if (isUndefined(ctx.colors)) ctx.colors = false; -- if (isUndefined(ctx.customInspect)) ctx.customInspect = true; -- if (ctx.colors) ctx.stylize = stylizeWithColor; -- return formatValue(ctx, obj, ctx.depth); --} --exports.inspect = inspect; -- -- --// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics --inspect.colors = { -- 'bold' : [1, 22], -- 'italic' : [3, 23], -- 'underline' : [4, 24], -- 'inverse' : [7, 27], -- 'white' : [37, 39], -- 'grey' : [90, 39], -- 'black' : [30, 39], -- 'blue' : [34, 39], -- 'cyan' : [36, 39], -- 'green' : [32, 39], -- 'magenta' : [35, 39], -- 'red' : [31, 39], -- 'yellow' : [33, 39] --}; -- --// Don't use 'blue' not visible on cmd.exe --inspect.styles = { -- 'special': 'cyan', -- 'number': 'yellow', -- 'boolean': 'yellow', -- 'undefined': 'grey', -- 'null': 'bold', -- 'string': 'green', -- 'date': 'magenta', -- // "name": intentionally not styling -- 'regexp': 'red' --}; -- -- --function stylizeWithColor(str, styleType) { -- var style = inspect.styles[styleType]; -- -- if (style) { -- return '\u001b[' + inspect.colors[style][0] + 'm' + str + -- '\u001b[' + inspect.colors[style][1] + 'm'; -- } else { -- return str; -- } --} -- -- --function stylizeNoColor(str, styleType) { -- return str; --} -- -- --function arrayToHash(array) { -- var hash = {}; -- -- array.forEach(function(val, idx) { -- hash[val] = true; -- }); -- -- return hash; --} -- -- --function formatValue(ctx, value, recurseTimes) { -- // Provide a hook for user-specified inspect functions. -- // Check that value is an object with an inspect function on it -- if (ctx.customInspect && -- value && -- isFunction(value.inspect) && -- // Filter out the util module, it's inspect function is special -- value.inspect !== exports.inspect && -- // Also filter out any prototype objects using the circular check. -- !(value.constructor && value.constructor.prototype === value)) { -- var ret = value.inspect(recurseTimes, ctx); -- if (!isString(ret)) { -- ret = formatValue(ctx, ret, recurseTimes); -- } -- return ret; -- } -- -- // Primitive types cannot have properties -- var primitive = formatPrimitive(ctx, value); -- if (primitive) { -- return primitive; -- } -- -- // Look up the keys of the object. -- var keys = Object.keys(value); -- var visibleKeys = arrayToHash(keys); -- -- if (ctx.showHidden) { -- keys = Object.getOwnPropertyNames(value); -- } -- -- // Some type of object without properties can be shortcutted. -- if (keys.length === 0) { -- if (isFunction(value)) { -- var name = value.name ? ': ' + value.name : ''; -- return ctx.stylize('[Function' + name + ']', 'special'); -- } -- if (isRegExp(value)) { -- return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); -- } -- if (isDate(value)) { -- return ctx.stylize(Date.prototype.toString.call(value), 'date'); -- } -- if (isError(value)) { -- return formatError(value); -- } -- } -- -- var base = '', array = false, braces = ['{', '}']; -- -- // Make Array say that they are Array -- if (isArray(value)) { -- array = true; -- braces = ['[', ']']; -- } -- -- // Make functions say that they are functions -- if (isFunction(value)) { -- var n = value.name ? ': ' + value.name : ''; -- base = ' [Function' + n + ']'; -- } -- -- // Make RegExps say that they are RegExps -- if (isRegExp(value)) { -- base = ' ' + RegExp.prototype.toString.call(value); -- } -- -- // Make dates with properties first say the date -- if (isDate(value)) { -- base = ' ' + Date.prototype.toUTCString.call(value); -- } -- -- // Make error with message first say the error -- if (isError(value)) { -- base = ' ' + formatError(value); -- } -- -- if (keys.length === 0 && (!array || value.length == 0)) { -- return braces[0] + base + braces[1]; -- } -- -- if (recurseTimes < 0) { -- if (isRegExp(value)) { -- return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); -- } else { -- return ctx.stylize('[Object]', 'special'); -- } -- } -- -- ctx.seen.push(value); -- -- var output; -- if (array) { -- output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); -- } else { -- output = keys.map(function(key) { -- return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); -- }); -- } -- -- ctx.seen.pop(); -- -- return reduceToSingleString(output, base, braces); --} -- -- --function formatPrimitive(ctx, value) { -- if (isUndefined(value)) -- return ctx.stylize('undefined', 'undefined'); -- if (isString(value)) { -- var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') -- .replace(/'/g, "\\'") -- .replace(/\\"/g, '"') + '\''; -- return ctx.stylize(simple, 'string'); -- } -- if (isNumber(value)) { -- // Format -0 as '-0'. Strict equality won't distinguish 0 from -0, -- // so instead we use the fact that 1 / -0 < 0 whereas 1 / 0 > 0 . -- if (value === 0 && 1 / value < 0) -- return ctx.stylize('-0', 'number'); -- return ctx.stylize('' + value, 'number'); -- } -- if (isBoolean(value)) -- return ctx.stylize('' + value, 'boolean'); -- // For some reason typeof null is "object", so special case here. -- if (isNull(value)) -- return ctx.stylize('null', 'null'); --} -- -- --function formatError(value) { -- return '[' + Error.prototype.toString.call(value) + ']'; --} -- -- --function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { -- var output = []; -- for (var i = 0, l = value.length; i < l; ++i) { -- if (hasOwnProperty(value, String(i))) { -- output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, -- String(i), true)); -- } else { -- output.push(''); -- } -- } -- keys.forEach(function(key) { -- if (!key.match(/^\d+$/)) { -- output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, -- key, true)); -- } -- }); -- return output; --} -- -- --function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { -- var name, str, desc; -- desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; -- if (desc.get) { -- if (desc.set) { -- str = ctx.stylize('[Getter/Setter]', 'special'); -- } else { -- str = ctx.stylize('[Getter]', 'special'); -- } -- } else { -- if (desc.set) { -- str = ctx.stylize('[Setter]', 'special'); -- } -- } -- if (!hasOwnProperty(visibleKeys, key)) { -- name = '[' + key + ']'; -- } -- if (!str) { -- if (ctx.seen.indexOf(desc.value) < 0) { -- if (isNull(recurseTimes)) { -- str = formatValue(ctx, desc.value, null); -- } else { -- str = formatValue(ctx, desc.value, recurseTimes - 1); -- } -- if (str.indexOf('\n') > -1) { -- if (array) { -- str = str.split('\n').map(function(line) { -- return ' ' + line; -- }).join('\n').substr(2); -- } else { -- str = '\n' + str.split('\n').map(function(line) { -- return ' ' + line; -- }).join('\n'); -- } -- } -- } else { -- str = ctx.stylize('[Circular]', 'special'); -- } -- } -- if (isUndefined(name)) { -- if (array && key.match(/^\d+$/)) { -- return str; -- } -- name = JSON.stringify('' + key); -- if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { -- name = name.substr(1, name.length - 2); -- name = ctx.stylize(name, 'name'); -- } else { -- name = name.replace(/'/g, "\\'") -- .replace(/\\"/g, '"') -- .replace(/(^"|"$)/g, "'"); -- name = ctx.stylize(name, 'string'); -- } -- } -- -- return name + ': ' + str; --} -- -- --function reduceToSingleString(output, base, braces) { -- var numLinesEst = 0; -- var length = output.reduce(function(prev, cur) { -- numLinesEst++; -- if (cur.indexOf('\n') >= 0) numLinesEst++; -- return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; -- }, 0); -- -- if (length > 60) { -- return braces[0] + -- (base === '' ? '' : base + '\n ') + -- ' ' + -- output.join(',\n ') + -- ' ' + -- braces[1]; -- } -- -- return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; --} -- -- - // NOTE: These type checking functions intentionally don't use `instanceof` - // because it is fragile and can be easily faked with `Object.create()`. - function isArray(ar) { -@@ -522,166 +98,10 @@ function isPrimitive(arg) { - exports.isPrimitive = isPrimitive; - - function isBuffer(arg) { -- return arg instanceof Buffer; -+ return Buffer.isBuffer(arg); - } - exports.isBuffer = isBuffer; - - function objectToString(o) { - return Object.prototype.toString.call(o); --} -- -- --function pad(n) { -- return n < 10 ? '0' + n.toString(10) : n.toString(10); --} -- -- --var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', -- 'Oct', 'Nov', 'Dec']; -- --// 26 Feb 16:19:34 --function timestamp() { -- var d = new Date(); -- var time = [pad(d.getHours()), -- pad(d.getMinutes()), -- pad(d.getSeconds())].join(':'); -- return [d.getDate(), months[d.getMonth()], time].join(' '); --} -- -- --// log is just a thin wrapper to console.log that prepends a timestamp --exports.log = function() { -- console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); --}; -- -- --/** -- * Inherit the prototype methods from one constructor into another. -- * -- * The Function.prototype.inherits from lang.js rewritten as a standalone -- * function (not on Function.prototype). NOTE: If this file is to be loaded -- * during bootstrapping this function needs to be rewritten using some native -- * functions as prototype setup using normal JavaScript does not work as -- * expected during bootstrapping (see mirror.js in r114903). -- * -- * @param {function} ctor Constructor function which needs to inherit the -- * prototype. -- * @param {function} superCtor Constructor function to inherit prototype from. -- */ --exports.inherits = function(ctor, superCtor) { -- ctor.super_ = superCtor; -- ctor.prototype = Object.create(superCtor.prototype, { -- constructor: { -- value: ctor, -- enumerable: false, -- writable: true, -- configurable: true -- } -- }); --}; -- --exports._extend = function(origin, add) { -- // Don't do anything if add isn't an object -- if (!add || !isObject(add)) return origin; -- -- var keys = Object.keys(add); -- var i = keys.length; -- while (i--) { -- origin[keys[i]] = add[keys[i]]; -- } -- return origin; --}; -- --function hasOwnProperty(obj, prop) { -- return Object.prototype.hasOwnProperty.call(obj, prop); --} -- -- --// Deprecated old stuff. -- --exports.p = exports.deprecate(function() { -- for (var i = 0, len = arguments.length; i < len; ++i) { -- console.error(exports.inspect(arguments[i])); -- } --}, 'util.p: Use console.error() instead'); -- -- --exports.exec = exports.deprecate(function() { -- return require('child_process').exec.apply(this, arguments); --}, 'util.exec is now called `child_process.exec`.'); -- -- --exports.print = exports.deprecate(function() { -- for (var i = 0, len = arguments.length; i < len; ++i) { -- process.stdout.write(String(arguments[i])); -- } --}, 'util.print: Use console.log instead'); -- -- --exports.puts = exports.deprecate(function() { -- for (var i = 0, len = arguments.length; i < len; ++i) { -- process.stdout.write(arguments[i] + '\n'); -- } --}, 'util.puts: Use console.log instead'); -- -- --exports.debug = exports.deprecate(function(x) { -- process.stderr.write('DEBUG: ' + x + '\n'); --}, 'util.debug: Use console.error instead'); -- -- --exports.error = exports.deprecate(function(x) { -- for (var i = 0, len = arguments.length; i < len; ++i) { -- process.stderr.write(arguments[i] + '\n'); -- } --}, 'util.error: Use console.error instead'); -- -- --exports.pump = exports.deprecate(function(readStream, writeStream, callback) { -- var callbackCalled = false; -- -- function call(a, b, c) { -- if (callback && !callbackCalled) { -- callback(a, b, c); -- callbackCalled = true; -- } -- } -- -- readStream.addListener('data', function(chunk) { -- if (writeStream.write(chunk) === false) readStream.pause(); -- }); -- -- writeStream.addListener('drain', function() { -- readStream.resume(); -- }); -- -- readStream.addListener('end', function() { -- writeStream.end(); -- }); -- -- readStream.addListener('close', function() { -- call(); -- }); -- -- readStream.addListener('error', function(err) { -- writeStream.end(); -- call(err); -- }); -- -- writeStream.addListener('error', function(err) { -- readStream.destroy(); -- call(err); -- }); --}, 'util.pump(): Use readableStream.pipe() instead'); -- -- --var uv; --exports._errnoException = function(err, syscall) { -- if (isUndefined(uv)) uv = process.binding('uv'); -- var errname = uv.errname(err); -- var e = new Error(syscall + ' ' + errname); -- e.code = errname; -- e.errno = errname; -- e.syscall = syscall; -- return e; --}; -+} \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/lib/util.js b/node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/lib/util.js deleted file mode 100644 index 9074e8e..0000000 --- a/node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/lib/util.js +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -// NOTE: These type checking functions intentionally don't use `instanceof` -// because it is fragile and can be easily faked with `Object.create()`. -function isArray(ar) { - return Array.isArray(ar); -} -exports.isArray = isArray; - -function isBoolean(arg) { - return typeof arg === 'boolean'; -} -exports.isBoolean = isBoolean; - -function isNull(arg) { - return arg === null; -} -exports.isNull = isNull; - -function isNullOrUndefined(arg) { - return arg == null; -} -exports.isNullOrUndefined = isNullOrUndefined; - -function isNumber(arg) { - return typeof arg === 'number'; -} -exports.isNumber = isNumber; - -function isString(arg) { - return typeof arg === 'string'; -} -exports.isString = isString; - -function isSymbol(arg) { - return typeof arg === 'symbol'; -} -exports.isSymbol = isSymbol; - -function isUndefined(arg) { - return arg === void 0; -} -exports.isUndefined = isUndefined; - -function isRegExp(re) { - return isObject(re) && objectToString(re) === '[object RegExp]'; -} -exports.isRegExp = isRegExp; - -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} -exports.isObject = isObject; - -function isDate(d) { - return isObject(d) && objectToString(d) === '[object Date]'; -} -exports.isDate = isDate; - -function isError(e) { - return isObject(e) && - (objectToString(e) === '[object Error]' || e instanceof Error); -} -exports.isError = isError; - -function isFunction(arg) { - return typeof arg === 'function'; -} -exports.isFunction = isFunction; - -function isPrimitive(arg) { - return arg === null || - typeof arg === 'boolean' || - typeof arg === 'number' || - typeof arg === 'string' || - typeof arg === 'symbol' || // ES6 symbol - typeof arg === 'undefined'; -} -exports.isPrimitive = isPrimitive; - -function isBuffer(arg) { - return Buffer.isBuffer(arg); -} -exports.isBuffer = isBuffer; - -function objectToString(o) { - return Object.prototype.toString.call(o); -} \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/package.json b/node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/package.json deleted file mode 100644 index 2b7593c..0000000 --- a/node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/package.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "name": "core-util-is", - "version": "1.0.1", - "description": "The `util.is*` functions introduced in Node v0.12.", - "main": "lib/util.js", - "repository": { - "type": "git", - "url": "git://github.com/isaacs/core-util-is" - }, - "keywords": [ - "util", - "isBuffer", - "isArray", - "isNumber", - "isString", - "isRegExp", - "isThis", - "isThat", - "polyfill" - ], - "author": { - "name": "Isaac Z. Schlueter", - "email": "i@izs.me", - "url": "http://blog.izs.me/" - }, - "license": "MIT", - "bugs": { - "url": "https://github.com/isaacs/core-util-is/issues" - }, - "readme": "# core-util-is\n\nThe `util.is*` functions introduced in Node v0.12.\n", - "readmeFilename": "README.md", - "homepage": "https://github.com/isaacs/core-util-is", - "_id": "core-util-is@1.0.1", - "dist": { - "shasum": "6b07085aef9a3ccac6ee53bf9d3df0c1521a5538", - "tarball": "http://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" - }, - "_from": "core-util-is@~1.0.0", - "_npmVersion": "1.3.23", - "_npmUser": { - "name": "isaacs", - "email": "i@izs.me" - }, - "maintainers": [ - { - "name": "isaacs", - "email": "i@izs.me" - } - ], - "directories": {}, - "_shasum": "6b07085aef9a3ccac6ee53bf9d3df0c1521a5538", - "_resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", - "scripts": {} -} diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/util.js b/node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/util.js deleted file mode 100644 index 007fa10..0000000 --- a/node_modules/mongodb/node_modules/readable-stream/node_modules/core-util-is/util.js +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -// NOTE: These type checking functions intentionally don't use `instanceof` -// because it is fragile and can be easily faked with `Object.create()`. -function isArray(ar) { - return Array.isArray(ar); -} -exports.isArray = isArray; - -function isBoolean(arg) { - return typeof arg === 'boolean'; -} -exports.isBoolean = isBoolean; - -function isNull(arg) { - return arg === null; -} -exports.isNull = isNull; - -function isNullOrUndefined(arg) { - return arg == null; -} -exports.isNullOrUndefined = isNullOrUndefined; - -function isNumber(arg) { - return typeof arg === 'number'; -} -exports.isNumber = isNumber; - -function isString(arg) { - return typeof arg === 'string'; -} -exports.isString = isString; - -function isSymbol(arg) { - return typeof arg === 'symbol'; -} -exports.isSymbol = isSymbol; - -function isUndefined(arg) { - return arg === void 0; -} -exports.isUndefined = isUndefined; - -function isRegExp(re) { - return isObject(re) && objectToString(re) === '[object RegExp]'; -} -exports.isRegExp = isRegExp; - -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} -exports.isObject = isObject; - -function isDate(d) { - return isObject(d) && objectToString(d) === '[object Date]'; -} -exports.isDate = isDate; - -function isError(e) { - return isObject(e) && objectToString(e) === '[object Error]'; -} -exports.isError = isError; - -function isFunction(arg) { - return typeof arg === 'function'; -} -exports.isFunction = isFunction; - -function isPrimitive(arg) { - return arg === null || - typeof arg === 'boolean' || - typeof arg === 'number' || - typeof arg === 'string' || - typeof arg === 'symbol' || // ES6 symbol - typeof arg === 'undefined'; -} -exports.isPrimitive = isPrimitive; - -function isBuffer(arg) { - return arg instanceof Buffer; -} -exports.isBuffer = isBuffer; - -function objectToString(o) { - return Object.prototype.toString.call(o); -} diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/LICENSE b/node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/LICENSE deleted file mode 100644 index dea3013..0000000 --- a/node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/LICENSE +++ /dev/null @@ -1,16 +0,0 @@ -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/mongodb/node_modules/readable-stream/node_modules/inherits/README.md b/node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/README.md deleted file mode 100644 index b1c5665..0000000 --- a/node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/README.md +++ /dev/null @@ -1,42 +0,0 @@ -Browser-friendly inheritance fully compatible with standard node.js -[inherits](http://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructor). - -This package exports standard `inherits` from node.js `util` module in -node environment, but also provides alternative browser-friendly -implementation through [browser -field](https://gist.github.com/shtylman/4339901). Alternative -implementation is a literal copy of standard one located in standalone -module to avoid requiring of `util`. It also has a shim for old -browsers with no `Object.create` support. - -While keeping you sure you are using standard `inherits` -implementation in node.js environment, it allows bundlers such as -[browserify](https://github.com/substack/node-browserify) to not -include full `util` package to your client code if all you need is -just `inherits` function. It worth, because browser shim for `util` -package is large and `inherits` is often the single function you need -from it. - -It's recommended to use this package instead of -`require('util').inherits` for any code that has chances to be used -not only in node.js but in browser too. - -## usage - -```js -var inherits = require('inherits'); -// then use exactly as the standard one -``` - -## note on version ~1.0 - -Version ~1.0 had completely different motivation and is not compatible -neither with 2.0 nor with standard node.js `inherits`. - -If you are using version ~1.0 and planning to switch to ~2.0, be -careful: - -* new version uses `super_` instead of `super` for referencing - superclass -* new version overwrites current prototype while old one preserves any - existing fields on it diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/inherits.js b/node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/inherits.js deleted file mode 100644 index 29f5e24..0000000 --- a/node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/inherits.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('util').inherits diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/inherits_browser.js b/node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/inherits_browser.js deleted file mode 100644 index c1e78a7..0000000 --- a/node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/inherits_browser.js +++ /dev/null @@ -1,23 +0,0 @@ -if (typeof Object.create === 'function') { - // implementation from standard node.js 'util' module - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - ctor.prototype = Object.create(superCtor.prototype, { - constructor: { - value: ctor, - enumerable: false, - writable: true, - configurable: true - } - }); - }; -} else { - // old school shim for old browsers - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - var TempCtor = function () {} - TempCtor.prototype = superCtor.prototype - ctor.prototype = new TempCtor() - ctor.prototype.constructor = ctor - } -} diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/package.json b/node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/package.json deleted file mode 100644 index 3d69f4f..0000000 --- a/node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/package.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "name": "inherits", - "description": "Browser-friendly inheritance fully compatible with standard node.js inherits()", - "version": "2.0.1", - "keywords": [ - "inheritance", - "class", - "klass", - "oop", - "object-oriented", - "inherits", - "browser", - "browserify" - ], - "main": "./inherits.js", - "browser": "./inherits_browser.js", - "repository": { - "type": "git", - "url": "git://github.com/isaacs/inherits" - }, - "license": "ISC", - "scripts": { - "test": "node test" - }, - "readme": "Browser-friendly inheritance fully compatible with standard node.js\n[inherits](http://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructor).\n\nThis package exports standard `inherits` from node.js `util` module in\nnode environment, but also provides alternative browser-friendly\nimplementation through [browser\nfield](https://gist.github.com/shtylman/4339901). Alternative\nimplementation is a literal copy of standard one located in standalone\nmodule to avoid requiring of `util`. It also has a shim for old\nbrowsers with no `Object.create` support.\n\nWhile keeping you sure you are using standard `inherits`\nimplementation in node.js environment, it allows bundlers such as\n[browserify](https://github.com/substack/node-browserify) to not\ninclude full `util` package to your client code if all you need is\njust `inherits` function. It worth, because browser shim for `util`\npackage is large and `inherits` is often the single function you need\nfrom it.\n\nIt's recommended to use this package instead of\n`require('util').inherits` for any code that has chances to be used\nnot only in node.js but in browser too.\n\n## usage\n\n```js\nvar inherits = require('inherits');\n// then use exactly as the standard one\n```\n\n## note on version ~1.0\n\nVersion ~1.0 had completely different motivation and is not compatible\nneither with 2.0 nor with standard node.js `inherits`.\n\nIf you are using version ~1.0 and planning to switch to ~2.0, be\ncareful:\n\n* new version uses `super_` instead of `super` for referencing\n superclass\n* new version overwrites current prototype while old one preserves any\n existing fields on it\n", - "readmeFilename": "README.md", - "bugs": { - "url": "https://github.com/isaacs/inherits/issues" - }, - "_id": "inherits@2.0.1", - "dist": { - "shasum": "b17d08d326b4423e568eff719f91b0b1cbdf69f1", - "tarball": "http://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" - }, - "_from": "inherits@~2.0.1", - "_npmVersion": "1.3.8", - "_npmUser": { - "name": "isaacs", - "email": "i@izs.me" - }, - "maintainers": [ - { - "name": "isaacs", - "email": "i@izs.me" - } - ], - "directories": {}, - "_shasum": "b17d08d326b4423e568eff719f91b0b1cbdf69f1", - "_resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "homepage": "https://github.com/isaacs/inherits" -} diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/test.js b/node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/test.js deleted file mode 100644 index fc53012..0000000 --- a/node_modules/mongodb/node_modules/readable-stream/node_modules/inherits/test.js +++ /dev/null @@ -1,25 +0,0 @@ -var inherits = require('./inherits.js') -var assert = require('assert') - -function test(c) { - assert(c.constructor === Child) - assert(c.constructor.super_ === Parent) - assert(Object.getPrototypeOf(c) === Child.prototype) - assert(Object.getPrototypeOf(Object.getPrototypeOf(c)) === Parent.prototype) - assert(c instanceof Child) - assert(c instanceof Parent) -} - -function Child() { - Parent.call(this) - test(this) -} - -function Parent() {} - -inherits(Child, Parent) - -var c = new Child -test(c) - -console.log('ok') diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/README.md b/node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/README.md deleted file mode 100644 index 052a62b..0000000 --- a/node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/README.md +++ /dev/null @@ -1,54 +0,0 @@ - -# isarray - -`Array#isArray` for older browsers. - -## Usage - -```js -var isArray = require('isarray'); - -console.log(isArray([])); // => true -console.log(isArray({})); // => false -``` - -## Installation - -With [npm](http://npmjs.org) do - -```bash -$ npm install isarray -``` - -Then bundle for the browser with -[browserify](https://github.com/substack/browserify). - -With [component](http://component.io) do - -```bash -$ component install juliangruber/isarray -``` - -## License - -(MIT) - -Copyright (c) 2013 Julian Gruber <julian@juliangruber.com> - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -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/mongodb/node_modules/readable-stream/node_modules/isarray/build/build.js b/node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/build/build.js deleted file mode 100644 index ec58596..0000000 --- a/node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/build/build.js +++ /dev/null @@ -1,209 +0,0 @@ - -/** - * Require the given path. - * - * @param {String} path - * @return {Object} exports - * @api public - */ - -function require(path, parent, orig) { - var resolved = require.resolve(path); - - // lookup failed - if (null == resolved) { - orig = orig || path; - parent = parent || 'root'; - var err = new Error('Failed to require "' + orig + '" from "' + parent + '"'); - err.path = orig; - err.parent = parent; - err.require = true; - throw err; - } - - var module = require.modules[resolved]; - - // perform real require() - // by invoking the module's - // registered function - if (!module.exports) { - module.exports = {}; - module.client = module.component = true; - module.call(this, module.exports, require.relative(resolved), module); - } - - return module.exports; -} - -/** - * Registered modules. - */ - -require.modules = {}; - -/** - * Registered aliases. - */ - -require.aliases = {}; - -/** - * Resolve `path`. - * - * Lookup: - * - * - PATH/index.js - * - PATH.js - * - PATH - * - * @param {String} path - * @return {String} path or null - * @api private - */ - -require.resolve = function(path) { - if (path.charAt(0) === '/') path = path.slice(1); - var index = path + '/index.js'; - - var paths = [ - path, - path + '.js', - path + '.json', - path + '/index.js', - path + '/index.json' - ]; - - for (var i = 0; i < paths.length; i++) { - var path = paths[i]; - if (require.modules.hasOwnProperty(path)) return path; - } - - if (require.aliases.hasOwnProperty(index)) { - return require.aliases[index]; - } -}; - -/** - * Normalize `path` relative to the current path. - * - * @param {String} curr - * @param {String} path - * @return {String} - * @api private - */ - -require.normalize = function(curr, path) { - var segs = []; - - if ('.' != path.charAt(0)) return path; - - curr = curr.split('/'); - path = path.split('/'); - - for (var i = 0; i < path.length; ++i) { - if ('..' == path[i]) { - curr.pop(); - } else if ('.' != path[i] && '' != path[i]) { - segs.push(path[i]); - } - } - - return curr.concat(segs).join('/'); -}; - -/** - * Register module at `path` with callback `definition`. - * - * @param {String} path - * @param {Function} definition - * @api private - */ - -require.register = function(path, definition) { - require.modules[path] = definition; -}; - -/** - * Alias a module definition. - * - * @param {String} from - * @param {String} to - * @api private - */ - -require.alias = function(from, to) { - if (!require.modules.hasOwnProperty(from)) { - throw new Error('Failed to alias "' + from + '", it does not exist'); - } - require.aliases[to] = from; -}; - -/** - * Return a require function relative to the `parent` path. - * - * @param {String} parent - * @return {Function} - * @api private - */ - -require.relative = function(parent) { - var p = require.normalize(parent, '..'); - - /** - * lastIndexOf helper. - */ - - function lastIndexOf(arr, obj) { - var i = arr.length; - while (i--) { - if (arr[i] === obj) return i; - } - return -1; - } - - /** - * The relative require() itself. - */ - - function localRequire(path) { - var resolved = localRequire.resolve(path); - return require(resolved, parent, path); - } - - /** - * Resolve relative to the parent. - */ - - localRequire.resolve = function(path) { - var c = path.charAt(0); - if ('/' == c) return path.slice(1); - if ('.' == c) return require.normalize(p, path); - - // resolve deps by returning - // the dep in the nearest "deps" - // directory - var segs = parent.split('/'); - var i = lastIndexOf(segs, 'deps') + 1; - if (!i) i = 0; - path = segs.slice(0, i + 1).join('/') + '/deps/' + path; - return path; - }; - - /** - * Check if module is defined at `path`. - */ - - localRequire.exists = function(path) { - return require.modules.hasOwnProperty(localRequire.resolve(path)); - }; - - return localRequire; -}; -require.register("isarray/index.js", function(exports, require, module){ -module.exports = Array.isArray || function (arr) { - return Object.prototype.toString.call(arr) == '[object Array]'; -}; - -}); -require.alias("isarray/index.js", "isarray/index.js"); - diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/component.json b/node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/component.json deleted file mode 100644 index 9e31b68..0000000 --- a/node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/component.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name" : "isarray", - "description" : "Array#isArray for older browsers", - "version" : "0.0.1", - "repository" : "juliangruber/isarray", - "homepage": "https://github.com/juliangruber/isarray", - "main" : "index.js", - "scripts" : [ - "index.js" - ], - "dependencies" : {}, - "keywords": ["browser","isarray","array"], - "author": { - "name": "Julian Gruber", - "email": "mail@juliangruber.com", - "url": "http://juliangruber.com" - }, - "license": "MIT" -} diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/index.js b/node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/index.js deleted file mode 100644 index 5f5ad45..0000000 --- a/node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/index.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = Array.isArray || function (arr) { - return Object.prototype.toString.call(arr) == '[object Array]'; -}; diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/package.json b/node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/package.json deleted file mode 100644 index fc7904b..0000000 --- a/node_modules/mongodb/node_modules/readable-stream/node_modules/isarray/package.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "name": "isarray", - "description": "Array#isArray for older browsers", - "version": "0.0.1", - "repository": { - "type": "git", - "url": "git://github.com/juliangruber/isarray.git" - }, - "homepage": "https://github.com/juliangruber/isarray", - "main": "index.js", - "scripts": { - "test": "tap test/*.js" - }, - "dependencies": {}, - "devDependencies": { - "tap": "*" - }, - "keywords": [ - "browser", - "isarray", - "array" - ], - "author": { - "name": "Julian Gruber", - "email": "mail@juliangruber.com", - "url": "http://juliangruber.com" - }, - "license": "MIT", - "readme": "\n# isarray\n\n`Array#isArray` for older browsers.\n\n## Usage\n\n```js\nvar isArray = require('isarray');\n\nconsole.log(isArray([])); // => true\nconsole.log(isArray({})); // => false\n```\n\n## Installation\n\nWith [npm](http://npmjs.org) do\n\n```bash\n$ npm install isarray\n```\n\nThen bundle for the browser with\n[browserify](https://github.com/substack/browserify).\n\nWith [component](http://component.io) do\n\n```bash\n$ component install juliangruber/isarray\n```\n\n## License\n\n(MIT)\n\nCopyright (c) 2013 Julian Gruber <julian@juliangruber.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\nof the Software, and to permit persons to whom the Software is furnished to do\nso, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n", - "readmeFilename": "README.md", - "_id": "isarray@0.0.1", - "dist": { - "shasum": "8a18acfca9a8f4177e09abfc6038939b05d1eedf", - "tarball": "http://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" - }, - "_from": "isarray@0.0.1", - "_npmVersion": "1.2.18", - "_npmUser": { - "name": "juliangruber", - "email": "julian@juliangruber.com" - }, - "maintainers": [ - { - "name": "juliangruber", - "email": "julian@juliangruber.com" - } - ], - "directories": {}, - "_shasum": "8a18acfca9a8f4177e09abfc6038939b05d1eedf", - "_resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "bugs": { - "url": "https://github.com/juliangruber/isarray/issues" - } -} diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/.npmignore b/node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/.npmignore deleted file mode 100644 index 206320c..0000000 --- a/node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/.npmignore +++ /dev/null @@ -1,2 +0,0 @@ -build -test diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/LICENSE b/node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/LICENSE deleted file mode 100644 index 6de584a..0000000 --- a/node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -Copyright Joyent, Inc. and other Node contributors. - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to permit -persons to whom the Software is furnished to do so, subject to the -following conditions: - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/README.md b/node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/README.md deleted file mode 100644 index 4d2aa00..0000000 --- a/node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/README.md +++ /dev/null @@ -1,7 +0,0 @@ -**string_decoder.js** (`require('string_decoder')`) from Node.js core - -Copyright Joyent, Inc. and other Node contributors. See LICENCE file for details. - -Version numbers match the versions found in Node core, e.g. 0.10.24 matches Node 0.10.24, likewise 0.11.10 matches Node 0.11.10. **Prefer the stable version over the unstable.** - -The *build/* directory contains a build script that will scrape the source from the [joyent/node](https://github.com/joyent/node) repo given a specific Node version. \ No newline at end of file diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/index.js b/node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/index.js deleted file mode 100644 index b00e54f..0000000 --- a/node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/index.js +++ /dev/null @@ -1,221 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -var Buffer = require('buffer').Buffer; - -var isBufferEncoding = Buffer.isEncoding - || function(encoding) { - switch (encoding && encoding.toLowerCase()) { - case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': case 'raw': return true; - default: return false; - } - } - - -function assertEncoding(encoding) { - if (encoding && !isBufferEncoding(encoding)) { - throw new Error('Unknown encoding: ' + encoding); - } -} - -// StringDecoder provides an interface for efficiently splitting a series of -// buffers into a series of JS strings without breaking apart multi-byte -// characters. CESU-8 is handled as part of the UTF-8 encoding. -// -// @TODO Handling all encodings inside a single object makes it very difficult -// to reason about this code, so it should be split up in the future. -// @TODO There should be a utf8-strict encoding that rejects invalid UTF-8 code -// points as used by CESU-8. -var StringDecoder = exports.StringDecoder = function(encoding) { - this.encoding = (encoding || 'utf8').toLowerCase().replace(/[-_]/, ''); - assertEncoding(encoding); - switch (this.encoding) { - case 'utf8': - // CESU-8 represents each of Surrogate Pair by 3-bytes - this.surrogateSize = 3; - break; - case 'ucs2': - case 'utf16le': - // UTF-16 represents each of Surrogate Pair by 2-bytes - this.surrogateSize = 2; - this.detectIncompleteChar = utf16DetectIncompleteChar; - break; - case 'base64': - // Base-64 stores 3 bytes in 4 chars, and pads the remainder. - this.surrogateSize = 3; - this.detectIncompleteChar = base64DetectIncompleteChar; - break; - default: - this.write = passThroughWrite; - return; - } - - // Enough space to store all bytes of a single character. UTF-8 needs 4 - // bytes, but CESU-8 may require up to 6 (3 bytes per surrogate). - this.charBuffer = new Buffer(6); - // Number of bytes received for the current incomplete multi-byte character. - this.charReceived = 0; - // Number of bytes expected for the current incomplete multi-byte character. - this.charLength = 0; -}; - - -// write decodes the given buffer and returns it as JS string that is -// guaranteed to not contain any partial multi-byte characters. Any partial -// character found at the end of the buffer is buffered up, and will be -// returned when calling write again with the remaining bytes. -// -// Note: Converting a Buffer containing an orphan surrogate to a String -// currently works, but converting a String to a Buffer (via `new Buffer`, or -// Buffer#write) will replace incomplete surrogates with the unicode -// replacement character. See https://codereview.chromium.org/121173009/ . -StringDecoder.prototype.write = function(buffer) { - var charStr = ''; - // if our last write ended with an incomplete multibyte character - while (this.charLength) { - // determine how many remaining bytes this buffer has to offer for this char - var available = (buffer.length >= this.charLength - this.charReceived) ? - this.charLength - this.charReceived : - buffer.length; - - // add the new bytes to the char buffer - buffer.copy(this.charBuffer, this.charReceived, 0, available); - this.charReceived += available; - - if (this.charReceived < this.charLength) { - // still not enough chars in this buffer? wait for more ... - return ''; - } - - // remove bytes belonging to the current character from the buffer - buffer = buffer.slice(available, buffer.length); - - // get the character that was split - charStr = this.charBuffer.slice(0, this.charLength).toString(this.encoding); - - // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character - var charCode = charStr.charCodeAt(charStr.length - 1); - if (charCode >= 0xD800 && charCode <= 0xDBFF) { - this.charLength += this.surrogateSize; - charStr = ''; - continue; - } - this.charReceived = this.charLength = 0; - - // if there are no more bytes in this buffer, just emit our char - if (buffer.length === 0) { - return charStr; - } - break; - } - - // determine and set charLength / charReceived - this.detectIncompleteChar(buffer); - - var end = buffer.length; - if (this.charLength) { - // buffer the incomplete character bytes we got - buffer.copy(this.charBuffer, 0, buffer.length - this.charReceived, end); - end -= this.charReceived; - } - - charStr += buffer.toString(this.encoding, 0, end); - - var end = charStr.length - 1; - var charCode = charStr.charCodeAt(end); - // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character - if (charCode >= 0xD800 && charCode <= 0xDBFF) { - var size = this.surrogateSize; - this.charLength += size; - this.charReceived += size; - this.charBuffer.copy(this.charBuffer, size, 0, size); - buffer.copy(this.charBuffer, 0, 0, size); - return charStr.substring(0, end); - } - - // or just emit the charStr - return charStr; -}; - -// detectIncompleteChar determines if there is an incomplete UTF-8 character at -// the end of the given buffer. If so, it sets this.charLength to the byte -// length that character, and sets this.charReceived to the number of bytes -// that are available for this character. -StringDecoder.prototype.detectIncompleteChar = function(buffer) { - // determine how many bytes we have to check at the end of this buffer - var i = (buffer.length >= 3) ? 3 : buffer.length; - - // Figure out if one of the last i bytes of our buffer announces an - // incomplete char. - for (; i > 0; i--) { - var c = buffer[buffer.length - i]; - - // See http://en.wikipedia.org/wiki/UTF-8#Description - - // 110XXXXX - if (i == 1 && c >> 5 == 0x06) { - this.charLength = 2; - break; - } - - // 1110XXXX - if (i <= 2 && c >> 4 == 0x0E) { - this.charLength = 3; - break; - } - - // 11110XXX - if (i <= 3 && c >> 3 == 0x1E) { - this.charLength = 4; - break; - } - } - this.charReceived = i; -}; - -StringDecoder.prototype.end = function(buffer) { - var res = ''; - if (buffer && buffer.length) - res = this.write(buffer); - - if (this.charReceived) { - var cr = this.charReceived; - var buf = this.charBuffer; - var enc = this.encoding; - res += buf.slice(0, cr).toString(enc); - } - - return res; -}; - -function passThroughWrite(buffer) { - return buffer.toString(this.encoding); -} - -function utf16DetectIncompleteChar(buffer) { - this.charReceived = buffer.length % 2; - this.charLength = this.charReceived ? 2 : 0; -} - -function base64DetectIncompleteChar(buffer) { - this.charReceived = buffer.length % 3; - this.charLength = this.charReceived ? 3 : 0; -} diff --git a/node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/package.json b/node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/package.json deleted file mode 100644 index a8c586b..0000000 --- a/node_modules/mongodb/node_modules/readable-stream/node_modules/string_decoder/package.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "name": "string_decoder", - "version": "0.10.31", - "description": "The string_decoder module from Node core", - "main": "index.js", - "dependencies": {}, - "devDependencies": { - "tap": "~0.4.8" - }, - "scripts": { - "test": "tap test/simple/*.js" - }, - "repository": { - "type": "git", - "url": "git://github.com/rvagg/string_decoder.git" - }, - "homepage": "https://github.com/rvagg/string_decoder", - "keywords": [ - "string", - "decoder", - "browser", - "browserify" - ], - "license": "MIT", - "gitHead": "d46d4fd87cf1d06e031c23f1ba170ca7d4ade9a0", - "bugs": { - "url": "https://github.com/rvagg/string_decoder/issues" - }, - "_id": "string_decoder@0.10.31", - "_shasum": "62e203bc41766c6c28c9fc84301dab1c5310fa94", - "_from": "string_decoder@~0.10.x", - "_npmVersion": "1.4.23", - "_npmUser": { - "name": "rvagg", - "email": "rod@vagg.org" - }, - "maintainers": [ - { - "name": "substack", - "email": "mail@substack.net" - }, - { - "name": "rvagg", - "email": "rod@vagg.org" - } - ], - "dist": { - "shasum": "62e203bc41766c6c28c9fc84301dab1c5310fa94", - "tarball": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - }, - "directories": {}, - "_resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "readme": "ERROR: No README data found!" -} diff --git a/node_modules/mongodb/node_modules/readable-stream/package.json b/node_modules/mongodb/node_modules/readable-stream/package.json deleted file mode 100644 index 153fb54..0000000 --- a/node_modules/mongodb/node_modules/readable-stream/package.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "name": "readable-stream", - "version": "1.0.33", - "description": "Streams2, a user-land copy of the stream library from Node.js v0.10.x", - "main": "readable.js", - "dependencies": { - "core-util-is": "~1.0.0", - "isarray": "0.0.1", - "string_decoder": "~0.10.x", - "inherits": "~2.0.1" - }, - "devDependencies": { - "tap": "~0.2.6" - }, - "scripts": { - "test": "tap test/simple/*.js" - }, - "repository": { - "type": "git", - "url": "git://github.com/isaacs/readable-stream" - }, - "keywords": [ - "readable", - "stream", - "pipe" - ], - "browser": { - "util": false - }, - "author": { - "name": "Isaac Z. Schlueter", - "email": "i@izs.me", - "url": "http://blog.izs.me/" - }, - "license": "MIT", - "gitHead": "0bf97a117c5646556548966409ebc57a6dda2638", - "bugs": { - "url": "https://github.com/isaacs/readable-stream/issues" - }, - "homepage": "https://github.com/isaacs/readable-stream", - "_id": "readable-stream@1.0.33", - "_shasum": "3a360dd66c1b1d7fd4705389860eda1d0f61126c", - "_from": "readable-stream@latest", - "_npmVersion": "1.4.28", - "_npmUser": { - "name": "rvagg", - "email": "rod@vagg.org" - }, - "maintainers": [ - { - "name": "isaacs", - "email": "i@izs.me" - }, - { - "name": "tootallnate", - "email": "nathan@tootallnate.net" - }, - { - "name": "rvagg", - "email": "rod@vagg.org" - } - ], - "dist": { - "shasum": "3a360dd66c1b1d7fd4705389860eda1d0f61126c", - "tarball": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz" - }, - "directories": {}, - "_resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", - "readme": "ERROR: No README data found!" -} diff --git a/node_modules/mongodb/node_modules/readable-stream/passthrough.js b/node_modules/mongodb/node_modules/readable-stream/passthrough.js deleted file mode 100644 index 27e8d8a..0000000 --- a/node_modules/mongodb/node_modules/readable-stream/passthrough.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require("./lib/_stream_passthrough.js") diff --git a/node_modules/mongodb/node_modules/readable-stream/readable.js b/node_modules/mongodb/node_modules/readable-stream/readable.js deleted file mode 100644 index 8b5337b..0000000 --- a/node_modules/mongodb/node_modules/readable-stream/readable.js +++ /dev/null @@ -1,8 +0,0 @@ -var Stream = require('stream'); // hack to fix a circular dependency issue when used with browserify -exports = module.exports = require('./lib/_stream_readable.js'); -exports.Stream = Stream; -exports.Readable = exports; -exports.Writable = require('./lib/_stream_writable.js'); -exports.Duplex = require('./lib/_stream_duplex.js'); -exports.Transform = require('./lib/_stream_transform.js'); -exports.PassThrough = require('./lib/_stream_passthrough.js'); diff --git a/node_modules/mongodb/node_modules/readable-stream/transform.js b/node_modules/mongodb/node_modules/readable-stream/transform.js deleted file mode 100644 index 5d482f0..0000000 --- a/node_modules/mongodb/node_modules/readable-stream/transform.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require("./lib/_stream_transform.js") diff --git a/node_modules/mongodb/node_modules/readable-stream/writable.js b/node_modules/mongodb/node_modules/readable-stream/writable.js deleted file mode 100644 index e1e9efd..0000000 --- a/node_modules/mongodb/node_modules/readable-stream/writable.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require("./lib/_stream_writable.js") diff --git a/node_modules/mongodb/package.json b/node_modules/mongodb/package.json deleted file mode 100755 index 47169d9..0000000 --- a/node_modules/mongodb/package.json +++ /dev/null @@ -1,252 +0,0 @@ -{ - "name": "mongodb", - "description": "A node.js driver for MongoDB", - "keywords": [ - "mongodb", - "mongo", - "driver", - "db" - ], - "version": "1.4.23", - "author": { - "name": "Christian Amor Kvalheim", - "email": "christkv@gmail.com" - }, - "contributors": [ - { - "name": "Aaron Heckmann" - }, - { - "name": "Christoph Pojer" - }, - { - "name": "Pau Ramon Revilla" - }, - { - "name": "Nathan White" - }, - { - "name": "Emmerman" - }, - { - "name": "Seth LaForge" - }, - { - "name": "Boris Filipov" - }, - { - "name": "Stefan Schärmeli" - }, - { - "name": "Tedde Lundgren" - }, - { - "name": "renctan" - }, - { - "name": "Sergey Ukustov" - }, - { - "name": "Ciaran Jessup" - }, - { - "name": "kuno" - }, - { - "name": "srimonti" - }, - { - "name": "Erik Abele" - }, - { - "name": "Pratik Daga" - }, - { - "name": "Slobodan Utvic" - }, - { - "name": "Kristina Chodorow" - }, - { - "name": "Yonathan Randolph" - }, - { - "name": "Brian Noguchi" - }, - { - "name": "Sam Epstein" - }, - { - "name": "James Harrison Fisher" - }, - { - "name": "Vladimir Dronnikov" - }, - { - "name": "Ben Hockey" - }, - { - "name": "Henrik Johansson" - }, - { - "name": "Simon Weare" - }, - { - "name": "Alex Gorbatchev" - }, - { - "name": "Shimon Doodkin" - }, - { - "name": "Kyle Mueller" - }, - { - "name": "Eran Hammer-Lahav" - }, - { - "name": "Marcin Ciszak" - }, - { - "name": "François de Metz" - }, - { - "name": "Vinay Pulim" - }, - { - "name": "nstielau" - }, - { - "name": "Adam Wiggins" - }, - { - "name": "entrinzikyl" - }, - { - "name": "Jeremy Selier" - }, - { - "name": "Ian Millington" - }, - { - "name": "Public Keating" - }, - { - "name": "andrewjstone" - }, - { - "name": "Christopher Stott" - }, - { - "name": "Corey Jewett" - }, - { - "name": "brettkiefer" - }, - { - "name": "Rob Holland" - }, - { - "name": "Senmiao Liu" - }, - { - "name": "heroic" - }, - { - "name": "gitfy" - }, - { - "name": "Andrew Stone" - }, - { - "name": "John Le Drew" - }, - { - "name": "Lucasfilm Singapore" - }, - { - "name": "Roman Shtylman" - }, - { - "name": "Matt Self" - }, - { - "name": "Gregory Langlais" - }, - { - "name": "Samantha Ritter" - } - ], - "repository": { - "type": "git", - "url": "http://github.com/mongodb/node-mongodb-native.git" - }, - "bugs": { - "url": "http://github.com/mongodb/node-mongodb-native/issues" - }, - "dependencies": { - "bson": "~0.2", - "kerberos": "0.0.6", - "readable-stream": "latest" - }, - "devDependencies": { - "dox": "0.4.4", - "uglify-js": "1.2.5", - "ejs": "0.6.1", - "request": "2.12.0", - "nodeunit": "0.7.3", - "markdown": "0.3.1", - "gleak": "0.5.0", - "step": "0.0.5", - "async": "0.1.22", - "integra": "0.1.8", - "optimist": "latest", - "rimraf": "2.2.6", - "semver": "4.1.0", - "mongodb-core": "1.1.3" - }, - "optionalDependencies": { - "kerberos": "0.0.6", - "readable-stream": "latest" - }, - "config": { - "native": false - }, - "main": "./lib/mongodb/index", - "homepage": "http://mongodb.github.com/node-mongodb-native/", - "directories": { - "lib": "./lib/mongodb" - }, - "engines": { - "node": ">=0.6.19" - }, - "scripts": { - "test": "node test/runner.js -t functional" - }, - "licenses": [ - { - "type": "Apache License, Version 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0" - } - ], - "gitHead": "5fb481a1e1d127c48550de6f7ddf3acf52cc2fab", - "_id": "mongodb@1.4.23", - "_shasum": "da19ffb2b16a7182b92460a9ff4207b3bb2fb9b6", - "_from": "mongodb@", - "_npmVersion": "2.0.0", - "_npmUser": { - "name": "christkv", - "email": "christkv@gmail.com" - }, - "maintainers": [ - { - "name": "christkv", - "email": "christkv@gmail.com" - } - ], - "dist": { - "shasum": "da19ffb2b16a7182b92460a9ff4207b3bb2fb9b6", - "tarball": "http://registry.npmjs.org/mongodb/-/mongodb-1.4.23.tgz" - }, - "_resolved": "https://registry.npmjs.org/mongodb/-/mongodb-1.4.23.tgz", - "readme": "ERROR: No README data found!" -} diff --git a/node_modules/neon/.npmignore b/node_modules/neon/.npmignore deleted file mode 100644 index 3c3629e..0000000 --- a/node_modules/neon/.npmignore +++ /dev/null @@ -1 +0,0 @@ -node_modules diff --git a/node_modules/neon/CHANGELOG.markdown b/node_modules/neon/CHANGELOG.markdown deleted file mode 100644 index cb2fde4..0000000 --- a/node_modules/neon/CHANGELOG.markdown +++ /dev/null @@ -1,22 +0,0 @@ -2.0.0 (2014-02-15) - - - Requiring now adds Class, Module, Interface to global scope (neon) - - You can now require the stdlib with require('neon/stdlib') - - Requiring now adds CustomEvent, CustomEventSupport, NodeSupport - and BubblingSupport to the global scope (stdlib) - - Major version bump because it's not compatible with 1.x (The other - was loaded in a namespace) - -1.1.0 (2014-01-29) - - - Added stdlib, consisting on: - - NodeSupport - - CustomEvent and CustomEventSupport - - BubblingSupport - - Added tests for stdlib - - Moved files to /lib - -1.0.0 (2012-06-23) - - - Cleaned up and packed Neon library, used already in production. - Added usage files, improved documentation. diff --git a/node_modules/neon/README.markdown b/node_modules/neon/README.markdown deleted file mode 100644 index 2e7d4bf..0000000 --- a/node_modules/neon/README.markdown +++ /dev/null @@ -1,76 +0,0 @@ -= Neon - -== JavaScript DSL for Classical Inheritance - -This files provides a DSL for the following design patterns: - -* inheritance -* interface -* module - -Neon packs a DSL for Class creation, that helps in making programs following an object oriented design. - -The philosophy is that it should not try to emulate other languages, so it preserves the JavaScript good parts, -but with a nicer syntax to create classes that ensure interfaces and include reusable functionality as modules. - -== Why another Class System? - -As the web applications are getting more complex these times, backend and frontend engineers work has fusioned, and they need to be able to establish a common language. It was created for people coming from OOP languages like Ruby to Javascript. - -=== Usage - - Interface('Editable')({ - constructor : ['x'], - prototype : ['x'] - }); - - Module('Composition')({ - y : 5, - prototype : { - z : 3 - } - }); - - Module('Other')({ - a : 5, - prototype : { - b : 3 - } - }); - - Class('Overlay').inherits(Widget).ensures(Editable).includes(Composition, Other)({ - html : '
', - prototype : { - init : function (element){ - if(!element){ - element = document.createElement('div'); - element.innerHTML = 'hello'; - document.body.appendChild(element); - } - }, - b : 5 - } - }); - -== License - -Copyright (c) 2009 Fernando Trasviña - -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/neon/neon.js b/node_modules/neon/neon.js deleted file mode 100644 index bf0b94c..0000000 --- a/node_modules/neon/neon.js +++ /dev/null @@ -1,234 +0,0 @@ - -if (typeof global === "undefined") { - global = window; -} - -global.Interface = function Interface(nameOrNameSpace, name) { - var nameSpace, interfaceName, factory; - nameSpace = (nameOrNameSpace && name) ? nameOrNameSpace : this; - interfaceName = (nameOrNameSpace && name) ? name : - (nameOrNameSpace) ? nameOrNameSpace : 'interface' + Math.random().toString(); - factory = function(definition) { - definition.isInterface = true; - definition.name = interfaceName; - nameSpace[interfaceName] = definition; - return nameSpace[interfaceName]; - }; - return factory; -}; - -global.Module = function Module(nameOrNameSpace, name) { - var nameSpace, moduleName, factory, newModule; - - nameSpace = (nameOrNameSpace && name) ? nameOrNameSpace : this; - moduleName = (nameOrNameSpace && name) ? name : - (nameOrNameSpace) ? nameOrNameSpace : 'module' + Math.random().toString(); - - newModule = { - moduleName : moduleName, - prototype : {}, - __includedModules : [], - include : function(module) { - var property; - for (property in module) { - if (module.hasOwnProperty(property) - && property !== 'prototype' - && property !== 'isModule' - && property !== '__includedModules' - && property !== 'include' - && property !== 'moduleName') { - newModule[property] = module[property]; - } - } - - if (module.hasOwnProperty('prototype') && module.prototype) { - for (property in module.prototype) { - if (module.prototype.hasOwnProperty(property)) { - newModule.prototype[property] = module.prototype[property]; - } - } - } - else { - module.prototype = {}; - } - - this.__includedModules.push(module); - - return this; - } - } - - factory = function(definition){ - var property; - - newModule.isModule = true; - - for (property in definition) { - if (definition.hasOwnProperty(property) - && property !== 'prototype' - && property !== 'isModule' - && property !== '__includedModules' - && property !== 'include' - && property !== 'moduleName') { - newModule[property] = definition[property]; - } - } - - if (definition.hasOwnProperty('prototype') && definition.prototype) { - for (property in definition.prototype) { - if (definition.prototype.hasOwnProperty(property)) { - newModule.prototype[property] = definition.prototype[property]; - } - } - } - - nameSpace[moduleName] = newModule; - - return nameSpace[moduleName]; - }; - - factory.includes = function () { - for(var i = 0; i < arguments.length; i++){ - newModule.include(arguments[i]); - } - return factory; - }; - - return factory; -}; - -global.Class = function Class(classNameOrNameSpace, className) { - var nameSpace, newClass, classFactory; - nameSpace = (classNameOrNameSpace && className) ? classNameOrNameSpace : global; - className = (classNameOrNameSpace && className) ? className : - (classNameOrNameSpace) ? classNameOrNameSpace : 'class' + Math.random().toString(); - - newClass = function() { - if (this.init) { - this.init.apply(this, arguments); - } - }; - - newClass.__descendants = []; - newClass.__implementedInterfaces = []; - newClass.__includedModules = []; - newClass.className = className; - newClass.include = function(module) { - var property; - for (property in module) { - if (module.hasOwnProperty(property) - && property != 'prototype' - && property != 'constructor' - && property != 'isModule' - && property != 'superClass' - && property != 'include') { - newClass[property] = module[property]; - } - } - - if (module.hasOwnProperty('prototype') && module.prototype) { - for (property in module.prototype) { - if (module.prototype.hasOwnProperty(property)) { - newClass.prototype[property] = module.prototype[property]; - } - } - } else { - module.prototype = {}; - } - - newClass.__includedModules.push(module); - return this; - }; - - classFactory = function(classDefinition) { - var i, il, j, jl, property, classPrototype = classDefinition.prototype; - if (classPrototype) { - for (property in classPrototype) { - if (classPrototype.hasOwnProperty(property)) { - newClass.prototype[property] = classPrototype[property]; - } - } - delete classDefinition.prototype; - } - for (property in classDefinition) { - if (classDefinition.hasOwnProperty(property)) { - newClass[property] = classDefinition[property]; - } - } - - for (i = 0, il = newClass.__implementedInterfaces.length; i < il; i++) { - for (j = 0, jl = newClass.__implementedInterfaces[i].constructor.length; j < jl; j++) { - if (!newClass[ newClass.__implementedInterfaces[i].constructor[j] ]) { - console.log('must implement static ' + newClass.__implementedInterfaces[i].name); - break; - } - } - - if (newClass.__implementedInterfaces[i].hasOwnProperty('prototype') - && newClass.__implementedInterfaces[i].prototype) { - for (j = 0, jl = newClass.__implementedInterfaces[i].prototype.length; j < jl; j++) { - if (!newClass.prototype[newClass.__implementedInterfaces[i].prototype[j]]) { - console.log('must implement prototype ' + newClass.__implementedInterfaces[i].name); - break; - } - } - } - } - - try { - if (Li && Li.ObjectSpy && Li.Spy) { - newClass.__objectSpy = new Li.ObjectSpy(); - newClass.__objectSpy.spy(newClass); - newClass.__objectSpy.spy(newClass.prototype); - } - } catch (error) {} - - nameSpace[className] = newClass; - return newClass; - }; - - classFactory.inherits = function(superClass) { - var i, inheritedClass; - newClass.superClass = superClass; - if (superClass.hasOwnProperty('__descendants')) { - superClass.__descendants.push(newClass); - } - inheritedClass = function() { - }; - inheritedClass.prototype = superClass.prototype; - newClass.prototype = new inheritedClass(); - newClass.prototype.constructor = newClass; - - for (i in superClass) { - if (superClass.hasOwnProperty(i) - && i != 'prototype' - && i !== 'className' - && i !== 'superClass' - && i !== 'include' - && i != '__descendants') { - newClass[i] = superClass[i]; - } - } - - delete this.inherits; - return this; - }; - - classFactory.ensures = function(interfaces) { - for (var i = 0; i < arguments.length; i++) { - newClass.__implementedInterfaces.push(arguments[i]); - } - delete this.ensures; - return classFactory; - }; - - classFactory.includes = function() { - for (var i = 0; i < arguments.length; i++) { - newClass.include(arguments[i]); - } - return classFactory; - }; - - return classFactory; - -}; diff --git a/node_modules/neon/package.json b/node_modules/neon/package.json deleted file mode 100644 index aa60775..0000000 --- a/node_modules/neon/package.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "name": "neon", - "version": "2.0.0", - "description": "Javascript DSL for Classical Inheritance", - "main": "./neon", - "directories": { - "lib": "./lib" - }, - "repository": { - "type": "git", - "url": "https://github.com/azendal/neon.git" - }, - "keywords": [ - "class", - "prototype", - "inheritance", - "oop" - ], - "bugs": { - "url": "https://github.com/azendal/neon/issues" - }, - "_id": "neon@2.0.0", - "dist": { - "shasum": "eb70092c57fb03e2201c3682aed5b54ab9ed1316", - "tarball": "http://registry.npmjs.org/neon/-/neon-2.0.0.tgz" - }, - "_from": "neon@", - "_npmVersion": "1.2.25", - "_npmUser": { - "name": "chubas", - "email": "chubas7@gmail.com" - }, - "maintainers": [ - { - "name": "siedrix", - "email": "siedrix@gmail.com" - }, - { - "name": "benbeltran", - "email": "ben@nsovocal.com" - }, - { - "name": "chubas", - "email": "chubas7@gmail.com" - }, - { - "name": "azendal", - "email": "trasvina@gmail.com" - } - ], - "_shasum": "eb70092c57fb03e2201c3682aed5b54ab9ed1316", - "_resolved": "https://registry.npmjs.org/neon/-/neon-2.0.0.tgz", - "readme": "ERROR: No README data found!", - "homepage": "https://github.com/azendal/neon" -} diff --git a/node_modules/neon/stdlib/bubbling_support.js b/node_modules/neon/stdlib/bubbling_support.js deleted file mode 100644 index 30e0f5d..0000000 --- a/node_modules/neon/stdlib/bubbling_support.js +++ /dev/null @@ -1,32 +0,0 @@ -Module('BubblingSupport')({ - dispatch : function (type, data) { - data = data || {}; - var event = CustomEventSupport.prototype.dispatch.call(this, type, data); - if (event.isPropagationStopped === false) { - if (this.parent && this.parent.dispatch) { - data.target = event.target; - data.currentTarget = this.parent; - this.parent.dispatch(event.type, data); - } - } - return event; - }, - - prototype : { - dispatch : function (type, data) { - data = data || {}; - - var event = CustomEventSupport.prototype.dispatch.call(this, type, data); - - if (event.isPropagationStopped === false && event.bubbles === true) { - if (this.parent && this.parent.dispatch) { - data.target = event.target; - data.currentTarget = this.parent; - this.parent.dispatch(event.type, data); - } - } - - return event; - } - } - }); diff --git a/node_modules/neon/stdlib/custom_event.js b/node_modules/neon/stdlib/custom_event.js deleted file mode 100644 index c3c033c..0000000 --- a/node_modules/neon/stdlib/custom_event.js +++ /dev/null @@ -1,37 +0,0 @@ -Class('CustomEvent')({ - prototype : { - bubbles : true, - cancelable : true, - currentTarget : null, - timeStamp : 0, - target : null, - type : '', - isPropagationStopped : false, - isDefaultPrevented : false, - isImmediatePropagationStopped : false, - areImmediateHandlersPrevented : false, - init : function init(type, data) { - this.type = type; - if (typeof data !== 'undefined') { - for(var property in data) { - if (data.hasOwnProperty(property)) { - this[property] = data[property]; - } - } - } - }, - stopPropagation : function stopPropagation() { - this.isPropagationStopped = true; - }, - preventDefault : function preventDefault() { - this.isDefaultPrevented = true; - }, - stopImmediatePropagation : function stopImmediatePropagation() { - this.preventImmediateHandlers(); - this.stopPropagation(); - }, - preventImmediateHandlers : function preventImmediateHandlers() { - this.areImmediateHandlersPrevented = true; - } - } -}); diff --git a/node_modules/neon/stdlib/custom_event_support.js b/node_modules/neon/stdlib/custom_event_support.js deleted file mode 100644 index fecbd71..0000000 --- a/node_modules/neon/stdlib/custom_event_support.js +++ /dev/null @@ -1,180 +0,0 @@ -Module('CustomEventSupport')({ - - eventListeners : null, - - bind : function(type, eventHandler) { - var found, i, listeners; - - if(!this.eventListeners) { - this.eventListeners = {}; - } - - if(!this.eventListeners[type]) { - this.eventListeners[type] = []; - } - - found = false; - - listeners = this.eventListeners[type]; - for (i = 0; i < listeners.length; i++) { - if (listeners[i] === eventHandler) { - found = true; - break; - } - } - - if(!found) { - this.eventListeners[type].push(eventHandler); - } - - return this; - }, - - unbind : function(type, eventHandler) { - var i, found, listeners; - - found = false; - - if(!this.eventListeners) { - this.eventListeners = {}; - } - - if(typeof eventHandler == 'undefined') { - this.eventListeners[type] = []; - } - - listeners = this.eventListeners[type]; - for (i = 0; i < listeners.length; i++) { - if(listeners[i] === eventHandler) { - found = true; - break; - } - } - - if(found) { - this.eventListeners[type].splice(i, 1); - } - - return this; - }, - - dispatch : function(type, data) { - var event, listeners, instance, i; - - if (this.eventListeners === null) { - this.eventListeners = {}; - } - - if (typeof data === 'undefined') { - data = {}; - } - - if (data.hasOwnProperty('target') === false) { - data.target = this; - } - - event = new CustomEvent(type, data); - listeners = this.eventListeners[type] || []; - instance = this; - - for (i = 0; i < listeners.length; i = i + 1) { - listeners[i].call(instance, event); - if (event.areImmediateHandlersPrevented === true) { - break; - } - } - - return event; - }, - - prototype : { - - eventListeners : null, - - bind : function(type, eventHandler) { - var found, i, listeners; - - if(!this.eventListeners) { - this.eventListeners = {}; - } - - if(!this.eventListeners[type]) { - this.eventListeners[type] = []; - } - - found = false; - - listeners = this.eventListeners[type]; - for (i = 0; i < listeners.length; i++) { - if(listeners[i] === eventHandler) { - found = true; - break; - } - } - - if(!found) { - this.eventListeners[type].push(eventHandler); - } - - return this; - }, - - unbind : function(type, eventHandler) { - var i, found, listeners; - - found = false; - i = 0; - - if(!this.eventListeners) { - this.eventListeners = {}; - } - - if(typeof eventHandler == 'undefined') { - this.eventListeners[type] = []; - } - - listeners = this.eventListeners[type]; - for (i = 0; i < listeners.length; i++) { - if(listeners[i] == eventHandler) { - found = true; - break; - } - } - - if(found) { - this.eventListeners[type].splice(i, 1); - } - - return this; - }, - - dispatch : function(type, data) { - var event, listeners, instance, i; - - if (this.eventListeners === null) { - this.eventListeners = {}; - } - - if (typeof data === 'undefined') { - data = {}; - } - - if (data.hasOwnProperty('target') === false) { - data.target = this; - } - - event = new CustomEvent(type, data); - listeners = this.eventListeners[type] || []; - instance = this; - - for (i = 0; i < listeners.length; i = i + 1) { - listeners[i].call(instance, event); - if (event.areImmediateHandlersPrevented === true) { - break; - } - } - - return event; - } - } -}); diff --git a/node_modules/neon/stdlib/index.js b/node_modules/neon/stdlib/index.js deleted file mode 100644 index 862193b..0000000 --- a/node_modules/neon/stdlib/index.js +++ /dev/null @@ -1,7 +0,0 @@ -// This file is node only -if(typeof require !== 'undefined'){ - require('./custom_event'); - require('./custom_event_support'); - require('./node_support'); - require('./bubbling_support'); -} diff --git a/node_modules/neon/stdlib/node_support.js b/node_modules/neon/stdlib/node_support.js deleted file mode 100644 index b1e9473..0000000 --- a/node_modules/neon/stdlib/node_support.js +++ /dev/null @@ -1,123 +0,0 @@ -Module('NodeSupport')({ - prototype : { - parent : null, - - children : [], - - appendChild : function(child) { - if(child.parent) { - child.parent.removeChild(child); - } - - if(!this.hasOwnProperty('children')) { - this.children = []; - } - - this.children.push(child); - this[child.name] = child; - child.setParent(this); - return child; - }, - - insertBefore : function (child, beforeChild) { - var position; - - if (child.parent) { - child.parent.removeChild(child); - } - - if (!this.hasOwnProperty('children')) { - this.children = []; - } - - if (typeof beforeChild === 'undefined') { - this.appendChild(child); - } else { - position = this.children.indexOf(beforeChild); - this.children.splice(position, 0, child); - - this[child.name] = child; - child.setParent(this); - } - - return child; - - }, - - insertChild : function(child, position) { - console.warn('NodeSupport insertChild method is deprecated, try insertBefore'); - - if (child.parent) { - child.parent.removeChild(child); - } - - if (!this.hasOwnProperty('children')) { - this.children = []; - } - - if (typeof position == 'undefined') { - this.children.push(child); - this[child.name] = child; - child.setParent(this); - return child; - } - - this.children.splice(position, 0, child); - this[child.name] = child; - child.setParent(this); - return child; - }, - - removeChild : function (child) { - var position = this.children.indexOf(child); - - if (position !== -1) { - this.children.splice(position, 1); - delete this[child.name]; - child.parent = null; - } - - return child; - }, - - setParent : function (parent) { - this.parent = parent; - return this; - }, - - getDescendants : function () { - var nodes = []; - this.children.forEach(function (node) { - nodes.push(node); - }); - this.children.forEach(function (node) { - nodes = nodes.concat(node.getDescendants()); - }); - return nodes; - }, - - getPreviousSibling : function () { - if (typeof this.parent === 'undefined') { - return; - } - - if (this.parent.children[0] === this) { - return; - } - - return this.parent.children[ this.parent.children.indexOf(this) - 1 ]; - }, - - getNextSibling : function () { - if (typeof this.parent === 'undefined') { - return; - } - - if (this.parent.children[ this.parent.children.length - 1 ] === this) { - return; - } - - return this.parent.children[ this.parent.children.indexOf(this) + 1 ]; - } - } -}); diff --git a/node_modules/neon/test/neon_browser.html b/node_modules/neon/test/neon_browser.html deleted file mode 100644 index 9b3d15a..0000000 --- a/node_modules/neon/test/neon_browser.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - Neon - - - - -

Neon

- - diff --git a/node_modules/neon/test/neon_stdlib_browser.html b/node_modules/neon/test/neon_stdlib_browser.html deleted file mode 100644 index fd585a0..0000000 --- a/node_modules/neon/test/neon_stdlib_browser.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - Neon - - - - - - - - -

Neon

- - diff --git a/node_modules/neon/test/neon_stdlib_test.js b/node_modules/neon/test/neon_stdlib_test.js deleted file mode 100644 index bba9445..0000000 --- a/node_modules/neon/test/neon_stdlib_test.js +++ /dev/null @@ -1,84 +0,0 @@ -// @TODO: Make proper spec'ing and testing for these modules -if(typeof require !== 'undefined') { - console.log("Requiring neon stdlib from file"); - require('neon'); - require('neon/stdlib'); -} - -console.log("CustomEvent ", typeof CustomEvent !== 'undefined'); -console.log("CustomEventSupport ", typeof CustomEventSupport !== 'undefined'); -console.log("NodeSupport ", typeof NodeSupport !== 'undefined'); -console.log("BubblingSupport ", typeof BubblingSupport !== 'undefined'); - -console.log("--- node support") - -Class('TreeNode').includes(NodeSupport)({ - prototype : { - init : function(name) { - this.name = name; - } - } -}); - -var root = new TreeNode('root'); - -console.log(root); - -var left = new TreeNode('left'); -var right = new TreeNode('right'); - -root.appendChild(left); -right.setParent(root); - -console.log(root.children.indexOf(left)); -console.log(left == right.parent.left); - -Class('X').includes(CustomEventSupport)({ - prototype : { - init : function() { - - } - } -}); - -console.log('--- custom event support'); - -var sender = new X(); - -sender.dispatch('alert', { message : 'ERROR: nobody should be receiving yet' }); -sender.bind('alert', function(event) { - console.log(event.message == 'TEST'); -}); - -sender.dispatch('alert', { message : 'TEST' }); - -console.log('--- bubbling support'); - -Class('BubblingTreeNode').includes(NodeSupport, CustomEventSupport, BubblingSupport)({ - prototype : { - init : function(name) { - this.name = name; - this.bind('alert', function(event) { - console.log("Bound to alert on init (" + this.name + ")"); - }); - } - } -}); - -var root = new BubblingTreeNode('root'); -var son = root.appendChild(new BubblingTreeNode('son')); -var grandson = son.appendChild(new BubblingTreeNode('grandson')); - -console.log("Bubbles up"); -grandson.dispatch('alert'); - -console.log("Doesn't bubble down"); -root.dispatch('alert'); - -// @ TODO : Leave this tests to azendal, I have to read the browser's propagation spec -// console.log("Prevent default"); -// son.bind('alert', function(event) { -// console.log(event); -// event.preventImmediatePropagation(); -// }); -// grandson.dispatch('alert'); diff --git a/node_modules/neon/test/neon_test.js b/node_modules/neon/test/neon_test.js deleted file mode 100644 index d49a7b4..0000000 --- a/node_modules/neon/test/neon_test.js +++ /dev/null @@ -1,64 +0,0 @@ -if(typeof require !== 'undefined') { // We are in Node, need to require the file - - console.log("Requiring neon from file"); - require('neon'); - // In Coffeescript, the following construct is recommended - // { Class, Module, Interface } = require('neon') -} - - -console.log('Class :', typeof Class); -console.log('Module :', typeof Module); -console.log('Interface :', typeof Interface); - -Module('Composition')({ - moduleClassVariable : 1, - prototype : { - moduleInstanceVariable : 2 - } -}); - -Interface('Contract')({ - constructor : ['ensuredClassVariable'], - prototype : ['ensuredInstanceVariable'] -}); - -Class('BaseClass')({ - baseClassVariable : 3, - prototype : { - baseInstanceVariable : 4 - } -}); - -var AnonymousModule = Module()({ - anonymousClassVariable : 5, - prototype : { - anonymousInstanceVariable : 6 - } -}); - -Class('MyClass').inherits(BaseClass).ensures(Contract).includes(Composition, AnonymousModule)({ - GREETING : 'HELLO', - inheritedClassVariable : 7, - ensuredClassVariable : 8, - prototype : { - inheritedInstanceVariable : 9, - ensuredInstanceVariable : 10, - init : function(argument) { - console.log(this.constructor.GREETING + ' ' + argument + '!'); - } - } -}); - -var instance = new MyClass('world'); -console.log(MyClass.moduleClassVariable); -console.log(instance.moduleInstanceVariable); -console.log(MyClass.baseClassVariable); -console.log(instance.baseInstanceVariable); -console.log(MyClass.anonymousClassVariable); -console.log(instance.anonymousInstanceVariable); -console.log(MyClass.inheritedClassVariable); -console.log(MyClass.ensuredClassVariable); -console.log(instance.inheritedInstanceVariable); -console.log(instance.ensuredInstanceVariable); - diff --git a/node_modules/tellurium/CHANGELOG.md b/node_modules/tellurium/CHANGELOG.md deleted file mode 100644 index 50a8a6a..0000000 --- a/node_modules/tellurium/CHANGELOG.md +++ /dev/null @@ -1,5 +0,0 @@ -2.0.0 (2014-02-15) - - - Changed FirebugLogger for a console logger as the default one - - Requires new major version of neon, and follows the same pattern for - requiring tellurium \ No newline at end of file diff --git a/node_modules/tellurium/README.md b/node_modules/tellurium/README.md deleted file mode 100644 index a7066a9..0000000 --- a/node_modules/tellurium/README.md +++ /dev/null @@ -1,242 +0,0 @@ - +----+ - | Te | - +----+ - -Tellurium is a JavaScript Testing Framework using testing patterns like Mock, Stub, and Spy. - -## Features: - -* Support asynchronous specifications by default -* Support syncronous specifications via .sync() -* Support Scripted test by default -* Support guided tests via .guided() -* ... (yes there is more but why dont you give it a try?) - -This framework tries to go as close as possible with EcmaScript behaviour. so if you used anothers language -testing frameworks you may find that some of your tools are not here but trust me its better this way. - -## Does it work? -Yes Tellurium is tested with Tellurium - -## Is is used for other projects? -Yes it is but not many yet. but it really works, if not pls send me an issue or a msg. - -## Ok how can I use it? - - var someObj = { - good : true; - }; - - Tellurium.suite('my first test')({ - this.specify('someObj must be good')({ - this.assert(someObj.good).toBe(true); - }); - }); - - Tellurium.run(); - -## Theory of Operation - -Tellurium was designed to do front-end testing. this is a very important thing to consider because environment is very different from server side environments, so there is a number of objects that may be colliding and interacting to form a web application. Complex web applications tend to be event driven and not so much procedural because of the interaction of the user, network, and other events happening on the system in different order and on different times. - -Creating such system is not very easy to organize but there was some work done before and following the principle of unix of having small units of code that perform one task well, Tellurium has a number of dependencies instead of trying to build everything from the ground up. - -## Testing - -* **Test Method** - - Where do we put our test code? - - *We encode each test as a single Test Method on some class.* - -* **Four-Phase Test** (Setup -> Exercise -> Verify -> Teardown) - - How do we structure our test logic to make what we are testing obvious? - - *We structure each test with four distinct parts executed in sequence.* - -* **Assertion Method** - - How do we make tests self-checking? - - *We call a utility method to evaluate whether an expected outcome has been achieved.* - -* **Assertion Message** - - How do we structure our test logic to know which assertion failed? - - *We include a descriptive string argument in each call to an Assertion Method.* - -* **Testcase** - - Where do we put our test code? - - *Class We group a set of related Test Methods on a single Testcase Class.* - -* **Test Runner** - - How do we run the tests? - - *We define an application that instantiates a Test Suite Object and executes all the Testcase Objects it contains.* - -* **Testcase Object** - - How do we run the tests? - - *We create a Command object for each test and call the run method when we wish to execute it.* - -* **Test Suite Object** - - How do we run the tests when we have many tests to run? - - *We define a collection class that implements the standard test interface and use it to run a set of related Testcase Objects.* - -* **Test Discovery** - - How does the Test Runner know which tests to run? - - The Test Automation Framework discovers all tests that belong to the test suite automatically. - -* **Test Enumeration** - - How does the Test Runner know which tests to run? - - The test automater manually writes the code that enumerates all tests that belong to the test suite. - -* **Test Selection** - - How does the Test Runner know which tests to run? - - *The Test Automation Framework selects the Test Methods to be run at runtime based on attributes of the tests.* - -## This Library is based on the xUnit Test Patterns Book. - -* **Stub** - - How can we verify logic independently when it depends on indirect inputs from other software components? - - *We replace a real object with a test-specific object that feeds the desired indirect inputs into the system under test.* - -* **Spy** - - How do we implement Behavior Verification? How can we verify logic independently when it has indirect outputs to other software components? - - *We use a Test Double to capture the indirect output calls made to another component by the SUT for later verification by the test.* - -* **Mock** - - How do we implement Behavior Verification for indirect outputs of the SUT? How can we verify logic independently when it depends on indirect inputs from other software components? - - *We replace an object on which the SUT depends on with a test-specific object that verifies it is being used correctly by the SUT.* - -* **Assertion** - - How do we make tests self-checking? - - *We call a utility method to evaluate whether an expected outcome has been achieved.* - -* **Fresh Fixture Setup** - - * **Inline-Setup** - - How do we construct the Fresh Fixture? - - *Each Test Method creates its own Fresh Fixture by calling the appropriate constructor methods to build exactly the test fixture it requires.* - - * **Delegated Setup** - - How do we construct the Fresh Fixture? - - *Each Test Method creates its own Fresh Fixture by calling Creation Methods from within the Test Methods.* - - * **Creation Method** - How do we construct the Fresh Fixture? - - *We set up the test fixture by calling methods that hide the mechanics of building ready-to-use objects behind Intent-Revealing Names.* - - * **Implicit Setup** - - How do we construct the Fresh Fixture? - - *We build the test fixture common to several tests in the setUp method.* - -* **Shared Fixture Construction** - - * **Prebuilt Fixture** - - How do we cause the Shared Fixture to be built before the first test method that needs it? - - *We build the Shared Fixture separately from running the tests.* - - * **Lazy Setup** - - How do we cause the Shared Fixture to be built before the first test method that needs it? - - *We use Lazy Initialization of the fixture to create it in the first test that needs it.* - - * **Suite Fixture Setup** - - How do we cause the Shared Fixture to be built before the first test method that needs it? - - *We build/destroy the shared fixture in special methods called by the Test Automation Framework before/after the first/last Test Method is called.* - - * **Setup Decorator** - - How do we cause the Shared Fixture to be built before the first test method that needs it? - - *We wrap the test suite with a Decorator that sets up the shared test fixture before running the tests and tears it down after all tests are done.* - - * **Chained Tests** - - How do we cause the Shared Fixture to be built before the first test method that needs it? - - *We let the other tests in a test suite set up the test fixture.* - -## Testing Strategies - -* **Recorded Test** - - How do we prepare automated tests for our software? - - *We automate tests by recording interactions with the application and playing them back using a test tool.* - -* **Scripted Test** - - How do we prepare automated tests for our software? - - *We automate the tests by writing test programs by hand.* - -* **Data-Driven Test** - - How do we prepare automated tests for our software? How do we reduce Test Code Duplication? - - *We store all the information needed for each test in a data file and write an interpreter that reads the file and executes the tests.* - -* **Guided Test** - - How do we prepare automated tests for our software? How do we not forget a test? - - *We combine scripted or data-driven test with something similar to a recorded test (but that recorded process cannot dupplicate). and guide the tester trough the tests.* - - - -### Dependencies - -* Neon (Object Organization DSL) -* CustomEvent (Synthetic events for objects) -* CustomEventSupport (Includable module to give the ability of customEvents to an object) - -### Objects from Tellurium - -* Tellurium (<> <> <>. is the initial point of almost all operations); -* Tellurium.Stub (<>. Mechanism to define a non implemented property) -* Tellurium.Stub.Factory (<>. Provides Stub functionality to an Object) -* Tellurium.Spy -* Tellurium.Spy.Factory -* Tellurium.Assertion -* Tellurium.Context -* Tellurium.Suite -* Tellurium.Description -* Tellurium.Specification -* Tellurium.Reporter - diff --git a/node_modules/tellurium/build/tellurium-min.js b/node_modules/tellurium/build/tellurium-min.js deleted file mode 100644 index bb8de46..0000000 --- a/node_modules/tellurium/build/tellurium-min.js +++ /dev/null @@ -1 +0,0 @@ -var Te=Module("Tellurium")({children:[],completedChildren:[],isCompleted:false,reporter:null,suite:function(b){var a=function(d){var c=new Tellurium.Suite(b,d);c.setParent(Tellurium);Tellurium.children.push(c);return c};return a},run:function(c){var b,a,d;this.completedChildren=[];this.isCompleted=false;if(typeof c==="string"){c=[c]}if(c){for(a=0;a0)},toBeCalledWith:function(a){return(this.actual.called[0].arguments===a)},toReturn:function(a){return(this.actual.called[0].returned===a)},toBeGreaterThan:function(a){return(this.actual>a)},toBeLessThan:function(a){return(this.actual - - - Tellurium Test Runner - - - - - - - - - - - - - - - diff --git a/node_modules/tellurium/tellurium.js b/node_modules/tellurium/tellurium.js deleted file mode 100644 index 2eeda6b..0000000 --- a/node_modules/tellurium/tellurium.js +++ /dev/null @@ -1,901 +0,0 @@ -if(typeof require !== 'undefined') { - require('neon'); -} - -Module('Tellurium')({ - children : [], - completedChildren : [], - isCompleted : false, - reporter : null, - - suite : function (description) { - var factory = function (code) { - var suite = new Tellurium.Suite(description, code); - suite.setParent(Tellurium); - Tellurium.children.push(suite); - return suite; - }; - - return factory; - }, - - run : function (ids) { - var i, j, id; - - this.completedChildren = []; - this.isCompleted = false; - - if (typeof ids === 'string') { - ids = [ids]; - } - - if (ids) { - for (j = 0; j < ids.length; j += 1) { - id = ids[j]; - for (i = 0; i < this.children.length; i += 1) { - if (this.children[i].description === id) { - console.time('run ' + this.children[i].description); - this.children[i].run(); - } - } - } - } else { - console.time('run all'); - for (i = 0; i < this.children.length; i += 1) { - Tellurium.children[i].run(); - } - } - - return this; - }, - - childCompleted : function (child) { - this.completedChildren.push(child); - - if (this.reporter === null) { - this.reporter = new Tellurium.Reporter.Console(); - } - // console.timeEnd('run ' + child.description); - this.reporter.run(child); - - if (this.children.length === this.completedChildren.length) { - this.completed(); - } - - return this; - }, - - completed : function () { - this.isCompleted = true; - // console.timeEnd('run all'); - return this; - } -}); - -Class(Tellurium, 'Stub')({ - prototype : { - targetObject : null, - methodName : null, - newMethod : null, - originalMethod : null, - - init : function (config) { - config = config || {}; - - this.targetObject = config.targetObject; - this.methodName = config.methodName; - this.newMethod = config.newMethod; - }, - - applyStub : function () { - this.originalMethod = this.targetObject[this.methodName]; - this.targetObject[this.methodName] = this.newMethod; - return this; - }, - - removeStub : function () { - this.targetObject[this.methodName] = this.originalMethod; - return this; - }, - - on : function (targetObject) { - this.targetObject = targetObject; - return this; - }, - - method : function (methodName) { - this.methodName = methodName; - return this; - }, - - using : function (newMethod) { - this.newMethod = newMethod; - this.applyStub(); - return this; - } - } -}); - -Module(Tellurium.Stub, 'Factory')({ - prototype : { - stubs : null, - - stub : function () { - var stub = new Tellurium.Stub(); - this.stubs = this.stubs || []; - this.stubs.push(stub); - return stub; - }, - - cleanStubs : function () { - var i; - - for (i = 0; i < this.stubs.length; i += 1) { - this.stubs[i].removeStub(); - } - - return this; - } - } -}); - -Class(Tellurium, 'Spy')({ - prototype : { - targetObject : null, - methodName : null, - spyMethod : null, - originalMethod : null, - objectHasMethod : null, - called : null, - - init : function (config) { - config = config || {}; - - this.called = []; - this.targetObject = config.targetObject; - this.methodName = config.methodName; - }, - - applySpy : function () { - var spy; - - spy = this; - if (this.targetObject.hasOwnProperty(this.methodName) === false) { - this.objectHasMethod = false; - } - else { - this.objectHasMethod = true; - } - - this.originalMethod = this.targetObject[this.methodName]; - - this.targetObject[this.methodName] = function () { - var args, result; - args = Array.prototype.slice.call(arguments, 0, arguments.length); - var scope = this; - - if (this === spy) { - scope = spy.targetObject; - } - - var startTime = Date.now(); - result = spy.originalMethod.apply(scope, args); - var endTime = Date.now(); - - spy.called.push({ - arguments : args, - returned : result, - time : endTime - startTime - }); - return result; - }; - return this; - }, - - removeSpy : function () { - if (this.objectHasMethod === true) { - this.targetObject[this.methodName] = this.originalMethod; - } - else { - delete this.targetObject[this.methodName]; - } - return this; - }, - - on : function (targetObject) { - this.targetObject = targetObject; - return this; - }, - - method : function (methodName) { - this.methodName = methodName; - this.applySpy(); - return this; - } - } -}); - -Module(Tellurium.Spy, 'Factory')({ - prototype : { - spies : null, - spy : function () { - var spy = new Tellurium.Spy(); - this.spies = this.spies || []; - this.spies.push(spy); - return spy; - }, - - cleanSpies : function () { - var i; - - for (i = 0; i < this.spies.length; i += 1) { - this.spies[i].removeSpy(); - } - - return this; - } - } -}); - -Class(Tellurium, 'Assertion')({ - includeAssertions : function (assertions) { - var assertion; - for (assertion in assertions) { - if (assertions.hasOwnProperty(assertion)) { - this.prototype.addAssert(assertion, assertions[assertion]); - } - } - - return this; - }, - - prototype : { - TYPE_TRUE : 'TYPE_TRUE', - TYPE_FALSE : 'TYPE_FALSE', - STATUS_FAIL : 'STATUS_FAIL', - STATUS_SUCCESS : 'STATUS_SUCCESS', - actual : null, - expected : null, - spec : null, - status : null, - type : null, - label : null, - - init : function (actual, spec) { - this.type = this.TYPE_TRUE; - this.actual = actual; - this.spec = spec; - }, - - withLabel : function (label) { - this.label = label; - return this; - }, - - not : function () { - this.type = this.TYPE_FALSE; - return this; - }, - - notify : function (assertResult) { - if (assertResult === true) { - if (this.type === this.TYPE_FALSE) { - this.status = this.STATUS_FAIL; - this.spec.assertionFailed(this); - } else { - this.status = this.STATUS_SUCCESS; - this.spec.assertionPassed(this); - } - } else { - if (this.type === this.TYPE_FALSE) { - this.status = this.STATUS_SUCCESS; - this.spec.assertionPassed(this); - } else { - this.status = this.STATUS_FAIL; - this.spec.assertionFailed(this); - } - } - - return this; - }, - - addAssert : function (name, assertFn) { - this[name] = function () { - var args; - - args = Array.prototype.slice.call(arguments, 0, arguments.length); - this.invoked = name; - this.expected = args; - this.notify(assertFn.apply(this, args)); - return this; - }; - - return this; - } - } -}); - -Tellurium.Assertion.includeAssertions({ - toBe : function (expected) { - return (this.actual === expected); - }, - - toEqual : function (expected) { - return (this.actual == expected); - }, - - toMatch : function (expected) { - return (expected.test(this.actual) === true); - }, - - toBeDefined : function () { - return (typeof this.actual !== 'undefined'); - }, - - toBeNull : function () { - return (this.actual === null); - }, - - toBeTruthy : function () { - return ((this.actual) ? true : false); - }, - - toBeCalled : function () { - return (this.actual.called.length > 0); - }, - - toBeCalledWith : function (expected) { - return (this.actual.called[0].arguments === expected); - }, - - toReturn : function (expected) { - return (this.actual.called[0].returned === expected); - }, - - toBeGreaterThan : function (expected) { - return (this.actual > expected); - }, - - toBeLessThan : function (expected) { - return (this.actual < expected); - }, - - toBeInstanceOf : function (expected) { - return (this.actual.constructor === expected); - }, - - toThrowError : function (expected) { - try { - this.actual(); - } catch (e) { - if (e === expected || e.name === expected) { - return true; - } - } - return false; - }, - - toNotThrowError : function () { - try { - this.actual(); - return true; - } catch (e) { - return false; - } - } -}); - -Module(Tellurium, 'Context')({ - prototype : { - registry : null, - description : null, - code : null, - parent : null, - children : null, - completedChildren : null, - setupCode : null, - tearDownCode : null, - beforeEachPool : null, - completedBeforeEach : null, - afterEachPool : null, - completedAfterEach : null, - isCompleted : null, - - init : function (description, code) { - this.registry = []; - this.description = description; - this.code = code; - this.children = []; - this.completedChildren = []; - this.beforeEachPool = []; - this.completedBeforeEach = []; - this.completedAfterEach = []; - this.afterEachPool = []; - this.isCompleted = false; - }, - - appendChild : function (child) { - if (child.parent) { - child.parent.removeChild(child); - } - - this.children.push(child); - child.setParent(this); - - return child; - }, - - setParent : function (parent) { - this.parent = parent; - - return this; - }, - - setup : function (code) { - this.setupCode = new Tellurium.Executable(code); - return this; - }, - - tearDown : function (code) { - this.tearDownCode = new Tellurium.Executable(code); - return this; - }, - - describe : function (description) { - var current, fn, guided; - - current = this; - - fn = function (code) { - var describe = new Tellurium.Description(description, code); - - if (guided === true) { - describe.guided = true; - var index = 0; - describe.run = function () { - this.code.call(this, this); - - if (this.children.length === 0) { - this.completed(); - } - - if (this.setupCode) { - this.setupCode.run(); - } - - if (this.children[index] instanceof Tellurium.Specification) { - this.runBeforeEach(this, this.children[index]); - } - - this.children[index].run(); - - return this; - }; - - describe.childCompleted = function (child) { - this.completedChildren.push(child); - - if (child instanceof Tellurium.Specification) { - this.runAfterEach(child); - } - - if (this.children.length === this.completedChildren.length) { - this.completed(); - } else { - index = index + 1; - if (this.children[index] instanceof Tellurium.Specification) { - this.runBeforeEach(this, this.children[index]); - } - this.children[index].run(); - } - - return this; - }; - } else { - describe.guided = false; - } - - current.appendChild(describe); - - return current; - }; - - fn.guided = function () { - guided = true; - return fn; - }; - - return fn; - }, - - specify : function (description) { - var current = this; - var sync = false; - var fn = function (code) { - var specification = new Tellurium.Specification(description, code); - specification.sync = sync; - current.appendChild(specification); - }; - - fn.sync = function () { - sync = true; - return fn; - }; - - return fn; - }, - - beforeEach : function (code) { - this.beforeEachPool.push(code); - - return this; - }, - - afterEach : function (code) { - this.afterEachPool.push(code); - - return this; - }, - - run : function () { - var i, context; - - context = this; - this.children = []; - this.completedChildren = []; - - this.code.call(this, this); - - if (this.children.length === 0) { - this.completed(); - } - - if (this.setupCode) { - this.setupCode.onCompleted(function () { - for (i = 0; i < context.children.length; i += 1) { - if (context.children[i] instanceof Tellurium.Specification) { - context.runBeforeEach(context, context.children[i]); - } - context.children[i].run(); - } - }); - this.setupCode.run(); - } else { - for (i = 0; i < this.children.length; i += 1) { - if (this.children[i] instanceof Tellurium.Specification || this.children[i] instanceof Tellurium.Description) { - this.runBeforeEach(this.children[i], this); - } - this.children[i].run(); - } - } - - return this; - }, - - runBeforeEach : function (target, context) { - var i; - - context = context || this; - - if (this.parent && this.parent.runBeforeEach) { - this.parent.runBeforeEach(target, context); - } - - for (i = 0; i < this.beforeEachPool.length; i += 1) { - this.beforeEachPool[i].call(target, target, context); - } - - return this; - }, - - runAfterEach : function (target, context) { - var i; - - context = context || this; - - if (this.parent && this.parent.runAfterEach) { - this.parent.runAfterEach(target, context); - } - - for (i = 0; i < this.afterEachPool.length; i += 1) { - this.afterEachPool[i].call(target, target, context); - } - - return this; - }, - - childCompleted : function (child) { - this.completedChildren.push(child); - - if (child instanceof Tellurium.Specification || child instanceof Tellurium.Description) { - this.runAfterEach(child, this); - } - - if (this.children.length === this.completedChildren.length) { - this.completed(); - } - - return this; - }, - - completed : function () { - var context; - - context = this; - - this.isCompleted = true; - - if (this.spies) { - this.cleanSpies(); - } - - if (this.stubs) { - this.cleanStubs(); - } - - if (this.tearDownCode) { - this.tearDownCode.onCompleted(function () { - if (context.parent) { - context.parent.childCompleted(context); - } - }); - this.tearDownCode.run(); - } else { - if (this.parent) { - this.parent.childCompleted(this); - } - } - - return this; - } - } -}); - -Class(Tellurium, 'Executable')({ - prototype : { - code : null, - isCompleted : null, - isAsynchronous : true, - - init : function (code) { - this.code = code; - }, - - completed : function () { - this.isCompleted = true; - this.onCompletedCode(); - return this; - }, - - run : function () { - this.isCompleted = false; - this.code.apply(this); - return this; - }, - - onCompleted : function (code) { - this.onCompletedCode = function () { - code(); - return this; - }; - return this; - } - } -}); - -Class(Tellurium, 'Suite').includes(Tellurium.Context, Tellurium.Stub.Factory, Tellurium.Spy.Factory)({}); - -Class(Tellurium, 'Description').includes(Tellurium.Context, Tellurium.Stub.Factory, Tellurium.Spy.Factory)({ - prototype : { - guided : false - } -}); - -Class(Tellurium, 'Specification').includes(Tellurium.Stub.Factory, Tellurium.Spy.Factory)({ - prototype : { - STATUS_PENDING : 'STATUS_PENDING', - STATUS_FAIL : 'STATUS_FAIL', - STATUS_SUCCESS : 'STATUS_SUCCESS', - description : null, - code : null, - parent : null, - assertions : null, - registry : null, - status : null, - isCompleted : null, - sync : false, - - init : function (description, code) { - this.description = description; - this.code = code; - this.registry = {}; - this.assertions = []; - this.spies = []; - this.stubs = []; - this.isCompleted = false; - }, - - setParent : function (parent) { - this.parent = parent; - return this; - }, - - run : function () { - if (this.code) { - this.code.call(this, this); - if (this.sync === true) { - this.completed(); - } - } else { - this.pending(); - } - }, - - pending : function () { - this.status = this.STATUS_PENDING; - this.completed(); - }, - - assertionPassed : function () { - if (this.status !== this.STATUS_FAIL) { - this.status = this.STATUS_SUCCESS; - } - - return this; - }, - - assertionFailed : function () { - this.status = this.STATUS_FAIL; - - return this; - }, - - assert : function (actual) { - - if (this.isCompleted === true) { - throw "called assert on a completed test"; - } - - var assertion = new Tellurium.Assertion(actual, this); - this.assertions.push(assertion); - return assertion; - }, - - mock : function () { - return {}; - }, - - completed : function () { - - if (this.isCompleted === true) { - throw "called completed more than once for test"; - } - - this.isCompleted = true; - - if (this.spies) { - this.cleanSpies(); - } - - if (this.stubs) { - this.cleanStubs(); - } - - if (this.status === null) { - this.status = this.STATUS_SUCCESS; - } - - this.parent.childCompleted(this); - - return this; - } - } -}); - -Tellurium.Reporter = {}; - -/* - * Standard console, nothing fancy. Override this one or create one, - * depending on your needs - */ -Class(Tellurium.Reporter, 'Console')({ - prototype : { - totalSpecs : null, - failedSpecs : null, - passedSpecs : null, - pendingSpecs : null, - - init : function () { - this.totalSpecs = 0; - this.failedSpecs = 0; - this.passedSpecs = 0; - this.pendingSpecs = 0; - }, - - run : function (suite) { - console.log("==========================="); - console.log('Tellurium Test Results for ' + suite.description); - this.totalSpecs = 0; - this.passedSpecs = 0; - this.failedSpecs = 0; - this.pendingSpecs = 0; - - this.suite(suite); - console.info('Total: ', this.totalSpecs); - console.info('Passed: ', this.passedSpecs); - console.info('Failed: ' + this.failedSpecs); - console.warn('Pending: ', this.pendingSpecs); - console.log("==========================="); - }, - - suite : function (suite) { - var i; - - console.log(' ' + suite.description); - - for (i = 0; i < suite.children.length; i += 1) { - if (suite.children[i] instanceof Tellurium.Description) { - this.description(suite.children[i]); - } else if (suite.children[i] instanceof Tellurium.Specification) { - this.specification(suite.children[i]); - } - } - }, - - description : function (description) { - var i; - console.log(' ' + description.description); - - for (i = 0; i < description.children.length; i += 1) { - if (description.children[i] instanceof Tellurium.Description) { - this.description(description.children[i]); - } else if (description.children[i] instanceof Tellurium.Specification) { - this.specification(description.children[i]); - } - } - - }, - - specification : function (specification) { - var i; - - this.totalSpecs = this.totalSpecs + 1; - - if (specification.status === specification.STATUS_FAIL) { - this.failedSpecs = this.failedSpecs + 1; - console.log("FAIL " + specification.description); - } else if (specification.status === specification.STATUS_SUCCESS) { - this.passedSpecs = this.passedSpecs + 1; - console.log("PASS " + specification.description); - } else if (specification.status === specification.STATUS_PENDING) { - this.pendingSpecs = this.pendingSpecs + 1; - console.log("PENDING " + specification.description); - } - - console.log("Assertions:"); - for (i = 0; i < specification.assertions.length; i += 1) { - this.assertion(specification.assertions[i]); - } - - }, - - assertion : function (assertion) { - var not; - if (assertion.type === Tellurium.Assertion.prototype.TYPE_FALSE) { - not = ' not '; - } else { - not = ' '; - } - - if (assertion.status === assertion.STATUS_SUCCESS) { - console.log(" " + assertion.label + " " + assertion.actual); - console.log(" " + assertion.label + " " + assertion.actual + - not + assertion.invoked + ' ' + (assertion.expected) ? assertion.expected : ''); - } else if (assertion.status === assertion.STATUS_FAIL) { - console.log(" " + assertion.label + " " + assertion.actual + - not + assertion.invoked + ' ' + (assertion.expected) ? assertion.expected : ''); - } - } - } -}); - From f3cad7c2699894ffcd5cbac7b08691d10639244a Mon Sep 17 00:00:00 2001 From: Gus Ortiz Date: Wed, 7 Jan 2015 23:33:59 -0600 Subject: [PATCH 3/4] Add search method to model and mongodb storage --- argon/model.js | 27 +++++++++++++++++++++++++++ argon/storage/mongodb.js | 16 ++++++++++++++++ package.json | 22 ++++++++++++++++++++++ spec/spec/argon/storage/mongodb.js | 29 +++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+) create mode 100644 package.json diff --git a/argon/model.js b/argon/model.js index 254abea..196a7cd 100644 --- a/argon/model.js +++ b/argon/model.js @@ -64,6 +64,33 @@ Module(Argon, 'Model').includes(CustomEventSupport, ValidationSupport)({ }); return this; }, + + /** + Fetches as many record matching a given query. Query lenguaje and structure + depends on the storage used for the model. + @method search + @argument query [Object] the query with the criteria to perform the lookup. + @argument callback [Function] method to handle data. + @return [Array]. + **/ + search : function search(query, callback) { + var Model; + + Model = this, + request = { + action : 'search', + model : Model, + query : query + }; + + this.storage.search(request, function searchCallback(data) { + if (callback) { + callback(data); + } + }); + + return this; + }, prototype : { diff --git a/argon/storage/mongodb.js b/argon/storage/mongodb.js index f1ce2db..f52638a 100644 --- a/argon/storage/mongodb.js +++ b/argon/storage/mongodb.js @@ -77,6 +77,22 @@ Class(Argon.Storage, 'MongoDB')({ return this; }, + search : function search(requestObj, callback) { + this.collection.find(requestObj.query, function searchCallback(error, data) { + if (error) { + return callback(error); + } + + data.toArray(function arrayHandler(error, documents) { + callback(JSON.parse(JSON.stringify(documents)).map(function (doc) { + return new requestObj.model(doc) + })); + }); + }); + + return this; + }, + remove : function remove(requestObj, callback) { var id = requestObj.data._id; diff --git a/package.json b/package.json new file mode 100644 index 0000000..62e6e11 --- /dev/null +++ b/package.json @@ -0,0 +1,22 @@ +{ + "name": "argon", + "description": "Javascript active record implementation.", + "version": "0.0.1", + "repository": { + "type": "git", + "url": "https://github.com/azendal/argon.git" + }, + "main": "argon.js", + "directories": { + "argon": "./argon" + }, + "keywords": [], + "dependencies": { + "mongodb": "^1.4.28", + "neon": "^2.0.0", + "tellurium": "^2.0.0" + }, + "engines": { + "node": "*" + } +} diff --git a/spec/spec/argon/storage/mongodb.js b/spec/spec/argon/storage/mongodb.js index ec5c3fd..cdc77f0 100644 --- a/spec/spec/argon/storage/mongodb.js +++ b/spec/spec/argon/storage/mongodb.js @@ -11,6 +11,10 @@ require('../../../../argon/storage'); require('../../../../argon/storage/mongodb'); require('tellurium'); +var TestModel = function TestModel(config) { + return config; +}; + setupSuite = function setupSuite(db) { Tellurium.suite('MongoDB Storage')(function(){ var storage = new Argon.Storage.MongoDB({ @@ -56,6 +60,31 @@ setupSuite = function setupSuite(db) { }); }); + + this.describe('Search records')(function () { + this.specify('should search and return matching records')(function () { + var spec = this, + gusData = {name : 'Gus', surname : 'Ortiz', age : 30}, + ferData = {name : 'Azendal', surname : 'Transvina', age : 5000}, + jonData = {name : 'Jon', surname : 'Snow', age : 18}; + + storage.create({model : TestModel, data : gusData}, function (gus) { + storage.create({model : TestModel, data : ferData}, function (fer) { + storage.create({model : TestModel, data : jonData}, function (jon) { + storage.search({model : TestModel, query : {age : {$lt : 40}}}, function (dudes) { + spec.assert(dudes.length).toBe(2); + spec.assert(dudes.map(function (dude) { + return dude.name; + }).sort().join(',')).toBe('Gus,Jon'); + + spec.completed(); + }) + }); + }); + }); + }) + }); + }); }; From e36ed3e06bba71bcaf446e9e4d6d847ecd0f8e2a Mon Sep 17 00:00:00 2001 From: Gus Ortiz Date: Wed, 7 Jan 2015 23:38:50 -0600 Subject: [PATCH 4/4] Add search methods to json rest and localstorage as find aliases --- argon/storage/json_rest.js | 9 +++++++++ argon/storage/local.js | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/argon/storage/json_rest.js b/argon/storage/json_rest.js index c64327c..396002a 100644 --- a/argon/storage/json_rest.js +++ b/argon/storage/json_rest.js @@ -376,6 +376,15 @@ Class(Argon.Storage, 'JsonRest')({ return this; }, + /** + Allias for find + @method search + **/ + search : function search(requestObj, callback) { + this.find(requestObj, callback); + return this; + }, + /** Updates from the resource @method put diff --git a/argon/storage/local.js b/argon/storage/local.js index 8a9b2f2..b4a4b50 100644 --- a/argon/storage/local.js +++ b/argon/storage/local.js @@ -224,6 +224,15 @@ Class(Argon.Storage, 'Local')({ return this; }, + /** + Allias for find + @method search + **/ + search : function search(requestObj, callback) { + this.find(requestObj, callback); + return this; + }, + /** Updates a set of data on the storage instance @method put