├── .editorconfig ├── .gitignore ├── .istanbul.yml ├── .jshintignore ├── .jshintrc ├── .travis.yml ├── API.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── bench ├── benchmark ├── README.md ├── analysis │ ├── promises-bluebird-parallel.js │ └── promises-bluebird.js ├── doxbee-sequential-errors │ ├── callbacks-baseline.js │ ├── callbacks-caolan-async-waterfall.js │ ├── callbacks-suguru03-neo-async-waterfall.js │ ├── promises-bluebird-generator.js │ ├── promises-bluebird.js │ ├── promises-calvinmetcalf-lie.js │ ├── promises-cujojs-when.js │ ├── promises-dfilatov-vow.js │ ├── promises-kriskowal-q.js │ ├── promises-lvivski-davy.js │ ├── promises-medikoo-deferred.js │ ├── promises-obvious-kew.js │ ├── promises-then-promise.js │ ├── promises-tildeio-rsvp.js │ ├── streamline-callbacks.js │ ├── streamline-generators.js │ └── streamline._js ├── doxbee-sequential │ ├── callbacks-baseline.js │ ├── callbacks-caolan-async-waterfall.js │ ├── callbacks-suguru03-neo-async-waterfall.js │ ├── generators-tj-co.js │ ├── observables-Reactive-Extensions-RxJS.js │ ├── observables-baconjs-bacon.js.js │ ├── observables-caolan-highland.js │ ├── observables-pozadi-kefir.js │ ├── promises-bluebird-generator.js │ ├── promises-bluebird.js │ ├── promises-calvinmetcalf-lie.js │ ├── promises-cujojs-when.js │ ├── promises-dfilatov-vow.js │ ├── promises-ecmascript6-native.js │ ├── promises-kriskowal-q.js │ ├── promises-lvivski-davy.js │ ├── promises-medikoo-deferred.js │ ├── promises-native-async-await.js │ ├── promises-obvious-kew.js │ ├── promises-then-promise.js │ ├── promises-tildeio-rsvp.js │ ├── streamline-callbacks.js │ ├── streamline-generators.js │ └── streamline._js ├── lib │ ├── catcher.js │ ├── dummy.js │ ├── fakemaker.js │ ├── fakes-ctx.js │ ├── fakes.js │ ├── fakesC.js │ ├── fakesO.js │ ├── fakesObservable.js │ ├── fakesP-ctx.js │ ├── fakesP.js │ ├── fakesSJS-dst.js │ ├── fakesSJS-src.sjs │ ├── promiseSupport.js │ └── timers-ctx.js ├── madeup-parallel │ ├── callbacks-baseline.js │ ├── callbacks-caolan-async-parallel.js │ ├── callbacks-suguru03-neo-async-parallel.js │ ├── generators-tj-co.js │ ├── promises-bluebird-generator.js │ ├── promises-bluebird.js │ ├── promises-calvinmetcalf-lie.js │ ├── promises-cujojs-when.js │ ├── promises-dfilatov-vow.js │ ├── promises-ecmascript6-native.js │ ├── promises-lvivski-davy.js │ ├── promises-medikoo-deferred.js │ ├── promises-native-async-await.js │ ├── promises-obvious-kew.js │ ├── promises-then-promise.js │ ├── promises-tildeio-rsvp.js │ ├── streamline-callbacks.js │ ├── streamline-generators.js │ └── streamline._js ├── package-lock.json ├── package.json └── performance.js ├── bower.json ├── build ├── changelog.md ├── deprecated_apis.md ├── docs ├── .gitignore ├── Gemfile ├── README.md ├── _config.yml ├── _layouts │ ├── api.html │ ├── default.html │ └── page.html ├── _plugins │ ├── mdate.rb │ └── plugin.rb ├── css │ ├── main.css │ └── mono-blue.css ├── docs │ ├── anti-patterns.md │ ├── api-reference.md │ ├── api │ │ ├── aggregateerror.md │ │ ├── all.md │ │ ├── any.md │ │ ├── ascallback.md │ │ ├── bind.md │ │ ├── built-in-error-types.md │ │ ├── call.md │ │ ├── cancel.md │ │ ├── cancellation.md │ │ ├── cancellationerror.md │ │ ├── catch.md │ │ ├── catchreturn.md │ │ ├── catchthrow.md │ │ ├── collections.md │ │ ├── core.md │ │ ├── deferred-migration.md │ │ ├── delay.md │ │ ├── disposer.md │ │ ├── done.md │ │ ├── each.md │ │ ├── environment-variables.md │ │ ├── error-management-configuration.md │ │ ├── error.md │ │ ├── filter.md │ │ ├── finally.md │ │ ├── generators.md │ │ ├── get.md │ │ ├── iscancelled.md │ │ ├── isfulfilled.md │ │ ├── ispending.md │ │ ├── isrejected.md │ │ ├── map.md │ │ ├── mapseries.md │ │ ├── new-promise.md │ │ ├── operationalerror.md │ │ ├── progression-migration.md │ │ ├── promise.all.md │ │ ├── promise.any.md │ │ ├── promise.bind.md │ │ ├── promise.config.md │ │ ├── promise.coroutine.addyieldhandler.md │ │ ├── promise.coroutine.md │ │ ├── promise.delay.md │ │ ├── promise.each.md │ │ ├── promise.filter.md │ │ ├── promise.fromcallback.md │ │ ├── promise.getnewlibrarycopy.md │ │ ├── promise.join.md │ │ ├── promise.longstacktraces.md │ │ ├── promise.map.md │ │ ├── promise.mapseries.md │ │ ├── promise.method.md │ │ ├── promise.noconflict.md │ │ ├── promise.onpossiblyunhandledrejection.md │ │ ├── promise.onunhandledrejectionhandled.md │ │ ├── promise.promisify.md │ │ ├── promise.promisifyall.md │ │ ├── promise.props.md │ │ ├── promise.race.md │ │ ├── promise.reduce.md │ │ ├── promise.reject.md │ │ ├── promise.resolve.md │ │ ├── promise.setscheduler.md │ │ ├── promise.some.md │ │ ├── promise.try.md │ │ ├── promise.using.md │ │ ├── promiseinspection.md │ │ ├── promisification.md │ │ ├── props.md │ │ ├── race.md │ │ ├── reason.md │ │ ├── reduce.md │ │ ├── reflect.md │ │ ├── resource-management.md │ │ ├── return.md │ │ ├── some.md │ │ ├── spread.md │ │ ├── suppressunhandledrejections.md │ │ ├── synchronous-inspection.md │ │ ├── tap.md │ │ ├── tapcatch.md │ │ ├── then.md │ │ ├── throw.md │ │ ├── timeout.md │ │ ├── timeouterror.md │ │ ├── timers.md │ │ ├── utility.md │ │ └── value.md │ ├── async-dialogs.md │ ├── beginners-guide.md │ ├── benchmarks.md │ ├── changelog.md │ ├── coming-from-other-languages.md │ ├── coming-from-other-libraries.md │ ├── contribute.md │ ├── deprecated-apis.md │ ├── deprecated_apis.md │ ├── download-api-reference.md │ ├── error-explanations.md │ ├── features.md │ ├── getting-started.md │ ├── install.md │ ├── new-in-bluebird-3.md │ ├── support.md │ ├── warning-explanations.md │ ├── what-about-generators.md │ ├── why-bluebird.md │ ├── why-performance.md │ ├── why-promises.md │ └── working-with-callbacks.md ├── helpers.rb ├── img │ ├── README.txt │ ├── favicon.png │ ├── libbblog_v3.png │ ├── logo.png │ └── supportlogo.png └── index.html ├── issue_template.md ├── package-lock.json ├── package.json ├── src ├── any.js ├── assert.js ├── async.js ├── bind.js ├── bluebird.js ├── call_get.js ├── cancel.js ├── catch_filter.js ├── constants.js ├── context.js ├── debuggability.js ├── direct_resolve.js ├── each.js ├── errors.js ├── es5.js ├── filter.js ├── finally.js ├── generators.js ├── join.js ├── map.js ├── method.js ├── nodeback.js ├── nodeify.js ├── promise.js ├── promise_array.js ├── promisify.js ├── props.js ├── queue.js ├── race.js ├── reduce.js ├── schedule.js ├── settle.js ├── some.js ├── synchronous_inspection.js ├── thenables.js ├── timers.js ├── using.js └── util.js ├── test ├── browser │ ├── es5-sham.js │ ├── es5-shim.js │ ├── have_getters.js │ ├── index.html │ ├── json.js │ ├── main.js │ ├── mocha.css │ ├── mocha.js │ ├── package.json │ ├── promise_debug.js │ ├── promise_instrumented.js │ └── worker.js └── mocha │ ├── 2.1.2.js │ ├── 2.1.3.js │ ├── 2.2.1.js │ ├── 2.2.2.js │ ├── 2.2.3.js │ ├── 2.2.4.js │ ├── 2.2.5.js │ ├── 2.2.6.js │ ├── 2.2.7.js │ ├── 2.3.1.js │ ├── 2.3.2.js │ ├── 2.3.3.js │ ├── 2.3.4.js │ ├── 3.2.1.js │ ├── 3.2.2.js │ ├── 3.2.3.js │ ├── 3.2.4.js │ ├── 3.2.5.js │ ├── 3.2.6.js │ ├── any.js │ ├── api_exceptions.js │ ├── async.js │ ├── async_hooks.js │ ├── bind.js │ ├── bluebird-multiple-instances.js │ ├── call.js │ ├── cancel.js │ ├── catch_filter.js │ ├── collections_thenables.js │ ├── constructor.js │ ├── cycles.js │ ├── direct_resolving.js │ ├── domain.js │ ├── done.js │ ├── each.js │ ├── error.js │ ├── filter.js │ ├── finally.js │ ├── following.js │ ├── generator.js │ ├── get.js │ ├── getNewLibraryCopy.js │ ├── github-2xx-76.js │ ├── github-3.6.4.js │ ├── github-3.7.3.js │ ├── github-4.1.7.js │ ├── github36.js │ ├── helpers │ ├── assert_long_trace.js │ ├── bluebird0_7_0.js │ ├── error.js │ ├── reasons.js │ ├── testThreeCases.js │ ├── thenables.js │ └── util.js │ ├── is.js │ ├── join.js │ ├── late_buffer_safety.js │ ├── long_stack_traces.js │ ├── map.js │ ├── method.js │ ├── monitoring.js │ ├── multiple-copies.js │ ├── no_conflict.js │ ├── nodeify.js │ ├── promise_array.js │ ├── promisify.js │ ├── props.js │ ├── race.js │ ├── reduce.js │ ├── reflect.js │ ├── regress.js │ ├── rejections.js │ ├── resolution.js │ ├── schedule.js │ ├── settle.js │ ├── some.js │ ├── spread.js │ ├── synchronous_inspection.js │ ├── tap.js │ ├── tapCatch.js │ ├── timers.js │ ├── try.js │ ├── unhandled_rejections.js │ └── using.js ├── tests └── tools ├── README.md ├── ast_passes.js ├── browser_test_generator.js ├── browser_test_runner.js ├── build.js ├── job-runner └── job-runner.js ├── jshint.js ├── jshintrc_generator.js ├── mocha_runner.js ├── saucelabs_runner.js ├── test.js └── utils.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # This file is for unifying the coding style for different editors and IDEs 2 | # editorconfig.org 3 | 4 | root = true 5 | 6 | [*] 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [**.js] 13 | indent_style = space 14 | indent_size = 4 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | docs/Gemfile.lock 2 | gh-pages 3 | node_modules 4 | gh-pages 5 | test/browser/bundle.js 6 | test/browser/worker_bundle.js 7 | js/* 8 | zalgo.js 9 | coverage/* 10 | .vscode 11 | .idea 12 | .jekyll-cache/* 13 | _site 14 | -------------------------------------------------------------------------------- /.istanbul.yml: -------------------------------------------------------------------------------- 1 | verbose: false 2 | instrumentation: 3 | root: . 4 | default-excludes: true 5 | excludes: [] 6 | embed-source: false 7 | variable: __coverage__ 8 | compact: true 9 | preserve-comments: false 10 | complete-copy: false 11 | save-baseline: false 12 | baseline-file: ./coverage/coverage-baseline.json 13 | include-all-sources: false 14 | reporting: 15 | print: summary 16 | reports: 17 | - lcov 18 | dir: ./coverage 19 | watermarks: 20 | statements: [50, 80] 21 | lines: [50, 80] 22 | functions: [50, 80] 23 | branches: [50, 80] 24 | report-config: 25 | clover: {file: clover.xml} 26 | cobertura: {file: cobertura-coverage.xml} 27 | json: {file: coverage-final.json} 28 | json-summary: {file: coverage-summary.json} 29 | lcovonly: {file: lcov.info} 30 | teamcity: {file: null} 31 | text: {file: null, maxCols: 0} 32 | text-summary: {file: null} 33 | hooks: 34 | hook-run-in-context: false 35 | post-require-hook: null 36 | handle-sigint: false 37 | check: 38 | global: 39 | statements: 0 40 | lines: 0 41 | branches: 0 42 | functions: 0 43 | excludes: [] 44 | each: 45 | statements: 0 46 | lines: 0 47 | branches: 0 48 | functions: 0 49 | excludes: [] 50 | -------------------------------------------------------------------------------- /.jshintignore: -------------------------------------------------------------------------------- 1 | src/constants.js 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | sudo: false 3 | matrix: 4 | include: 5 | - node_js: "0.10" 6 | - node_js: "0.12" 7 | - node_js: "4" 8 | - node_js: "5" 9 | - node_js: "6" 10 | - node_js: "7" 11 | - node_js: "8" 12 | - node_js: "10" 13 | fast_finish: true 14 | git: 15 | depth: 5 16 | env: 17 | - "NODE_FLAGS='--expose-gc' SCRIPT_FLAGS=''" 18 | before_script: 19 | - git submodule update --init --recursive 20 | script: "node $NODE_FLAGS tools/test.js $SCRIPT_FLAGS" 21 | branches: 22 | only: 23 | - master 24 | cache: 25 | directories: 26 | - "$HOME/.npm" 27 | -------------------------------------------------------------------------------- /API.md: -------------------------------------------------------------------------------- 1 | [http://bluebirdjs.com/docs/api-reference.html](http://bluebirdjs.com/docs/api-reference.html) 2 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | 2 | # Questions and issues 3 | 4 | Please see [The Support Page](http://bluebirdjs.com/docs/support.html) 5 | The [github issue tracker](https://github.com/petkaantonov/bluebird/issues) is **_only_** for bug reports and feature requests. 6 | 7 | # Contributing to the library 8 | 9 | Contributions are welcome and appreciated. See the [Contribution Page](http://bluebirdjs.com/docs/contribute.html) on bluebirdjs.com 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013-2018 Petka Antonov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /bench: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ./build --release --no-debug 3 | benchmark=$1 4 | nodepath=${2:-node} 5 | shift 2; 6 | cwd=${PWD} 7 | 8 | export NODE_ENV=production 9 | 10 | trap 'cd "$cwd"' EXIT 11 | 12 | if [ "$benchmark" = "doxbee" ]; then 13 | cd "$cwd/benchmark" 14 | npm install 15 | echo "Doxbee sequential" 16 | $nodepath performance.js --n 10000 --t 1 ./doxbee-sequential/*.js --harmony "$@" 17 | exit 0 18 | elif [ "$benchmark" = "doxbee-errors" ]; then 19 | cd "$cwd/benchmark" 20 | npm install 21 | echo "Doxbee sequential with 10% errors" 22 | $nodepath performance.js --n 10000 --t 1 --e 0.1 ./doxbee-sequential-errors/*.js --harmony "$@" 23 | exit 0 24 | elif [ "$benchmark" = "parallel" ]; then 25 | cd "$cwd/benchmark" 26 | npm install 27 | echo "Madeup parallel" 28 | $nodepath performance.js --n 10000 --t 1 --p 25 ./madeup-parallel/*.js --harmony "$@" 29 | exit 0 30 | elif [ "$benchmark" = "analysis" ]; then 31 | cd "$cwd/benchmark" 32 | npm install 33 | echo "analysis" 34 | $nodepath performance.js --n 10000 --t 1 ./analysis/*.js --harmony "$@" 35 | exit 0 36 | else 37 | echo "Invalid benchmark name $benchmark" 38 | exit -1 39 | fi 40 | -------------------------------------------------------------------------------- /benchmark/analysis/promises-bluebird-parallel.js: -------------------------------------------------------------------------------- 1 | global.useBluebird = true; 2 | global.useQ = false; 3 | global.parallelQueries = 25; 4 | var Promise = require('../../js/release/bluebird.js'); 5 | require('../lib/fakesP'); 6 | 7 | module.exports = function upload(stream, idOrPath, tag, done) { 8 | var queries = new Array(global.parallelQueries); 9 | var tx = db.begin(); 10 | 11 | for( var i = 0, len = queries.length; i < len; ++i ) { 12 | queries[i] = FileVersion.insert({index: i}).execWithin(tx); 13 | } 14 | 15 | Promise.all(queries).then().then(function() { 16 | tx.commit(); 17 | done(); 18 | }, function(err) { 19 | tx.rollback(); 20 | done(err); 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /benchmark/analysis/promises-bluebird.js: -------------------------------------------------------------------------------- 1 | global.useBluebird = true; 2 | global.useQ = false; 3 | var bluebird = require('../../js/release/bluebird.js'); 4 | require('../lib/fakesP'); 5 | 6 | module.exports = function upload(stream, idOrPath, tag, done) { 7 | var blob = blobManager.create(account); 8 | var tx = db.begin(); 9 | var blobIdP = blob.put(stream); 10 | var fileP = self.byUuidOrPath(idOrPath).get(); 11 | var version, fileId, file; 12 | 13 | bluebird.join(blobIdP, fileP, function(blobId, fileV) { 14 | file = fileV; 15 | var previousId = file ? file.version : null; 16 | version = { 17 | userAccountId: userAccount.id, 18 | date: new Date(), 19 | blobId: blobId, 20 | creatorId: userAccount.id, 21 | previousId: previousId, 22 | }; 23 | version.id = Version.createHash(version); 24 | return Version.insert(version).execWithin(tx); 25 | }).then(function() { 26 | if (!file) { 27 | var splitPath = idOrPath.split('/'); 28 | var fileName = splitPath[splitPath.length - 1]; 29 | var newId = uuid.v1(); 30 | return self.createQuery(idOrPath, { 31 | id: newId, 32 | userAccountId: userAccount.id, 33 | name: fileName, 34 | version: version.id 35 | }).then(function(q) { 36 | return q.execWithin(tx); 37 | }).then(function() { 38 | return newId; 39 | }); 40 | } else { 41 | return file.id; 42 | } 43 | }).then(function(fileIdV) { 44 | fileId = fileIdV; 45 | return FileVersion.insert({ 46 | fileId: fileId, 47 | versionId: version.id 48 | }).execWithin(tx); 49 | }).then(function() { 50 | return File.whereUpdate({id: fileId}, {version: version.id}) 51 | .execWithin(tx); 52 | }).then(function() { 53 | tx.commit(); 54 | return done(); 55 | }, function(err) { 56 | tx.rollback(); 57 | return done(err); 58 | }); 59 | } 60 | -------------------------------------------------------------------------------- /benchmark/doxbee-sequential-errors/promises-bluebird-generator.js: -------------------------------------------------------------------------------- 1 | global.useBluebird = true; 2 | global.useQ = false; 3 | var bluebird = require('../../js/release/bluebird.js'); 4 | require('../lib/fakesP'); 5 | 6 | module.exports = bluebird.coroutine(function* upload(stream, idOrPath, tag, done) { 7 | try { 8 | var blob = blobManager.create(account); 9 | var tx = db.begin(); 10 | var blobId = yield blob.put(stream); 11 | var file = yield self.byUuidOrPath(idOrPath).get(); 12 | 13 | var previousId = file ? file.version : null; 14 | version = { 15 | userAccountId: userAccount.id, 16 | date: new Date(), 17 | blobId: blobId, 18 | creatorId: userAccount.id, 19 | previousId: previousId, 20 | }; 21 | version.id = Version.createHash(version); 22 | yield Version.insert(version).execWithin(tx); 23 | triggerIntentionalError(); 24 | if (!file) { 25 | var splitPath = idOrPath.split('/'); 26 | var fileName = splitPath[splitPath.length - 1]; 27 | file = { 28 | id: uuid.v1(), 29 | userAccountId: userAccount.id, 30 | name: fileName, 31 | version: version.id 32 | } 33 | var query = yield self.createQuery(idOrPath, file); 34 | yield query.execWithin(tx); 35 | triggerIntentionalError(); 36 | } 37 | yield FileVersion.insert({fileId: file.id, versionId: version.id}) 38 | .execWithin(tx); 39 | triggerIntentionalError(); 40 | yield File.whereUpdate({id: file.id}, {version: version.id}) 41 | .execWithin(tx); 42 | triggerIntentionalError(); 43 | tx.commit(); 44 | done(); 45 | } catch (err) { 46 | tx.rollback(); 47 | done(err); 48 | } 49 | }); 50 | -------------------------------------------------------------------------------- /benchmark/doxbee-sequential-errors/promises-kriskowal-q.js: -------------------------------------------------------------------------------- 1 | global.useQ = true; 2 | 3 | var q = require('q'); 4 | 5 | require('../lib/fakesP'); 6 | 7 | module.exports = function upload(stream, idOrPath, tag, done) { 8 | var blob = blobManager.create(account); 9 | var tx = db.begin(); 10 | var blobIdP = blob.put(stream); 11 | var fileP = self.byUuidOrPath(idOrPath).get(); 12 | var version, fileId, file; 13 | q.spread([blobIdP, fileP], function(blobId, fileV) { 14 | file = fileV; 15 | var previousId = file ? file.version : null; 16 | version = { 17 | userAccountId: userAccount.id, 18 | date: new Date(), 19 | blobId: blobId, 20 | creatorId: userAccount.id, 21 | previousId: previousId, 22 | }; 23 | version.id = Version.createHash(version); 24 | return Version.insert(version).execWithin(tx); 25 | }).then(function() { 26 | triggerIntentionalError(); 27 | if (!file) { 28 | var splitPath = idOrPath.split('/'); 29 | var fileName = splitPath[splitPath.length - 1]; 30 | var newId = uuid.v1(); 31 | return self.createQuery(idOrPath, { 32 | id: newId, 33 | userAccountId: userAccount.id, 34 | name: fileName, 35 | version: version.id 36 | }).then(function(q) { 37 | return q.execWithin(tx); 38 | }).then(function() { 39 | return newId; 40 | }); 41 | } else { 42 | return file.id; 43 | } 44 | }).then(function(fileIdV) { 45 | triggerIntentionalError(); 46 | fileId = fileIdV; 47 | return FileVersion.insert({ 48 | fileId: fileId, 49 | versionId: version.id 50 | }).execWithin(tx); 51 | }).then(function() { 52 | triggerIntentionalError(); 53 | return File.whereUpdate({id: fileId}, {version: version.id}) 54 | .execWithin(tx); 55 | }).then(function() { 56 | triggerIntentionalError(); 57 | tx.commit(); 58 | return done(); 59 | }).then(null, function(err) { 60 | tx.rollback(); 61 | return done(err); 62 | }); 63 | } 64 | -------------------------------------------------------------------------------- /benchmark/doxbee-sequential-errors/promises-lvivski-davy.js: -------------------------------------------------------------------------------- 1 | global.useDavy = true; 2 | var davy = require('davy'); 3 | require('../lib/fakesP'); 4 | 5 | module.exports = function upload(stream, idOrPath, tag, done) { 6 | var blob = blobManager.create(account); 7 | var tx = db.begin(); 8 | var blobIdP = blob.put(stream); 9 | var fileP = self.byUuidOrPath(idOrPath).get(); 10 | var version, fileId, file; 11 | 12 | davy.all([blobIdP, fileP]).spread(function(blobId, fileV) { 13 | file = fileV; 14 | var previousId = file ? file.version : null; 15 | version = { 16 | userAccountId: userAccount.id, 17 | date: new Date(), 18 | blobId: blobId, 19 | creatorId: userAccount.id, 20 | previousId: previousId, 21 | }; 22 | version.id = Version.createHash(version); 23 | return Version.insert(version).execWithin(tx); 24 | }).then(function() { 25 | triggerIntentionalError(); 26 | if (!file) { 27 | var splitPath = idOrPath.split('/'); 28 | var fileName = splitPath[splitPath.length - 1]; 29 | var newId = uuid.v1(); 30 | return self.createQuery(idOrPath, { 31 | id: newId, 32 | userAccountId: userAccount.id, 33 | name: fileName, 34 | version: version.id 35 | }).then(function(q) { 36 | return q.execWithin(tx); 37 | }).then(function() { 38 | return newId; 39 | }); 40 | } else { 41 | return file.id; 42 | } 43 | }).then(function(fileIdV) { 44 | triggerIntentionalError(); 45 | fileId = fileIdV; 46 | return FileVersion.insert({ 47 | fileId: fileId, 48 | versionId: version.id 49 | }).execWithin(tx); 50 | }).then(function() { 51 | triggerIntentionalError(); 52 | return File.whereUpdate({id: fileId}, {version: version.id}) 53 | .execWithin(tx); 54 | }).then(function() { 55 | triggerIntentionalError(); 56 | tx.commit(); 57 | return done(); 58 | }).then(null, function(err) { 59 | tx.rollback(); 60 | return done(err); 61 | }); 62 | } 63 | -------------------------------------------------------------------------------- /benchmark/doxbee-sequential-errors/streamline._js: -------------------------------------------------------------------------------- 1 | require('../lib/fakes'); 2 | 3 | module.exports = function upload(stream, idOrPath, tag, _) { 4 | try { 5 | var blob = blobManager.create(account); 6 | var tx = db.begin(); 7 | var blobId = blob.put(stream, _); 8 | var file = self.byUuidOrPath(idOrPath).get(_); 9 | 10 | var previousId = file ? file.version : null; 11 | var version = { 12 | userAccountId: userAccount.id, 13 | date: new Date(), 14 | blobId: blobId, 15 | creatorId: userAccount.id, 16 | previousId: previousId, 17 | }; 18 | version.id = Version.createHash(version); 19 | Version.insert(version).execWithin(tx, _); 20 | triggerIntentionalError(); 21 | if (!file) { 22 | var splitPath = idOrPath.split('/'); 23 | var fileName = splitPath[splitPath.length - 1]; 24 | file = { 25 | id: uuid.v1(), 26 | userAccountId: userAccount.id, 27 | name: fileName, 28 | version: version.id 29 | } 30 | var query = self.createQuery(idOrPath, file, _); 31 | query.execWithin(tx, _); 32 | triggerIntentionalError(); 33 | } 34 | FileVersion.insert({fileId: file.id, versionId: version.id}) 35 | .execWithin(tx, _); 36 | triggerIntentionalError(); 37 | File.whereUpdate({id: file.id}, {version: version.id}) 38 | .execWithin(tx, _); 39 | triggerIntentionalError(); 40 | tx.commit(); 41 | } catch (err) { 42 | tx.rollback(); 43 | throw err; 44 | } 45 | }; -------------------------------------------------------------------------------- /benchmark/doxbee-sequential/generators-tj-co.js: -------------------------------------------------------------------------------- 1 | global.useNative = true; 2 | 3 | try { 4 | if (Promise.race.toString() !== 'function race() { [native code] }') 5 | throw 0; 6 | } catch (e) { 7 | throw new Error("No ES6 promises available"); 8 | } 9 | var co = require("co"); 10 | require('../lib/fakesP'); 11 | 12 | module.exports = function upload(stream, idOrPath, tag, done) { 13 | co(function* () { 14 | try { 15 | var blob = blobManager.create(account); 16 | var tx = db.begin(); 17 | var blobId = yield blob.put(stream); 18 | var file = yield self.byUuidOrPath(idOrPath).get(); 19 | 20 | var previousId = file ? file.version : null; 21 | version = { 22 | userAccountId: userAccount.id, 23 | date: new Date(), 24 | blobId: blobId, 25 | creatorId: userAccount.id, 26 | previousId: previousId, 27 | }; 28 | version.id = Version.createHash(version); 29 | yield Version.insert(version).execWithin(tx); 30 | if (!file) { 31 | var splitPath = idOrPath.split('/'); 32 | var fileName = splitPath[splitPath.length - 1]; 33 | file = { 34 | id: uuid.v1(), 35 | userAccountId: userAccount.id, 36 | name: fileName, 37 | version: version.id 38 | } 39 | var query = yield self.createQuery(idOrPath, file); 40 | yield query.execWithin(tx); 41 | } 42 | yield FileVersion.insert({fileId: file.id, versionId: version.id}) 43 | .execWithin(tx); 44 | yield File.whereUpdate({id: file.id}, {version: version.id}) 45 | .execWithin(tx); 46 | tx.commit(); 47 | done(); 48 | } catch (err) { 49 | tx.rollback(); 50 | done(err); 51 | } 52 | }); 53 | }; 54 | -------------------------------------------------------------------------------- /benchmark/doxbee-sequential/observables-Reactive-Extensions-RxJS.js: -------------------------------------------------------------------------------- 1 | global.useRx = true; 2 | var Rx = require('rx'); 3 | require('../lib/fakesObservable'); 4 | 5 | module.exports = function upload(stream, idOrPath, tag, done) { 6 | var blob = blobManager.create(account); 7 | var tx = db.begin(); 8 | var blobIdP = blob.put(stream); 9 | var fileP = self.byUuidOrPath(idOrPath).get(); 10 | var version, fileId, file; 11 | 12 | 13 | Rx.Observable.forkJoin(blobIdP, fileP).flatMap(function(v) { 14 | file = v[1]; 15 | var blobId = v[0]; 16 | var previousId = file ? file.version : null; 17 | version = { 18 | userAccountId: userAccount.id, 19 | date: new Date(), 20 | blobId: blobId, 21 | creatorId: userAccount.id, 22 | previousId: previousId, 23 | }; 24 | version.id = Version.createHash(version); 25 | return Version.insert(version).execWithin(tx); 26 | }).flatMap(function() { 27 | if (!file) { 28 | var splitPath = idOrPath.split('/'); 29 | var fileName = splitPath[splitPath.length - 1]; 30 | var newId = uuid.v1(); 31 | return self.createQuery(idOrPath, { 32 | id: newId, 33 | userAccountId: userAccount.id, 34 | name: fileName, 35 | version: version.id 36 | }).flatMap(function(q) { 37 | return q.execWithin(tx); 38 | }).map(function() { 39 | return newId; 40 | }); 41 | } else { 42 | return Rx.Observable.return(file.id); 43 | } 44 | }).flatMap(function(fileIdV) { 45 | fileId = fileIdV; 46 | return FileVersion.insert({ 47 | fileId: fileId, 48 | versionId: version.id 49 | }).execWithin(tx); 50 | }).flatMap(function() { 51 | return File.whereUpdate({id: fileId}, {version: version.id}) 52 | .execWithin(tx); 53 | }).subscribe(function() { 54 | 55 | }, function() { 56 | tx.rollback(); 57 | done(err); 58 | }, function() { 59 | tx.commit(); 60 | done(); 61 | }); 62 | } 63 | -------------------------------------------------------------------------------- /benchmark/doxbee-sequential/observables-baconjs-bacon.js.js: -------------------------------------------------------------------------------- 1 | global.useBacon = true; 2 | var Bacon = require('baconjs').Bacon; 3 | require('../lib/fakesObservable'); 4 | 5 | module.exports = function upload(stream, idOrPath, tag, done) { 6 | var blob = blobManager.create(account); 7 | var tx = db.begin(); 8 | var blobIdP = blob.put(stream); 9 | var fileP = self.byUuidOrPath(idOrPath).get(); 10 | var version, fileId, file; 11 | 12 | 13 | var stream = Bacon.combineAsArray(blobIdP, fileP).flatMap(function(v) { 14 | file = v[1]; 15 | var blobId = v[0]; 16 | var previousId = file ? file.version : null; 17 | version = { 18 | userAccountId: userAccount.id, 19 | date: new Date(), 20 | blobId: blobId, 21 | creatorId: userAccount.id, 22 | previousId: previousId, 23 | }; 24 | version.id = Version.createHash(version); 25 | return Version.insert(version).execWithin(tx); 26 | }).flatMap(function() { 27 | if (!file) { 28 | var splitPath = idOrPath.split('/'); 29 | var fileName = splitPath[splitPath.length - 1]; 30 | var newId = uuid.v1(); 31 | return self.createQuery(idOrPath, { 32 | id: newId, 33 | userAccountId: userAccount.id, 34 | name: fileName, 35 | version: version.id 36 | }).flatMap(function(q) { 37 | return q.execWithin(tx); 38 | }).map(function() { 39 | return newId; 40 | }); 41 | } else { 42 | return Bacon.constant(file.id); 43 | } 44 | }).flatMap(function(fileIdV) { 45 | fileId = fileIdV; 46 | return FileVersion.insert({ 47 | fileId: fileId, 48 | versionId: version.id 49 | }).execWithin(tx); 50 | }).flatMap(function() { 51 | return File.whereUpdate({id: fileId}, {version: version.id}) 52 | .execWithin(tx); 53 | }); 54 | stream.onError(function() { 55 | tx.rollback(); 56 | done(err); 57 | }); 58 | stream.onValue(function() { 59 | tx.commit(); 60 | done(); 61 | }); 62 | } 63 | -------------------------------------------------------------------------------- /benchmark/doxbee-sequential/observables-caolan-highland.js: -------------------------------------------------------------------------------- 1 | global.useHighland = true; 2 | var _ = require("highland"); 3 | require('../lib/fakesObservable'); 4 | 5 | module.exports = function upload(stream, idOrPath, tag, done) { 6 | var blob = blobManager.create(account); 7 | var tx = db.begin(); 8 | var blobIdP = blob.put(stream); 9 | var fileP = self.byUuidOrPath(idOrPath).get(); 10 | var version, fileId, file; 11 | 12 | _([blobIdP, fileP]).merge().apply(function(blobId, file) { 13 | var previousId = file ? file.version : null; 14 | version = { 15 | userAccountId: userAccount.id, 16 | date: new Date(), 17 | blobId: blobId, 18 | creatorId: userAccount.id, 19 | previousId: previousId, 20 | }; 21 | version.id = Version.createHash(version); 22 | Version.insert(version).execWithin(tx).flatMap(function() { 23 | if (!file) { 24 | var splitPath = idOrPath.split('/'); 25 | var fileName = splitPath[splitPath.length - 1]; 26 | var newId = uuid.v1(); 27 | return self.createQuery(idOrPath, { 28 | id: newId, 29 | userAccountId: userAccount.id, 30 | name: fileName, 31 | version: version.id 32 | }).flatMap(function(q) { 33 | return q.execWithin(tx); 34 | }).map(function() { 35 | return newId; 36 | }); 37 | } else { 38 | return _([file.id]); 39 | } 40 | }).flatMap(function(fileIdV) { 41 | fileId = fileIdV; 42 | return FileVersion.insert({ 43 | fileId: fileId, 44 | versionId: version.id 45 | }).execWithin(tx); 46 | }).flatMap(function() { 47 | return File.whereUpdate({id: fileId}, {version: version.id}) 48 | .execWithin(tx); 49 | }).stopOnError(function(err) { 50 | tx.rollback(); 51 | done(err); 52 | }).apply(function(v) { 53 | tx.commit(); 54 | done(); 55 | }); 56 | }); 57 | } 58 | -------------------------------------------------------------------------------- /benchmark/doxbee-sequential/observables-pozadi-kefir.js: -------------------------------------------------------------------------------- 1 | global.useKefir = true; 2 | var Kefir = require('kefir').Kefir; 3 | require('../lib/fakesObservable'); 4 | 5 | module.exports = function upload(stream, idOrPath, tag, done) { 6 | var blob = blobManager.create(account); 7 | var tx = db.begin(); 8 | var blobIdP = blob.put(stream); 9 | var fileP = self.byUuidOrPath(idOrPath).get(); 10 | var version, fileId, file; 11 | 12 | 13 | var stream = Kefir.zip([blobIdP, fileP]).flatMap(function(v) { 14 | file = v[1]; 15 | var blobId = v[0]; 16 | var previousId = file ? file.version : null; 17 | version = { 18 | userAccountId: userAccount.id, 19 | date: new Date(), 20 | blobId: blobId, 21 | creatorId: userAccount.id, 22 | previousId: previousId, 23 | }; 24 | version.id = Version.createHash(version); 25 | return Version.insert(version).execWithin(tx); 26 | }).flatMap(function() { 27 | if (!file) { 28 | var splitPath = idOrPath.split('/'); 29 | var fileName = splitPath[splitPath.length - 1]; 30 | var newId = uuid.v1(); 31 | return self.createQuery(idOrPath, { 32 | id: newId, 33 | userAccountId: userAccount.id, 34 | name: fileName, 35 | version: version.id 36 | }).flatMap(function(q) { 37 | return q.execWithin(tx); 38 | }).map(function() { 39 | return newId; 40 | }); 41 | } else { 42 | return Kefir.constant(file.id); 43 | } 44 | }).flatMap(function(fileIdV) { 45 | fileId = fileIdV; 46 | return FileVersion.insert({ 47 | fileId: fileId, 48 | versionId: version.id 49 | }).execWithin(tx); 50 | }).flatMap(function() { 51 | return File.whereUpdate({id: fileId}, {version: version.id}) 52 | .execWithin(tx); 53 | }); 54 | stream.onError(function() { 55 | tx.rollback(); 56 | done(err); 57 | }); 58 | stream.onValue(function() { 59 | tx.commit(); 60 | done(); 61 | }); 62 | } 63 | -------------------------------------------------------------------------------- /benchmark/doxbee-sequential/promises-bluebird-generator.js: -------------------------------------------------------------------------------- 1 | global.useBluebird = true; 2 | global.useQ = false; 3 | var bluebird = require('../../js/release/bluebird.js'); 4 | require('../lib/fakesP'); 5 | 6 | module.exports = bluebird.coroutine(function* upload(stream, idOrPath, tag, done) { 7 | try { 8 | var blob = blobManager.create(account); 9 | var tx = db.begin(); 10 | var blobId = yield blob.put(stream); 11 | var file = yield self.byUuidOrPath(idOrPath).get(); 12 | 13 | var previousId = file ? file.version : null; 14 | version = { 15 | userAccountId: userAccount.id, 16 | date: new Date(), 17 | blobId: blobId, 18 | creatorId: userAccount.id, 19 | previousId: previousId, 20 | }; 21 | version.id = Version.createHash(version); 22 | yield Version.insert(version).execWithin(tx); 23 | if (!file) { 24 | var splitPath = idOrPath.split('/'); 25 | var fileName = splitPath[splitPath.length - 1]; 26 | file = { 27 | id: uuid.v1(), 28 | userAccountId: userAccount.id, 29 | name: fileName, 30 | version: version.id 31 | } 32 | var query = yield self.createQuery(idOrPath, file); 33 | yield query.execWithin(tx); 34 | } 35 | yield FileVersion.insert({fileId: file.id, versionId: version.id}) 36 | .execWithin(tx); 37 | yield File.whereUpdate({id: file.id}, {version: version.id}) 38 | .execWithin(tx); 39 | tx.commit(); 40 | done(); 41 | } catch (err) { 42 | tx.rollback(); 43 | done(err); 44 | } 45 | }); 46 | -------------------------------------------------------------------------------- /benchmark/doxbee-sequential/promises-bluebird.js: -------------------------------------------------------------------------------- 1 | global.useBluebird = true; 2 | global.useQ = false; 3 | var bluebird = require('../../js/release/bluebird.js'); 4 | require('../lib/fakesP'); 5 | 6 | module.exports = function upload(stream, idOrPath, tag, done) { 7 | var blob = blobManager.create(account); 8 | var tx = db.begin(); 9 | var blobIdP = blob.put(stream); 10 | var fileP = self.byUuidOrPath(idOrPath).get(); 11 | var version, fileId, file; 12 | 13 | bluebird.join(blobIdP, fileP, function(blobId, fileV) { 14 | file = fileV; 15 | var previousId = file ? file.version : null; 16 | version = { 17 | userAccountId: userAccount.id, 18 | date: new Date(), 19 | blobId: blobId, 20 | creatorId: userAccount.id, 21 | previousId: previousId, 22 | }; 23 | version.id = Version.createHash(version); 24 | return Version.insert(version).execWithin(tx); 25 | }).then(function() { 26 | if (!file) { 27 | var splitPath = idOrPath.split('/'); 28 | var fileName = splitPath[splitPath.length - 1]; 29 | var newId = uuid.v1(); 30 | return self.createQuery(idOrPath, { 31 | id: newId, 32 | userAccountId: userAccount.id, 33 | name: fileName, 34 | version: version.id 35 | }).then(function(q) { 36 | return q.execWithin(tx); 37 | }).then(function() { 38 | return newId; 39 | }); 40 | } else { 41 | return file.id; 42 | } 43 | }).then(function(fileIdV) { 44 | fileId = fileIdV; 45 | return FileVersion.insert({ 46 | fileId: fileId, 47 | versionId: version.id 48 | }).execWithin(tx); 49 | }).then(function() { 50 | return File.whereUpdate({id: fileId}, {version: version.id}) 51 | .execWithin(tx); 52 | }).then(function() { 53 | tx.commit(); 54 | return done(); 55 | }, function(err) { 56 | tx.rollback(); 57 | return done(err); 58 | }); 59 | } 60 | -------------------------------------------------------------------------------- /benchmark/doxbee-sequential/promises-calvinmetcalf-lie.js: -------------------------------------------------------------------------------- 1 | global.useLie = true; 2 | 3 | var promise = require("lie"); 4 | 5 | require('../lib/fakesP'); 6 | 7 | 8 | module.exports = function upload(stream, idOrPath, tag, done) { 9 | var blob = blobManager.create(account); 10 | var tx = db.begin(); 11 | var blobIdP = blob.put(stream); 12 | var fileP = self.byUuidOrPath(idOrPath).get(); 13 | var version, fileId, file; 14 | promise.all([blobIdP, fileP]).then(function(all) { 15 | var blobId = all[0], fileV = all[1]; 16 | file = fileV; 17 | var previousId = file ? file.version : null; 18 | version = { 19 | userAccountId: userAccount.id, 20 | date: new Date(), 21 | blobId: blobId, 22 | creatorId: userAccount.id, 23 | previousId: previousId, 24 | }; 25 | version.id = Version.createHash(version); 26 | return Version.insert(version).execWithin(tx); 27 | }).then(function() { 28 | if (!file) { 29 | var splitPath = idOrPath.split('/'); 30 | var fileName = splitPath[splitPath.length - 1]; 31 | var newId = uuid.v1(); 32 | return self.createQueryCtxless(idOrPath, { 33 | id: newId, 34 | userAccountId: userAccount.id, 35 | name: fileName, 36 | version: version.id 37 | }).then(function(q) { 38 | return q.execWithin(tx); 39 | }).then(function() { 40 | return newId; 41 | }); 42 | } else { 43 | return file.id; 44 | } 45 | }).then(function(fileIdV) { 46 | fileId = fileIdV; 47 | return FileVersion.insert({ 48 | fileId: fileId, 49 | versionId: version.id 50 | }).execWithin(tx); 51 | }).then(function() { 52 | return File.whereUpdate({id: fileId}, {version: version.id}) 53 | .execWithin(tx); 54 | }).then(function() { 55 | tx.commit(); 56 | return done(); 57 | }, function(err) { 58 | tx.rollback(); 59 | return done(err); 60 | }); 61 | } 62 | -------------------------------------------------------------------------------- /benchmark/doxbee-sequential/promises-cujojs-when.js: -------------------------------------------------------------------------------- 1 | var when = require('when'), 2 | fn = require('when/function'), 3 | p = require('../lib/promiseSupport.js'); 4 | 5 | require('../lib/fakesP'); 6 | 7 | module.exports = function upload(stream, idOrPath, tag, done) { 8 | var blob = blobManager.create(account); 9 | var tx = db.begin(); 10 | var blobIdP = blob.put(stream); 11 | var fileP = self.byUuidOrPath(idOrPath).get(); 12 | var version, fileId, file; 13 | when([blobIdP, fileP]).spread(function(blobId, fileV) { 14 | file = fileV; 15 | var previousId = file ? file.version : null; 16 | version = { 17 | userAccountId: userAccount.id, 18 | date: new Date(), 19 | blobId: blobId, 20 | creatorId: userAccount.id, 21 | previousId: previousId, 22 | }; 23 | version.id = Version.createHash(version); 24 | return Version.insert(version).execWithin(tx); 25 | }).then(function() { 26 | if (!file) { 27 | var splitPath = idOrPath.split('/'); 28 | var fileName = splitPath[splitPath.length - 1]; 29 | var newId = uuid.v1(); 30 | return self.createQuery(idOrPath, { 31 | id: newId, 32 | userAccountId: userAccount.id, 33 | name: fileName, 34 | version: version.id 35 | }).then(function(q) { 36 | return q.execWithin(tx); 37 | }).then(function() { 38 | return newId; 39 | }); 40 | } else { 41 | return file.id; 42 | } 43 | }).then(function(fileIdV) { 44 | fileId = fileIdV; 45 | return FileVersion.insert({ 46 | fileId: fileId, 47 | versionId: version.id 48 | }).execWithin(tx); 49 | }).then(function() { 50 | return File.whereUpdate({id: fileId}, {version: version.id}) 51 | .execWithin(tx); 52 | }).then(function() { 53 | tx.commit(); 54 | return done(); 55 | }, function(err) { 56 | tx.rollback(); 57 | return done(err); 58 | }); 59 | } 60 | -------------------------------------------------------------------------------- /benchmark/doxbee-sequential/promises-dfilatov-vow.js: -------------------------------------------------------------------------------- 1 | var vow = require('vow'), 2 | p = require('../lib/promiseSupport.js'); 3 | 4 | require('../lib/fakesP'); 5 | 6 | module.exports = function upload(stream, idOrPath, tag, done) { 7 | var blob = blobManager.create(account); 8 | var tx = db.begin(); 9 | var blobIdP = blob.put(stream); 10 | var fileP = self.byUuidOrPath(idOrPath).get(); 11 | var version, fileId, file; 12 | 13 | vow.all([blobIdP, fileP]).spread(function(blobId, fileV) { 14 | file = fileV; 15 | var previousId = file ? file.version : null; 16 | version = { 17 | userAccountId: userAccount.id, 18 | date: new Date(), 19 | blobId: blobId, 20 | creatorId: userAccount.id, 21 | previousId: previousId, 22 | }; 23 | version.id = Version.createHash(version); 24 | return Version.insert(version).execWithin(tx); 25 | }).then(function() { 26 | if (!file) { 27 | var splitPath = idOrPath.split('/'); 28 | var fileName = splitPath[splitPath.length - 1]; 29 | var newId = uuid.v1(); 30 | return self.createQuery(idOrPath, { 31 | id: newId, 32 | userAccountId: userAccount.id, 33 | name: fileName, 34 | version: version.id 35 | }).then(function(q) { 36 | return q.execWithin(tx); 37 | }).then(function() { 38 | return newId; 39 | }); 40 | } else { 41 | return file.id; 42 | } 43 | }).then(function(fileIdV) { 44 | fileId = fileIdV; 45 | return FileVersion.insert({ 46 | fileId: fileId, 47 | versionId: version.id 48 | }).execWithin(tx); 49 | }).then(function() { 50 | return File.whereUpdate({id: fileId}, {version: version.id}) 51 | .execWithin(tx); 52 | }).then(function() { 53 | tx.commit(); 54 | return done(); 55 | }, function(err) { 56 | tx.rollback(); 57 | return done(err); 58 | }); 59 | } 60 | -------------------------------------------------------------------------------- /benchmark/doxbee-sequential/promises-kriskowal-q.js: -------------------------------------------------------------------------------- 1 | global.useQ = true; 2 | 3 | var q = require('q'); 4 | 5 | require('../lib/fakesP'); 6 | 7 | module.exports = function upload(stream, idOrPath, tag, done) { 8 | var blob = blobManager.create(account); 9 | var tx = db.begin(); 10 | var blobIdP = blob.put(stream); 11 | var fileP = self.byUuidOrPath(idOrPath).get(); 12 | var version, fileId, file; 13 | q.spread([blobIdP, fileP], function(blobId, fileV) { 14 | file = fileV; 15 | var previousId = file ? file.version : null; 16 | version = { 17 | userAccountId: userAccount.id, 18 | date: new Date(), 19 | blobId: blobId, 20 | creatorId: userAccount.id, 21 | previousId: previousId, 22 | }; 23 | version.id = Version.createHash(version); 24 | return Version.insert(version).execWithin(tx); 25 | }).then(function() { 26 | if (!file) { 27 | var splitPath = idOrPath.split('/'); 28 | var fileName = splitPath[splitPath.length - 1]; 29 | var newId = uuid.v1(); 30 | return self.createQuery(idOrPath, { 31 | id: newId, 32 | userAccountId: userAccount.id, 33 | name: fileName, 34 | version: version.id 35 | }).then(function(q) { 36 | return q.execWithin(tx); 37 | }).then(function() { 38 | return newId; 39 | }); 40 | } else { 41 | return file.id; 42 | } 43 | }).then(function(fileIdV) { 44 | fileId = fileIdV; 45 | return FileVersion.insert({ 46 | fileId: fileId, 47 | versionId: version.id 48 | }).execWithin(tx); 49 | }).then(function() { 50 | return File.whereUpdate({id: fileId}, {version: version.id}) 51 | .execWithin(tx); 52 | }).then(function() { 53 | tx.commit(); 54 | return done(); 55 | }, function(err) { 56 | tx.rollback(); 57 | return done(err); 58 | }); 59 | } 60 | -------------------------------------------------------------------------------- /benchmark/doxbee-sequential/promises-lvivski-davy.js: -------------------------------------------------------------------------------- 1 | global.useDavy = true; 2 | var davy = require('davy'); 3 | require('../lib/fakesP'); 4 | 5 | module.exports = function upload(stream, idOrPath, tag, done) { 6 | var blob = blobManager.create(account); 7 | var tx = db.begin(); 8 | var blobIdP = blob.put(stream); 9 | var fileP = self.byUuidOrPath(idOrPath).get(); 10 | var version, fileId, file; 11 | 12 | davy.all([blobIdP, fileP]).spread(function(blobId, fileV) { 13 | file = fileV; 14 | var previousId = file ? file.version : null; 15 | version = { 16 | userAccountId: userAccount.id, 17 | date: new Date(), 18 | blobId: blobId, 19 | creatorId: userAccount.id, 20 | previousId: previousId, 21 | }; 22 | version.id = Version.createHash(version); 23 | return Version.insert(version).execWithin(tx); 24 | }).then(function() { 25 | if (!file) { 26 | var splitPath = idOrPath.split('/'); 27 | var fileName = splitPath[splitPath.length - 1]; 28 | var newId = uuid.v1(); 29 | return self.createQuery(idOrPath, { 30 | id: newId, 31 | userAccountId: userAccount.id, 32 | name: fileName, 33 | version: version.id 34 | }).then(function(q) { 35 | return q.execWithin(tx); 36 | }).then(function() { 37 | return newId; 38 | }); 39 | } else { 40 | return file.id; 41 | } 42 | }).then(function(fileIdV) { 43 | fileId = fileIdV; 44 | return FileVersion.insert({ 45 | fileId: fileId, 46 | versionId: version.id 47 | }).execWithin(tx); 48 | }).then(function() { 49 | return File.whereUpdate({id: fileId}, {version: version.id}) 50 | .execWithin(tx); 51 | }).then(function() { 52 | tx.commit(); 53 | return done(); 54 | }, function(err) { 55 | tx.rollback(); 56 | return done(err); 57 | }); 58 | } 59 | -------------------------------------------------------------------------------- /benchmark/doxbee-sequential/promises-medikoo-deferred.js: -------------------------------------------------------------------------------- 1 | global.useDeferred = true; 2 | 3 | var deferred = require('deferred'); 4 | 5 | require('../lib/fakesP'); 6 | 7 | function identity(v) { 8 | return v; 9 | } 10 | 11 | module.exports = function upload(stream, idOrPath, tag, done) { 12 | var blob = blobManager.create(account); 13 | var tx = db.begin(); 14 | var blobIdP = blob.put(stream); 15 | var fileP = self.byUuidOrPath(idOrPath).get(); 16 | var version, fileId, file; 17 | //Couldn't find .all in docs, this seems closest 18 | deferred.map([blobIdP, fileP], identity)(function(all) { 19 | var blobId = all[0], fileV = all[1]; 20 | file = fileV; 21 | var previousId = file ? file.version : null; 22 | version = { 23 | userAccountId: userAccount.id, 24 | date: new Date(), 25 | blobId: blobId, 26 | creatorId: userAccount.id, 27 | previousId: previousId, 28 | }; 29 | version.id = Version.createHash(version); 30 | return Version.insert(version).execWithin(tx); 31 | })(function() { 32 | if (!file) { 33 | var splitPath = idOrPath.split('/'); 34 | var fileName = splitPath[splitPath.length - 1]; 35 | var newId = uuid.v1(); 36 | return self.createQueryCtxless(idOrPath, { 37 | id: newId, 38 | userAccountId: userAccount.id, 39 | name: fileName, 40 | version: version.id 41 | })(function(q) { 42 | return q.execWithin(tx); 43 | })(function() { 44 | return newId; 45 | }); 46 | } else { 47 | return file.id; 48 | } 49 | })(function(fileIdV) { 50 | fileId = fileIdV; 51 | return FileVersion.insert({ 52 | fileId: fileId, 53 | versionId: version.id 54 | }).execWithin(tx); 55 | })(function() { 56 | return File.whereUpdate({id: fileId}, {version: version.id}) 57 | .execWithin(tx); 58 | })(function() { 59 | tx.commit(); 60 | return done(); 61 | }, function(err) { 62 | tx.rollback(); 63 | return done(err); 64 | }); 65 | } 66 | -------------------------------------------------------------------------------- /benchmark/doxbee-sequential/promises-native-async-await.js: -------------------------------------------------------------------------------- 1 | global.useNative = true; 2 | 3 | try { 4 | if (Promise.race.toString() !== 'function race() { [native code] }') 5 | throw 0; 6 | } catch (e) { 7 | throw new Error("No ES6 promises available"); 8 | } 9 | 10 | require('../lib/fakesP'); 11 | 12 | module.exports = async function upload(stream, idOrPath, tag, done) { 13 | try { 14 | var blob = blobManager.create(account); 15 | var tx = db.begin(); 16 | var blobId = await blob.put(stream); 17 | var file = await self.byUuidOrPath(idOrPath).get(); 18 | 19 | var previousId = file ? file.version : null; 20 | version = { 21 | userAccountId: userAccount.id, 22 | date: new Date(), 23 | blobId: blobId, 24 | creatorId: userAccount.id, 25 | previousId: previousId, 26 | }; 27 | version.id = Version.createHash(version); 28 | await Version.insert(version).execWithin(tx); 29 | if (!file) { 30 | var splitPath = idOrPath.split('/'); 31 | var fileName = splitPath[splitPath.length - 1]; 32 | file = { 33 | id: uuid.v1(), 34 | userAccountId: userAccount.id, 35 | name: fileName, 36 | version: version.id 37 | } 38 | var query = await self.createQuery(idOrPath, file); 39 | await query.execWithin(tx); 40 | } 41 | await FileVersion.insert({fileId: file.id, versionId: version.id}) 42 | .execWithin(tx); 43 | await File.whereUpdate({id: file.id}, {version: version.id}) 44 | .execWithin(tx); 45 | tx.commit(); 46 | done(); 47 | } catch (err) { 48 | tx.rollback(); 49 | done(err); 50 | } 51 | }; 52 | -------------------------------------------------------------------------------- /benchmark/doxbee-sequential/promises-obvious-kew.js: -------------------------------------------------------------------------------- 1 | global.useKew = true; 2 | 3 | var q = require('kew'); 4 | 5 | require('../lib/fakesP'); 6 | 7 | module.exports = function upload(stream, idOrPath, tag, done) { 8 | var blob = blobManager.create(account); 9 | var tx = db.begin(); 10 | var blobIdP = blob.put(stream); 11 | var fileP = self.byUuidOrPath(idOrPath).get(); 12 | var version, fileId, file; 13 | q.all([blobIdP, fileP]).then(function(all) { 14 | var blobId = all[0], fileV = all[1]; 15 | file = fileV; 16 | var previousId = file ? file.version : null; 17 | version = { 18 | userAccountId: userAccount.id, 19 | date: new Date(), 20 | blobId: blobId, 21 | creatorId: userAccount.id, 22 | previousId: previousId, 23 | }; 24 | version.id = Version.createHash(version); 25 | return Version.insert(version).execWithin(tx); 26 | }).then(function() { 27 | if (!file) { 28 | var splitPath = idOrPath.split('/'); 29 | var fileName = splitPath[splitPath.length - 1]; 30 | var newId = uuid.v1(); 31 | return self.createQueryCtxless(idOrPath, { 32 | id: newId, 33 | userAccountId: userAccount.id, 34 | name: fileName, 35 | version: version.id 36 | }).then(function(q) { 37 | return q.execWithin(tx); 38 | }).then(function() { 39 | return newId; 40 | }); 41 | } else { 42 | return file.id; 43 | } 44 | }).then(function(fileIdV) { 45 | fileId = fileIdV; 46 | return FileVersion.insert({ 47 | fileId: fileId, 48 | versionId: version.id 49 | }).execWithin(tx); 50 | }).then(function() { 51 | return File.whereUpdate({id: fileId}, {version: version.id}) 52 | .execWithin(tx); 53 | }).then(function() { 54 | tx.commit(); 55 | return done(); 56 | }, function(err) { 57 | tx.rollback(); 58 | return done(err); 59 | }); 60 | } 61 | -------------------------------------------------------------------------------- /benchmark/doxbee-sequential/promises-then-promise.js: -------------------------------------------------------------------------------- 1 | global.useThenPromise = true; 2 | 3 | var promise = require("promise"); 4 | 5 | require('../lib/fakesP'); 6 | 7 | 8 | module.exports = function upload(stream, idOrPath, tag, done) { 9 | var blob = blobManager.create(account); 10 | var tx = db.begin(); 11 | var blobIdP = blob.put(stream); 12 | var fileP = self.byUuidOrPath(idOrPath).get(); 13 | var version, fileId, file; 14 | promise.all([blobIdP, fileP]).then(function(all) { 15 | var blobId = all[0], fileV = all[1]; 16 | file = fileV; 17 | var previousId = file ? file.version : null; 18 | version = { 19 | userAccountId: userAccount.id, 20 | date: new Date(), 21 | blobId: blobId, 22 | creatorId: userAccount.id, 23 | previousId: previousId, 24 | }; 25 | version.id = Version.createHash(version); 26 | return Version.insert(version).execWithin(tx); 27 | }).then(function() { 28 | if (!file) { 29 | var splitPath = idOrPath.split('/'); 30 | var fileName = splitPath[splitPath.length - 1]; 31 | var newId = uuid.v1(); 32 | return self.createQueryCtxless(idOrPath, { 33 | id: newId, 34 | userAccountId: userAccount.id, 35 | name: fileName, 36 | version: version.id 37 | }).then(function(q) { 38 | return q.execWithin(tx); 39 | }).then(function() { 40 | return newId; 41 | }); 42 | } else { 43 | return file.id; 44 | } 45 | }).then(function(fileIdV) { 46 | fileId = fileIdV; 47 | return FileVersion.insert({ 48 | fileId: fileId, 49 | versionId: version.id 50 | }).execWithin(tx); 51 | }).then(function() { 52 | return File.whereUpdate({id: fileId}, {version: version.id}) 53 | .execWithin(tx); 54 | }).then(function() { 55 | tx.commit(); 56 | return done(); 57 | }, function(err) { 58 | tx.rollback(); 59 | return done(err); 60 | }); 61 | } 62 | -------------------------------------------------------------------------------- /benchmark/doxbee-sequential/promises-tildeio-rsvp.js: -------------------------------------------------------------------------------- 1 | global.useRSVP = true; 2 | 3 | var rsvp = require('rsvp'); 4 | 5 | require('../lib/fakesP'); 6 | 7 | module.exports = function upload(stream, idOrPath, tag, done) { 8 | var blob = blobManager.create(account); 9 | var tx = db.begin(); 10 | var blobIdP = blob.put(stream); 11 | var fileP = self.byUuidOrPath(idOrPath).get(); 12 | var version, fileId, file; 13 | rsvp.all([blobIdP, fileP]).then(function(all) { 14 | var blobId = all[0], fileV = all[1]; 15 | file = fileV; 16 | var previousId = file ? file.version : null; 17 | version = { 18 | userAccountId: userAccount.id, 19 | date: new Date(), 20 | blobId: blobId, 21 | creatorId: userAccount.id, 22 | previousId: previousId, 23 | }; 24 | version.id = Version.createHash(version); 25 | return Version.insert(version).execWithin(tx); 26 | }).then(function() { 27 | if (!file) { 28 | var splitPath = idOrPath.split('/'); 29 | var fileName = splitPath[splitPath.length - 1]; 30 | var newId = uuid.v1(); 31 | return self.createQueryCtxless(idOrPath, { 32 | id: newId, 33 | userAccountId: userAccount.id, 34 | name: fileName, 35 | version: version.id 36 | }).then(function(q) { 37 | return q.execWithin(tx); 38 | }).then(function() { 39 | return newId; 40 | }); 41 | } else { 42 | return file.id; 43 | } 44 | }).then(function(fileIdV) { 45 | fileId = fileIdV; 46 | return FileVersion.insert({ 47 | fileId: fileId, 48 | versionId: version.id 49 | }).execWithin(tx); 50 | }).then(function() { 51 | return File.whereUpdate({id: fileId}, {version: version.id}) 52 | .execWithin(tx); 53 | }).then(function() { 54 | tx.commit(); 55 | return done(); 56 | }, function(err) { 57 | tx.rollback(); 58 | return done(err); 59 | }); 60 | } 61 | -------------------------------------------------------------------------------- /benchmark/doxbee-sequential/streamline._js: -------------------------------------------------------------------------------- 1 | require('../lib/fakes'); 2 | 3 | module.exports = function upload(stream, idOrPath, tag, _) { 4 | try { 5 | var blob = blobManager.create(account); 6 | var tx = db.begin(); 7 | var blobId = blob.put(stream, _); 8 | var file = self.byUuidOrPath(idOrPath).get(_); 9 | 10 | var previousId = file ? file.version : null; 11 | var version = { 12 | userAccountId: userAccount.id, 13 | date: new Date(), 14 | blobId: blobId, 15 | creatorId: userAccount.id, 16 | previousId: previousId, 17 | }; 18 | version.id = Version.createHash(version); 19 | Version.insert(version).execWithin(tx, _); 20 | if (!file) { 21 | var splitPath = idOrPath.split('/'); 22 | var fileName = splitPath[splitPath.length - 1]; 23 | file = { 24 | id: uuid.v1(), 25 | userAccountId: userAccount.id, 26 | name: fileName, 27 | version: version.id 28 | } 29 | var query = self.createQuery(idOrPath, file, _); 30 | query.execWithin(tx, _); 31 | } 32 | FileVersion.insert({fileId: file.id, versionId: version.id}) 33 | .execWithin(tx, _); 34 | File.whereUpdate({id: file.id}, {version: version.id}) 35 | .execWithin(tx, _); 36 | tx.commit(); 37 | } catch (err) { 38 | tx.rollback(); 39 | throw err; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /benchmark/lib/catcher.js: -------------------------------------------------------------------------------- 1 | 2 | exports.longStackSupport = global.longStackSupport; 3 | 4 | 5 | function invoke(ctx, cb, value, myhandler) { 6 | try { 7 | cb.call(ctx, value); // no error 8 | } catch (e) { 9 | if (myhandler) 10 | myhandler.call(ctx, e); 11 | else 12 | console.error(e); 13 | } 14 | } 15 | 16 | module.exports = function() { 17 | var self = {}; 18 | var notCaught = true, myhandler; 19 | self.try = function $try(cb) { 20 | if (exports.longStackSupport) { 21 | var ex = {}; 22 | Error.captureStackTrace(ex); 23 | } 24 | return function wrapper(err, value) { 25 | if (err) { 26 | if (notCaught) { 27 | notCaught = false; 28 | if (err.stack && ex) { 29 | var asyncStackRaw = 30 | ex.stack.substr(ex.stack.indexOf('\n')); 31 | err.stack += '\nFrom previous event:' 32 | + asyncStackRaw; 33 | } 34 | if (myhandler) myhandler(err); 35 | else console.error(err); 36 | } 37 | } 38 | else if (myhandler) 39 | invoke(this, cb, value, myhandler); 40 | else cb(value); 41 | } 42 | } 43 | self.catch = function $catch(handler) { 44 | myhandler = handler 45 | }; 46 | return self; 47 | }; 48 | 49 | -------------------------------------------------------------------------------- /benchmark/lib/dummy.js: -------------------------------------------------------------------------------- 1 | // A typical node callback function 2 | // with the callback at the Nth position 3 | exports.dummy = function dummy(n) { 4 | return function dummy_n() { 5 | var cb = arguments[n - 1] || function(){}; 6 | if (global.asyncTime) 7 | setTimeout(cb, global.asyncTime || 100); 8 | else 9 | process.nextTick(cb); 10 | } 11 | } 12 | 13 | // A throwing callback function 14 | exports.dummyt = function dummyt(n) { 15 | return function dummy_throwing_n() { 16 | var cb = arguments[n - 1]; 17 | if (global.testThrow) 18 | throw(new Error("Exception happened")); 19 | setTimeout(function throwTimeout() { 20 | if (global.testThrowAsync) { 21 | throw(new Error("Exception happened")); 22 | } else if (global.testError) { 23 | return cb(new Error("Error happened")); 24 | } 25 | else cb(); 26 | }, global.asyncTime || 100); 27 | } 28 | } 29 | 30 | 31 | -------------------------------------------------------------------------------- /benchmark/lib/fakemaker.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = function fakemaker(dummy, dummyt, wrap) { 3 | 4 | var dummy_2 = dummy(2), 5 | dummy_1 = dummy(1); 6 | 7 | var dummyt_2, dummyt_1; 8 | 9 | if (global.testError || global.testThrow 10 | || global.testThrowAsync) { 11 | dummyt_2 = dummyt(2); 12 | dummyt_1 = dummyt(1); 13 | } else { 14 | dummyt_2 = dummy_2; 15 | dummyt_1 = dummy_1; 16 | } 17 | 18 | // a queryish object with all 19 | // kinds of functions 20 | function queryish() { 21 | return { 22 | execWithin: dummy_2, 23 | exec: dummy_1, 24 | get: dummy_1, 25 | all: dummy_1, 26 | }; 27 | } 28 | 29 | // a queryish object with functions 30 | // that throw 31 | function queryisht() { 32 | return { 33 | execWithin: dummyt_2, 34 | exec: dummyt_1, 35 | get: dummyt_1, 36 | all: dummyt_1, 37 | }; 38 | } 39 | 40 | global.uuid = { v1: function v1() {} }; 41 | 42 | global.userAccount = { }; 43 | 44 | global.account = { }; 45 | 46 | global.blobManager = { 47 | create: function create() { 48 | return { 49 | put: dummy_2, 50 | } 51 | } 52 | }; 53 | 54 | var cqQueryish = queryish(); 55 | 56 | global.self = { 57 | byUuidOrPath: queryish, 58 | createQuery: wrap(function createQuery(x, y, cb, ctx) { 59 | cb.call(ctx, null, cqQueryish); 60 | }), 61 | createQueryCtxless: wrap(function createQuery(x, y, cb) { 62 | cb.call(this, null, cqQueryish); 63 | }) 64 | }; 65 | 66 | 67 | global.File = { 68 | insert: queryish, 69 | whereUpdate: queryish 70 | }; 71 | 72 | global.FileVersion = { 73 | insert: queryisht 74 | }; 75 | 76 | global.Version = { 77 | createHash: function createHash(v) { return 1; }, 78 | insert: queryish 79 | }; 80 | 81 | global.db = { 82 | begin: function begin() { 83 | return { 84 | commit: dummy_1, 85 | rollback: dummy_1, 86 | }; 87 | } 88 | }; 89 | 90 | }; 91 | 92 | 93 | -------------------------------------------------------------------------------- /benchmark/lib/fakes-ctx.js: -------------------------------------------------------------------------------- 1 | var timers = require('./timers-ctx'); 2 | 3 | var fakemaker = require('./fakemaker'); 4 | 5 | var f = {}; 6 | f.dummy = function dummy(n) { 7 | return function dummy_n() { 8 | var cb = arguments[n - 1], 9 | ctx = arguments[n]; 10 | //console.log(cb, ctx); 11 | 12 | timers.setTimeout(cb, ctx, global.asyncTime || 100); 13 | } 14 | } 15 | 16 | // A throwing callback function 17 | f.dummyt = function dummyt(n) { 18 | return function dummy_throwing_n() { 19 | var cb = arguments[n - 1], 20 | ctx = arguments[n]; 21 | if (global.testThrow) 22 | throw(new Error("Exception happened")); 23 | setTimeout(function throwTimeout() { 24 | if (global.testThrowAsync) { 25 | throw(new Error("Exception happened")); 26 | } else if (global.testError) { 27 | return cb.call(ctx, new Error("Error happened")); 28 | } 29 | else cb.call(ctx); 30 | }, global.asyncTime || 100); 31 | } 32 | } 33 | 34 | 35 | 36 | 37 | fakemaker(f.dummy, f.dummyt, function wrap_identity(f) { return f; }); 38 | 39 | 40 | -------------------------------------------------------------------------------- /benchmark/lib/fakes.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | var fakemaker = require('./fakemaker'), 4 | f = require('./dummy'); 5 | 6 | fakemaker(f.dummy, f.dummyt, function wrap_identity(f) { return f; }); 7 | 8 | 9 | -------------------------------------------------------------------------------- /benchmark/lib/fakesC.js: -------------------------------------------------------------------------------- 1 | 2 | var co = require('co'); 3 | 4 | var f = require('./dummy'); 5 | 6 | var makefakes = require('./fakemaker'); 7 | 8 | // Continuable versions made with co.wrap 9 | function dummyC(n) { 10 | return co.wrap(f.dummy(n)); 11 | } 12 | function dummytC(n) { 13 | return co.wrap(f.dummyt(n)); 14 | } 15 | 16 | makefakes(dummyC, dummytC, co.wrap); 17 | 18 | 19 | -------------------------------------------------------------------------------- /benchmark/lib/fakesO.js: -------------------------------------------------------------------------------- 1 | 2 | var Rx = require('rx'); 3 | var f = require('./dummy'); 4 | 5 | var dummy1 = f.dummy(1), 6 | dummyt1 = f.dummyt(1); 7 | 8 | // Observable wrapper 9 | function dummyObsWrap(fn) { 10 | return function() { 11 | return Rx.Observable.create(function(observer) { 12 | fn(function(err, res) { 13 | if(err) 14 | return observer.onError(err); 15 | observer.onNext(res); 16 | observer.onCompleted(); 17 | }); 18 | }); 19 | } 20 | } 21 | function dummyO() { 22 | return dummyObsWrap(dummy(1)); 23 | } 24 | function dummytO() { 25 | return dummyObsWrap(dummyt(1)); 26 | } 27 | 28 | makefakes(dummyO, dummytO, dummyObsWrap); 29 | 30 | -------------------------------------------------------------------------------- /benchmark/lib/fakesObservable.js: -------------------------------------------------------------------------------- 1 | var lifter, fromNodeCallback; 2 | if (global.useRx) { 3 | lifter = require("rx").Observable.fromNodeCallback; 4 | } else if (global.useBacon) { 5 | fromNodeCallback = require("baconjs").fromNodeCallback; 6 | } else if (global.useKefir) { 7 | fromNodeCallback = require("kefir").Kefir.fromNodeCallback; 8 | lifter = function(nodeFn) { 9 | return function() { 10 | var args = [].slice.call(arguments); 11 | function thunk(callback) { 12 | args.push(callback); 13 | nodeFn.apply(null, args); 14 | args.pop(); 15 | } 16 | return fromNodeCallback(thunk); 17 | } 18 | }; 19 | } else if (global.useHighland) { 20 | lifter = require("highland").wrapCallback; 21 | } 22 | 23 | if (!lifter) { 24 | lifter = function(nodeFn) { 25 | return function() { 26 | var args = [].slice.call(arguments); 27 | args.unshift(nodeFn); 28 | return fromNodeCallback.apply(undefined, args); 29 | }; 30 | }; 31 | } 32 | 33 | var f = require('./dummy'); 34 | 35 | var makefakes = require('./fakemaker'); 36 | 37 | // A function taking n values or promises and returning 38 | // a promise 39 | function dummyP(n) { 40 | return lifter(f.dummy(n)); 41 | } 42 | 43 | // Throwing version of above 44 | function dummytP(n) { 45 | return lifter(f.dummyt(n)); 46 | } 47 | 48 | makefakes(dummyP, dummytP, lifter); 49 | -------------------------------------------------------------------------------- /benchmark/lib/fakesSJS-src.sjs: -------------------------------------------------------------------------------- 1 | var f = require('./dummy.js'); 2 | 3 | var makefakes = require('./fakemaker.js'); 4 | 5 | function wrap(f) { 6 | return function(x, y) { 7 | waitfor(var err, val) { 8 | f(x, y, resume); 9 | } 10 | if (err) throw err; 11 | return val; 12 | }; 13 | } 14 | 15 | function dummySJS0() { 16 | var inner = f.dummy(1); 17 | return function() { 18 | waitfor (var err, val) { 19 | inner(resume); 20 | } 21 | if (err) throw err; 22 | return val; 23 | } 24 | } 25 | 26 | function dummySJS1() { 27 | var inner = f.dummy(2); 28 | return function(x) { 29 | waitfor (var err, val) { 30 | inner(x, resume); 31 | } 32 | if (err) throw err; 33 | return val; 34 | } 35 | } 36 | 37 | function dummySJS(n) { 38 | if (n === 1) return dummySJS0(); 39 | if (n === 2) return dummySJS1(); 40 | } 41 | 42 | function dummytSJS(n) { 43 | var inner = f.dummyt(n); 44 | return function() { 45 | waitfor(var err, val) { 46 | var args = Array.prototype.slice.apply(arguments); 47 | args.push(resume); 48 | inner.apply(this, args); 49 | } 50 | 51 | if (err) throw err; 52 | return val; 53 | } 54 | } 55 | 56 | makefakes(dummySJS, dummytSJS, wrap, global); 57 | -------------------------------------------------------------------------------- /benchmark/lib/promiseSupport.js: -------------------------------------------------------------------------------- 1 | var when = require('when'); 2 | var fn = require('when/function'); 3 | 4 | 5 | 6 | exports.ternary = fn.lift(function(truthy, iftrue, iffalse) { 7 | return truthy ? iftrue: iffalse; 8 | }) 9 | 10 | exports.not = function not(truthyP) { 11 | return when(truthyP).then(function(truthyVal) { 12 | return !truthyVal; 13 | }); 14 | } 15 | 16 | exports.allObject = function allObject(objWithPromises) { 17 | return when(objWithPromises).then(function(objWithPromises) { 18 | var keys = Object.keys(objWithPromises); 19 | return when.all(keys.map(function(key) { 20 | return objWithPromise; 21 | })).then(function(vals) { 22 | var init = {}; 23 | for (var k = 0; k < keys.length; ++k) { 24 | init[keys[k]] = vals[k]; 25 | } 26 | return init; 27 | }); 28 | }); 29 | } 30 | 31 | exports.set = fn.lift(function(obj, values) { 32 | for (var key in values) 33 | obj[key] = values[key]; 34 | return obj; 35 | }); 36 | 37 | exports.if = function ifP (truthyP, fnTrue, fnFalse) { 38 | return truthyP.then(function(truthy) { 39 | if (truthy) return fnTrue(); 40 | else return fnFalse(); 41 | }); 42 | } 43 | 44 | exports.get = fn.lift(function (obj, key) { 45 | return obj[key]; 46 | }); 47 | 48 | exports.eventuallyCall = fn.lift(function(obj, fnkey) { 49 | var args = [].slice.call(arguments, 2); 50 | obj[fnkey].apply(obj, args); 51 | }); 52 | -------------------------------------------------------------------------------- /benchmark/madeup-parallel/callbacks-baseline.js: -------------------------------------------------------------------------------- 1 | require('../lib/fakes'); 2 | 3 | module.exports = function upload(stream, idOrPath, tag, done) { 4 | var tx = db.begin(); 5 | var current = 0; 6 | var total = global.parallelQueries; 7 | 8 | 9 | 10 | for( var i = 0; i < total; ++i ) { 11 | FileVersion.insert({index: i}).execWithin(tx, function onComplete(err) { 12 | if (onComplete.called) return; 13 | onComplete.called = true; 14 | if( err ) { 15 | tx.rollback(); 16 | done(err); 17 | } 18 | else { 19 | current++; 20 | if( current === total ) { 21 | tx.commit(); 22 | done(); 23 | } 24 | } 25 | }); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /benchmark/madeup-parallel/callbacks-caolan-async-parallel.js: -------------------------------------------------------------------------------- 1 | require('../lib/fakes'); 2 | var async = require('async'); 3 | 4 | function fileInsertFor(i, tx) { 5 | return function(callback) { 6 | FileVersion.insert({index: i}) 7 | .execWithin(tx, callback); 8 | }; 9 | } 10 | 11 | module.exports = function upload(stream, idOrPath, tag, done) { 12 | var queries = new Array(global.parallelQueries); 13 | var tx = db.begin(); 14 | 15 | for( var i = 0, len = queries.length; i < len; ++i ) { 16 | queries[i] = fileInsertFor(i, tx); 17 | } 18 | 19 | async.parallel(queries, function(err, callback) { 20 | if (err) { 21 | tx.rollback(); 22 | done(err); 23 | } 24 | else { 25 | tx.commit(); 26 | done(); 27 | } 28 | }); 29 | } 30 | -------------------------------------------------------------------------------- /benchmark/madeup-parallel/callbacks-suguru03-neo-async-parallel.js: -------------------------------------------------------------------------------- 1 | require('../lib/fakes'); 2 | var async = require('neo-async'); 3 | 4 | function fileInsertFor(i, tx) { 5 | return function(callback) { 6 | FileVersion.insert({index: i}) 7 | .execWithin(tx, callback); 8 | }; 9 | } 10 | 11 | module.exports = function upload(stream, idOrPath, tag, done) { 12 | var queries = new Array(global.parallelQueries); 13 | var tx = db.begin(); 14 | 15 | for( var i = 0, len = queries.length; i < len; ++i ) { 16 | queries[i] = fileInsertFor(i, tx); 17 | } 18 | 19 | async.parallel(queries, function(err, callback) { 20 | if (err) { 21 | tx.rollback(); 22 | done(err); 23 | } 24 | else { 25 | tx.commit(); 26 | done(); 27 | } 28 | }); 29 | } 30 | -------------------------------------------------------------------------------- /benchmark/madeup-parallel/generators-tj-co.js: -------------------------------------------------------------------------------- 1 | global.useNative = true; 2 | 3 | try { 4 | if (Promise.race.toString() !== 'function race() { [native code] }') 5 | throw 0; 6 | } catch (e) { 7 | throw new Error("No ES6 promises available"); 8 | } 9 | 10 | var co = require('co'); 11 | require('../lib/fakesP'); 12 | 13 | module.exports = function upload(stream, idOrPath, tag, done) { 14 | return co(function* () { 15 | var queries = new Array(global.parallelQueries); 16 | var tx = db.begin(); 17 | 18 | for( var i = 0, len = queries.length; i < len; ++i ) { 19 | queries[i] = FileVersion.insert({index: i}).execWithin(tx); 20 | } 21 | 22 | try { 23 | yield Promise.all(queries); 24 | tx.commit(); 25 | done(); 26 | } 27 | catch(e) { 28 | tx.rollback(); 29 | done(e); 30 | } 31 | }); 32 | }; 33 | -------------------------------------------------------------------------------- /benchmark/madeup-parallel/promises-bluebird-generator.js: -------------------------------------------------------------------------------- 1 | global.useBluebird = true; 2 | global.useQ = false; 3 | var bluebird = require('../../js/release/bluebird.js'); 4 | require('../lib/fakesP'); 5 | 6 | module.exports = bluebird.coroutine(function* upload(stream, idOrPath, tag, done) { 7 | var queries = new Array(global.parallelQueries); 8 | var tx = db.begin(); 9 | 10 | for( var i = 0, len = queries.length; i < len; ++i ) { 11 | queries[i] = FileVersion.insert({index: i}).execWithin(tx); 12 | } 13 | 14 | try { 15 | yield bluebird.all(queries); 16 | tx.commit(); 17 | done(); 18 | } 19 | catch(e) { 20 | tx.rollback(); 21 | done(e); 22 | } 23 | }); 24 | -------------------------------------------------------------------------------- /benchmark/madeup-parallel/promises-bluebird.js: -------------------------------------------------------------------------------- 1 | global.useBluebird = true; 2 | global.useQ = false; 3 | var Promise = require('../../js/release/bluebird.js'); 4 | require('../lib/fakesP'); 5 | 6 | module.exports = function upload(stream, idOrPath, tag, done) { 7 | var queries = new Array(global.parallelQueries); 8 | var tx = db.begin(); 9 | 10 | for( var i = 0, len = queries.length; i < len; ++i ) { 11 | queries[i] = FileVersion.insert({index: i}).execWithin(tx); 12 | } 13 | 14 | Promise.all(queries).then(function() { 15 | tx.commit(); 16 | done(); 17 | }, function(err) { 18 | tx.rollback(); 19 | done(err); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /benchmark/madeup-parallel/promises-calvinmetcalf-lie.js: -------------------------------------------------------------------------------- 1 | global.useLie = true; 2 | 3 | var Promise = require("lie"); 4 | 5 | require('../lib/fakesP'); 6 | 7 | module.exports = function upload(stream, idOrPath, tag, done) { 8 | var queries = new Array(global.parallelQueries); 9 | var tx = db.begin(); 10 | 11 | for( var i = 0, len = queries.length; i < len; ++i ) { 12 | queries[i] = FileVersion.insert({index: i}).execWithin(tx); 13 | } 14 | 15 | Promise.all(queries).then(function() { 16 | tx.commit(); 17 | done(); 18 | }, function(err) { 19 | tx.rollback(); 20 | done(err); 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /benchmark/madeup-parallel/promises-cujojs-when.js: -------------------------------------------------------------------------------- 1 | global.useWhen = true; 2 | 3 | var when = require('when'); 4 | 5 | require('../lib/fakesP'); 6 | 7 | module.exports = function upload(stream, idOrPath, tag, done) { 8 | var queries = new Array(global.parallelQueries); 9 | var tx = db.begin(); 10 | 11 | for( var i = 0, len = queries.length; i < len; ++i ) { 12 | queries[i] = FileVersion.insert({index: i}).execWithin(tx); 13 | } 14 | 15 | when.all(queries).then(function() { 16 | tx.commit(); 17 | done(); 18 | }, function(err) { 19 | tx.rollback(); 20 | done(err); 21 | }); 22 | }; 23 | -------------------------------------------------------------------------------- /benchmark/madeup-parallel/promises-dfilatov-vow.js: -------------------------------------------------------------------------------- 1 | var vow = require('vow'), 2 | p = require('../lib/promiseSupport.js'); 3 | 4 | require('../lib/fakesP'); 5 | 6 | module.exports = function upload(stream, idOrPath, tag, done) { 7 | var queries = new Array(global.parallelQueries); 8 | var tx = db.begin(); 9 | 10 | for( var i = 0, len = queries.length; i < len; ++i ) { 11 | queries[i] = FileVersion.insert({index: i}).execWithin(tx); 12 | } 13 | 14 | vow.all(queries).then(function() { 15 | tx.commit(); 16 | done(); 17 | }, function(err) { 18 | tx.rollback(); 19 | done(err); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /benchmark/madeup-parallel/promises-ecmascript6-native.js: -------------------------------------------------------------------------------- 1 | global.useNative = true; 2 | 3 | try { 4 | if (Promise.race.toString() !== 'function race() { [native code] }') 5 | throw 0; 6 | } catch (e) { 7 | throw new Error("No ES6 promises available"); 8 | } 9 | 10 | require('../lib/fakesP'); 11 | 12 | module.exports = function upload(stream, idOrPath, tag, done) { 13 | var queries = new Array(global.parallelQueries); 14 | var tx = db.begin(); 15 | 16 | for( var i = 0, len = queries.length; i < len; ++i ) { 17 | queries[i] = FileVersion.insert({index: i}).execWithin(tx); 18 | } 19 | 20 | Promise.all(queries).then(function() { 21 | tx.commit(); 22 | done(); 23 | }, function(err) { 24 | tx.rollback(); 25 | done(err); 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /benchmark/madeup-parallel/promises-lvivski-davy.js: -------------------------------------------------------------------------------- 1 | global.useDavy = true; 2 | 3 | var davy = require('davy'); 4 | 5 | require('../lib/fakesP'); 6 | 7 | module.exports = function upload(stream, idOrPath, tag, done) { 8 | var queries = new Array(global.parallelQueries); 9 | var tx = db.begin(); 10 | 11 | for( var i = 0, len = queries.length; i < len; ++i ) { 12 | queries[i] = FileVersion.insert({index: i}).execWithin(tx); 13 | } 14 | 15 | davy.all(queries).then(function() { 16 | tx.commit(); 17 | done(); 18 | }, function(err) { 19 | tx.rollback(); 20 | done(err); 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /benchmark/madeup-parallel/promises-medikoo-deferred.js: -------------------------------------------------------------------------------- 1 | global.useDeferred = true; 2 | 3 | var deferred = require('deferred'); 4 | 5 | require('../lib/fakesP'); 6 | 7 | function identity(v) { 8 | return v; 9 | } 10 | 11 | module.exports = function upload(stream, idOrPath, tag, done) { 12 | var queries = new Array(global.parallelQueries); 13 | var tx = db.begin(); 14 | 15 | for( var i = 0, len = queries.length; i < len; ++i ) { 16 | queries[i] = FileVersion.insert({index: i}).execWithin(tx); 17 | } 18 | 19 | //Couldn't find .all in docs, this seems closest 20 | deferred.map(queries, identity)(function() { 21 | tx.commit(); 22 | done(); 23 | }, function(err) { 24 | tx.rollback(); 25 | done(err); 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /benchmark/madeup-parallel/promises-native-async-await.js: -------------------------------------------------------------------------------- 1 | global.useNative = true; 2 | 3 | try { 4 | if (Promise.race.toString() !== 'function race() { [native code] }') 5 | throw 0; 6 | } catch (e) { 7 | throw new Error("No ES6 promises available"); 8 | } 9 | 10 | require('../lib/fakesP'); 11 | 12 | module.exports = async function upload(stream, idOrPath, tag, done) { 13 | var queries = new Array(global.parallelQueries); 14 | var tx = db.begin(); 15 | 16 | for( var i = 0, len = queries.length; i < len; ++i ) { 17 | queries[i] = FileVersion.insert({index: i}).execWithin(tx); 18 | } 19 | 20 | try { 21 | await Promise.all(queries); 22 | tx.commit(); 23 | done(); 24 | } 25 | catch(e) { 26 | tx.rollback(); 27 | done(e); 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /benchmark/madeup-parallel/promises-obvious-kew.js: -------------------------------------------------------------------------------- 1 | global.useKew = true; 2 | 3 | var q = require('kew'); 4 | 5 | require('../lib/fakesP'); 6 | 7 | module.exports = function upload(stream, idOrPath, tag, done) { 8 | var queries = new Array(global.parallelQueries); 9 | var tx = db.begin(); 10 | 11 | for( var i = 0, len = queries.length; i < len; ++i ) { 12 | queries[i] = FileVersion.insert({index: i}).execWithin(tx); 13 | } 14 | 15 | q.all(queries).then(function() { 16 | tx.commit(); 17 | done(); 18 | }, function(err) { 19 | tx.rollback(); 20 | done(err); 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /benchmark/madeup-parallel/promises-then-promise.js: -------------------------------------------------------------------------------- 1 | global.useThenPromise = true; 2 | 3 | var Promise = require("promise"); 4 | 5 | require('../lib/fakesP'); 6 | 7 | module.exports = function upload(stream, idOrPath, tag, done) { 8 | var queries = new Array(global.parallelQueries); 9 | var tx = db.begin(); 10 | 11 | for( var i = 0, len = queries.length; i < len; ++i ) { 12 | queries[i] = FileVersion.insert({index: i}).execWithin(tx); 13 | } 14 | 15 | Promise.all(queries).then(function() { 16 | tx.commit(); 17 | done(); 18 | }, function(err) { 19 | tx.rollback(); 20 | done(err); 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /benchmark/madeup-parallel/promises-tildeio-rsvp.js: -------------------------------------------------------------------------------- 1 | global.useRSVP = true; 2 | 3 | var RSVP = require('rsvp'); 4 | 5 | require('../lib/fakesP'); 6 | 7 | module.exports = function upload(stream, idOrPath, tag, done) { 8 | var queries = new Array(global.parallelQueries); 9 | var tx = db.begin(); 10 | 11 | for( var i = 0, len = queries.length; i < len; ++i ) { 12 | queries[i] = FileVersion.insert({index: i}).execWithin(tx); 13 | } 14 | 15 | RSVP.all(queries).then(function() { 16 | tx.commit(); 17 | done(); 18 | }, function(err) { 19 | tx.rollback(); 20 | done(err); 21 | }); 22 | }; 23 | -------------------------------------------------------------------------------- /benchmark/madeup-parallel/streamline-generators.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var _streamline = typeof require === 'function' ? require('streamline-runtime/lib/generators/runtime') : Streamline.require('streamline-runtime/lib/generators/runtime'); 4 | 5 | var _filename = '/Users/bruno/dev/bluebird/benchmark/madeup-parallel/streamline._js'; 6 | 7 | var execWithin = _streamline.async(function* _$$execWithin$$(query, tx, _2) { 8 | { 9 | return yield _streamline.await(_filename, 5, query, 'execWithin', 1, null, false, [tx, true]); 10 | } 11 | }, 2, 3); 12 | 13 | require('../lib/fakes'); 14 | 15 | // Futures work on streamlined function so we need to wrap execWithin 16 | 17 | 18 | module.exports = _streamline.async(function* _$$upload$$(stream, idOrPath, tag, _3) { 19 | { 20 | try { 21 | var queries = new Array(global.parallelQueries); 22 | var tx = db.begin(); 23 | 24 | for (var i = 0, len = queries.length; i < len; ++i) { 25 | queries[i] = _streamline.future(_filename, 14, null, execWithin, 2, null, false, [FileVersion.insert({ index: i }), tx, false]); 26 | } 27 | 28 | for (var i = 0, len = queries.length; i < len; ++i) { 29 | yield _streamline.await(_filename, 18, queries, i, 0, null, false, [true]); 30 | } 31 | 32 | tx.commit(); 33 | } catch (err) { 34 | tx.rollback(); 35 | throw err; 36 | } 37 | } 38 | }, 3, 4); -------------------------------------------------------------------------------- /benchmark/madeup-parallel/streamline._js: -------------------------------------------------------------------------------- 1 | require('../lib/fakes'); 2 | 3 | // Futures work on streamlined function so we need to wrap execWithin 4 | function execWithin(query, tx, _) { 5 | return query.execWithin(tx, _); 6 | } 7 | 8 | module.exports = function upload(stream, idOrPath, tag, _) { 9 | try { 10 | var queries = new Array(global.parallelQueries); 11 | var tx = db.begin(); 12 | 13 | for (var i = 0, len = queries.length; i < len; ++i ) { 14 | queries[i] = execWithin(FileVersion.insert({index: i}), tx, !_); 15 | } 16 | 17 | for (var i = 0, len = queries.length; i < len; ++i ) { 18 | queries[i](_); 19 | } 20 | 21 | tx.commit(); 22 | } catch (err) { 23 | tx.rollback(); 24 | throw err; 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /benchmark/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "async-compare", 3 | "version": "0.1.1", 4 | "description": "Compare the performance and code of multiple async patterns", 5 | "main": "perf.js", 6 | "dependencies": { 7 | "async": "^2.6.1", 8 | "davy": "^1.3.0", 9 | "deferred": "^0.7.9", 10 | "kew": "^0.7.0", 11 | "lie": "^3.3.0", 12 | "neo-async": "^2.5.1", 13 | "optimist": "^0.6.1", 14 | "promise": "^8.0.1", 15 | "q": "^1.5.1", 16 | "rsvp": "^4.8.3", 17 | "streamline": "^2.1.3", 18 | "streamline-runtime": "^1.1.15", 19 | "text-table": "^0.2.0", 20 | "vow": "^0.4.17", 21 | "when": "^3.7.8" 22 | }, 23 | "devDependencies": {}, 24 | "scripts": { 25 | "test": "echo \"Error: no test specified\" && exit 1" 26 | }, 27 | "keywords": [ 28 | "generators", 29 | "fibers", 30 | "promises", 31 | "callbacks", 32 | "comparison", 33 | "compare", 34 | "async" 35 | ], 36 | "author": "spion", 37 | "license": "MIT", 38 | "engines": { 39 | "node": ">8.11.0 <9" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bluebird", 3 | "version": "3.7.2", 4 | "homepage": "https://github.com/petkaantonov/bluebird", 5 | "authors": [ 6 | "Petka Antonov " 7 | ], 8 | "description": "Bluebird is a full featured promise library with unmatched performance.", 9 | "main": "js/browser/bluebird.js", 10 | "license": "MIT", 11 | "ignore": [ 12 | "**/.*", 13 | "benchmark", 14 | "bower_components", 15 | "./browser", 16 | "node_modules", 17 | "test" 18 | ], 19 | "keywords": [ 20 | "promise", 21 | "performance", 22 | "promises", 23 | "promises-a", 24 | "promises-aplus", 25 | "async", 26 | "await", 27 | "deferred", 28 | "deferreds", 29 | "future", 30 | "flow control", 31 | "dsl", 32 | "fluent interface" 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /build: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | node tools/build.js "$@" 3 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | [http://bluebirdjs.com/docs/changelog.html](http://bluebirdjs.com/docs/changelog.html) 2 | -------------------------------------------------------------------------------- /deprecated_apis.md: -------------------------------------------------------------------------------- 1 | [http://bluebirdjs.com/docs/deprecated-apis.html](http://bluebirdjs.com/docs/deprecated-apis.html) 2 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | _site 2 | .sass-cache 3 | Gemfile.lock 4 | -------------------------------------------------------------------------------- /docs/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem "jekyll", '3.9.0' 4 | gem "jekyll-redirect-from" 5 | gem "sanitize", '4.0.1' 6 | gem "redcarpet" 7 | gem "pygments.rb" 8 | gem 'wdm', '>= 0.1.0' if Gem.win_platform? 9 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | Requires ruby and [jekyll](http://jekyllrb.com/). See the gem file for dependencies. 2 | 3 | Change directory to `bluebird/docs` and run `jekyll serve`. The docs will be hosted under `/docs` directory in relation to the web root. Typically something like `http://localhost:4000/docs/` 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | name: bluebird 2 | description: Bluebird is a fully featured JavaScript promises library with unmatched performance. 3 | url: "http://bluebirdjs.com" 4 | baseurl: "" 5 | title: bluebird 6 | timezone: Helsinki/Finland 7 | highlighter: pygments 8 | exclude: 9 | - Gemfile 10 | - Gemfile.lock 11 | - helpers.rb 12 | defaults: 13 | - scope: 14 | path: docs 15 | type: pages 16 | values: 17 | layout: page 18 | markdown: redcarpet 19 | redcarpet: 20 | extensions: 21 | - fenced_code_blocks 22 | version: 3.7.2 23 | gems: 24 | - jekyll-redirect-from 25 | destination: ../gh-pages/ 26 | keep_files: 27 | - .git 28 | - .gitignore 29 | - logo.png 30 | - CNAME 31 | - coverage 32 | safe: false 33 | encoding: utf-8 34 | host: 0.0.0.0 35 | 36 | -------------------------------------------------------------------------------- /docs/_layouts/api.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 | 5 |
6 |
7 | {{ content }} 8 |
9 |
10 | -------------------------------------------------------------------------------- /docs/_layouts/page.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 |
5 | 6 |
7 |

{{ page.title }}

8 |
9 | 10 |
11 | {{ content }} 12 |
13 | 14 |
15 | -------------------------------------------------------------------------------- /docs/_plugins/mdate.rb: -------------------------------------------------------------------------------- 1 | module Jekyll 2 | module MyFilters 3 | def file_date(input) 4 | File.mtime(input) 5 | end 6 | 7 | def check_active(page_path, link_type) 8 | if (link_type == "support" and page_path =~ /support/) or 9 | (link_type == "install" and page_path =~ /install/) or 10 | (link_type == "docs") 11 | "active" 12 | else 13 | "" 14 | end 15 | end 16 | end 17 | end 18 | 19 | Liquid::Template.register_filter(Jekyll::MyFilters) 20 | -------------------------------------------------------------------------------- /docs/_plugins/plugin.rb: -------------------------------------------------------------------------------- 1 | require "redcarpet" 2 | require "pygments" 3 | require_relative "../helpers" 4 | 5 | 6 | class Redcarpet::Render::HTML 7 | def header(title, level) 8 | anchor = Helpers.clean(title) 9 | 10 | return <<-eos 11 | 12 | 16 | #{title} 17 | 18 | eos 19 | end 20 | # Hacks to get markdown working inside html blocks .... 21 | def block_html(html) 22 | html.gsub(/([\d\D]+?)<\/markdown>/) {|_| 23 | extensions = {fenced_code_blocks: true} 24 | renderer = Redcarpet::Markdown.new(WithHighlights, extensions) 25 | renderer.render(Regexp.last_match[1]) 26 | } 27 | end 28 | 29 | def link(link, title, content) 30 | if link == "unfinished-article" 31 | return <<-eos 32 |
33 | This article is partially or completely unfinished. 34 | You are welcome to create pull requests 35 | to help completing this article. 36 |
37 | eos 38 | elsif link == "." 39 | if content =~ /#\d+/ 40 | url = "https://github.com/petkaantonov/bluebird/issues/" + content[1..-1] 41 | else 42 | url = "/docs/api/" + Helpers.clean(content) + ".html" 43 | end 44 | return "#{content}" 45 | else 46 | return "#{content}" 47 | end 48 | end 49 | end 50 | 51 | class WithHighlights < Redcarpet::Render::HTML 52 | def block_code(code, language) 53 | Pygments.highlight(code, :lexer => language) 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /docs/docs/api/aggregateerror.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: aggregateerror 4 | title: AggregateError 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##AggregateError 11 | 12 | ```js 13 | new AggregateError() extends Array -> AggregateError 14 | ``` 15 | 16 | 17 | A collection of errors. `AggregateError` is an array-like object, with numeric indices and a `.length` property. It supports all generic array methods such as `.forEach` directly. 18 | 19 | `AggregateError`s are caught in [`.error`](.) handlers, even if the contained errors are not operational. 20 | 21 | [Promise.some](.) and [Promise.any](.) use `AggregateError` as rejection reason when they fail. 22 | 23 | 24 | Example: 25 | 26 | ```js 27 | //Assumes AggregateError has been made global 28 | var err = new AggregateError(); 29 | err.push(new Error("first error")); 30 | err.push(new Error("second error")); 31 | throw err; 32 | ``` 33 | 34 |
35 |
36 | 37 |
38 | 49 | -------------------------------------------------------------------------------- /docs/docs/api/all.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: all 4 | title: .all 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##.all 11 | 12 | ```js 13 | .all() -> Promise 14 | ``` 15 | 16 | Consume the resolved [`Iterable`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) and wait for all items to fulfill similar to [Promise.all()](.). 17 | 18 | [Promise.resolve(iterable).all()](.) is the same as [Promise.all(iterable)](.). 19 |
20 | 21 |
22 | 33 | 34 | -------------------------------------------------------------------------------- /docs/docs/api/any.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: any 4 | title: .any 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##.any 11 | 12 | ```js 13 | .any() -> Promise 14 | ``` 15 | 16 | Same as [Promise.any(this)](.). 17 |
18 | 19 |
20 | 31 | -------------------------------------------------------------------------------- /docs/docs/api/bind.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: bind 4 | title: .bind 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##.bind 11 | 12 | ```js 13 | .bind(any|Promise thisArg) -> BoundPromise 14 | ``` 15 | 16 | Same as calling [Promise.bind(thisArg, thisPromise)](.). 17 |
18 | 19 |
20 | 31 | -------------------------------------------------------------------------------- /docs/docs/api/built-in-error-types.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: built-in-error-types 4 | title: Built-in error types 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##Built-in error types 11 | 12 | Bluebird includes a few built-in error types for common usage. All error types have the same identity across different copies of bluebird 13 | module so that pattern matching works in [`.catch`](.). All error types have a constructor taking a message string as their first argument, with that message 14 | becoming the `.message` property of the error object. 15 | 16 | By default the error types need to be referenced from the Promise constructor, e.g. to get a reference to [TimeoutError](.), do `var TimeoutError = Promise.TimeoutError`. However, for convenience you will probably want to just make the references global. 17 |
18 | 19 |
20 | 31 | -------------------------------------------------------------------------------- /docs/docs/api/cancel.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: cancel 4 | title: .cancel 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##.cancel 11 | 12 | ```js 13 | .cancel() -> undefined 14 | ``` 15 | 16 | Cancel this promise. Will not do anything if this promise is already settled or if the [Cancellation](.) feature has not been enabled. See [Cancellation](.) for how to use cancellation. 17 | 18 |
19 |
20 | 21 |
22 | 33 | -------------------------------------------------------------------------------- /docs/docs/api/cancellationerror.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: cancellationerror 4 | title: CancellationError 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##CancellationError 11 | 12 | ```js 13 | new CancellationError(String message) -> CancellationError 14 | ``` 15 | 16 | 17 | Signals that an operation has been aborted or cancelled. The default reason used by [`.cancel`](.). 18 |
19 | 20 |
21 | 32 | -------------------------------------------------------------------------------- /docs/docs/api/catchreturn.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: catchreturn 4 | title: .catchReturn 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##.catchReturn 11 | 12 | ```js 13 | .catchReturn( 14 | [class ErrorClass|function(any error) predicate], 15 | any value 16 | ) -> Promise 17 | ``` 18 | 19 | Convenience method for: 20 | 21 | ```js 22 | .catch(function() { 23 | return value; 24 | }); 25 | ``` 26 | You may optionally prepend one predicate function or ErrorClass to pattern match the error (the generic [.catch](.) methods accepts multiple) 27 | 28 | Same limitations regarding to the binding time of `value` to apply as with [`.return`](.). 29 |
30 | 31 |
32 | 43 | -------------------------------------------------------------------------------- /docs/docs/api/catchthrow.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: catchthrow 4 | title: .catchThrow 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##.catchThrow 11 | 12 | ```js 13 | .catchThrow( 14 | [class ErrorClass|function(any error) predicate], 15 | any reason 16 | ) -> Promise 17 | ``` 18 | 19 | Convenience method for: 20 | 21 | ```js 22 | .catch(function() { 23 | throw reason; 24 | }); 25 | ``` 26 | You may optionally prepend one predicate function or ErrorClass to pattern match the error (the generic [.catch](.) methods accepts multiple) 27 | 28 | Same limitations regarding to the binding time of `reason` to apply as with [`.return`](.). 29 |
30 | 31 |
32 | 43 | -------------------------------------------------------------------------------- /docs/docs/api/collections.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: collections 4 | title: Collections 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##Collections 11 | 12 | Methods of `Promise` instances and core static methods of the Promise class to deal with collections of promises or mixed promises and values. 13 | 14 | All collection methods have a static equivalent on the Promise object, e.g. `somePromise.map(...)...` is same as `Promise.map(somePromise, ...)...`, 15 | `somePromise.all` is same as [`Promise.all`](.) and so on. 16 | 17 | None of the collection methods modify the original input. Holes in arrays are treated as if they were defined with the value `undefined`. 18 |
19 | 20 |
21 | 32 | -------------------------------------------------------------------------------- /docs/docs/api/core.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: core 4 | title: Core 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##Core 11 | 12 | Core methods of `Promise` instances and core static methods of the Promise class. 13 |
14 | 15 |
16 | 27 | -------------------------------------------------------------------------------- /docs/docs/api/deferred-migration.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: deferred-migration 4 | title: Deferred migration 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##Deferred migration 11 | 12 | Deferreds are deprecated in favor of the promise constructor. If you need deferreds for some reason, you can create them trivially using the constructor: 13 | 14 | ```js 15 | function defer() { 16 | var resolve, reject; 17 | var promise = new Promise(function() { 18 | resolve = arguments[0]; 19 | reject = arguments[1]; 20 | }); 21 | return { 22 | resolve: resolve, 23 | reject: reject, 24 | promise: promise 25 | }; 26 | } 27 | ``` 28 | 29 | For old code that still uses deferred objects, see [the deprecated API docs ](//bluebirdjs.com/docs/deprecated-apis.html#promise-resolution). 30 |
31 | 32 |
33 | 44 | 45 | -------------------------------------------------------------------------------- /docs/docs/api/delay.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: delay 4 | title: .delay 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##.delay 11 | 12 | ```js 13 | .delay(int ms) -> Promise 14 | ``` 15 | 16 | Same as calling [Promise.delay(ms, this)](.). 17 |
18 | 19 |
20 | 31 | -------------------------------------------------------------------------------- /docs/docs/api/done.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: done 4 | title: .done 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##.done 11 | 12 | ```js 13 | .done( 14 | [function(any value) fulfilledHandler], 15 | [function(any error) rejectedHandler] 16 | ) -> undefined 17 | ``` 18 | 19 | 20 | Like [`.then`](.), but any unhandled rejection that ends up here will crash the process (in node) or be thrown as an error (in browsers). The use of this method is heavily discouraged and it only exists for historical reasons. 21 | 22 |
23 |
24 | 25 |
26 | 37 | -------------------------------------------------------------------------------- /docs/docs/api/filter.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: filter 4 | title: .filter 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##.filter 11 | 12 | ```js 13 | .filter( 14 | function(any item, int index, int length) filterer, 15 | [Object {concurrency: int=Infinity} options] 16 | ) -> Promise 17 | ``` 18 | 19 | Same as [Promise.filter(this, filterer, options)](.). 20 |
21 | 22 |
23 | 34 | -------------------------------------------------------------------------------- /docs/docs/api/generators.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: generators 4 | title: Generators 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##Generators 11 | 12 | Using ECMAScript6 generators feature to implement C# 5.0 `async/await` like syntax. 13 |
14 | 15 |
16 | 27 | -------------------------------------------------------------------------------- /docs/docs/api/get.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: get 4 | title: .get 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##.get 11 | 12 | ```js 13 | .get(String propertyName|int index) -> Promise 14 | ``` 15 | 16 | 17 | This is a convenience method for doing: 18 | 19 | ```js 20 | promise.then(function(obj) { 21 | return obj[propertyName]; 22 | }); 23 | ``` 24 | 25 | For example: 26 | 27 | ```js 28 | db.query("...") 29 | .get(0) 30 | .then(function(firstRow) { 31 | 32 | }); 33 | ``` 34 | 35 | If `index` is negative, the indexed load will become `obj.length + index`. So that -1 can be used to read last item 36 | in the array, -2 to read the second last and so on. For example: 37 | 38 | ```js 39 | Promise.resolve([1,2,3]).get(-1).then(function(value) { 40 | console.log(value); // 3 41 | }); 42 | ``` 43 | 44 | If the `index` is still negative after `obj.length + index`, it will be clamped to 0. 45 |
46 | 47 |
48 | 59 | -------------------------------------------------------------------------------- /docs/docs/api/iscancelled.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: iscancelled 4 | title: .isCancelled 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##.isCancelled 11 | 12 | ```js 13 | .isCancelled() -> boolean 14 | ``` 15 | 16 | See if this `promise` has been cancelled. 17 |
18 | 19 |
20 | 31 | -------------------------------------------------------------------------------- /docs/docs/api/isfulfilled.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: isfulfilled 4 | title: .isFulfilled 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##.isFulfilled 11 | 12 | ```js 13 | .isFulfilled() -> boolean 14 | ``` 15 | 16 | See if this promise has been fulfilled. 17 |
18 | 19 |
20 | 31 | -------------------------------------------------------------------------------- /docs/docs/api/ispending.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: ispending 4 | title: .isPending 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##.isPending 11 | 12 | ```js 13 | .isPending() -> boolean 14 | ``` 15 | 16 | 17 | See if this `promise` is pending (not fulfilled or rejected or cancelled). 18 |
19 | 20 |
21 | 32 | -------------------------------------------------------------------------------- /docs/docs/api/isrejected.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: isrejected 4 | title: .isRejected 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##.isRejected 11 | 12 | ```js 13 | .isRejected() -> boolean 14 | ``` 15 | 16 | See if this promise has been rejected. 17 |
18 | 19 |
20 | 31 | -------------------------------------------------------------------------------- /docs/docs/api/map.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: map 4 | title: .map 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##.map 11 | 12 | ```js 13 | .map( 14 | function(any item, int index, int length) mapper, 15 | [Object {concurrency: int=Infinity} options] 16 | ) -> Promise 17 | ``` 18 | 19 | Same as [Promise.map(this, mapper, options)](.). 20 |
21 | 22 |
23 | 34 | -------------------------------------------------------------------------------- /docs/docs/api/mapseries.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: mapseries 4 | title: .mapseries 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##.mapSeries 11 | 12 | ```js 13 | .mapSeries(function(any item, int index, int length) mapper) -> Promise 14 | ``` 15 | 16 | Same as [Promise.mapSeries(this, iterator)](.). 17 |
18 | 19 |
20 | 31 | 32 | -------------------------------------------------------------------------------- /docs/docs/api/operationalerror.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: operationalerror 4 | title: OperationalError 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##OperationalError 11 | 12 | ```js 13 | new OperationalError(String message) -> OperationalError 14 | ``` 15 | 16 | 17 | Represents an error is an explicit promise rejection as opposed to a thrown error. For example, if an error is errbacked by a callback API promisified through [`Promise.promisify`](.) or [`Promise.promisifyAll`](.) 18 | and is not a typed error, it will be converted to a `OperationalError` which has the original error in the `.cause` property. 19 | 20 | `OperationalError`s are caught in [`.error`](.) handlers. 21 |
22 | 23 |
24 | 35 | 36 | -------------------------------------------------------------------------------- /docs/docs/api/promise.all.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: promise.all 4 | title: Promise.all 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##Promise.all 11 | 12 | ```js 13 | Promise.all(Iterable|Promise> input) -> Promise> 14 | ``` 15 | 16 | This method is useful for when you want to wait for more than one promise to complete. 17 | 18 | Given an [`Iterable`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols)\(arrays are `Iterable`\), or a promise of an `Iterable`, which produces promises (or a mix of promises and values), iterate over all the values in the `Iterable` into an array and return a promise that is fulfilled when all the items in the array are fulfilled. The promise's fulfillment value is an array with fulfillment values at respective positions to the original array. If any promise in the array rejects, the returned promise is rejected with the rejection reason. 19 | 20 | 21 | ```js 22 | var files = []; 23 | for (var i = 0; i < 100; ++i) { 24 | files.push(fs.writeFileAsync("file-" + i + ".txt", "", "utf-8")); 25 | } 26 | Promise.all(files).then(function() { 27 | console.log("all the files were created"); 28 | }); 29 | ``` 30 | 31 | 32 | This method is compatible with [`Promise.all`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all) from native promises. 33 |
34 | 35 |
36 | 47 | 48 | -------------------------------------------------------------------------------- /docs/docs/api/promise.any.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: promise.any 4 | title: Promise.any 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##Promise.any 11 | 12 | ```js 13 | Promise.any(Iterable|Promise> input) -> Promise 14 | ``` 15 | 16 | Like [Promise.some](.), with 1 as `count`. However, if the promise fulfills, the fulfillment value is not an array of 1 but the value directly. 17 |
18 | 19 |
20 | 31 | -------------------------------------------------------------------------------- /docs/docs/api/promise.delay.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: promise.delay 4 | title: Promise.delay 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##Promise.delay 11 | 12 | ```js 13 | Promise.delay( 14 | int ms, 15 | [any|Promise value=undefined] 16 | ) -> Promise 17 | ``` 18 | 19 | 20 | Returns a promise that will be resolved with `value` (or `undefined`) after given `ms` milliseconds. If `value` is a promise, the delay will start counting down when it is fulfilled and the returned promise will be fulfilled with the fulfillment value of the `value` promise. If `value` is a rejected promise, the resulting promise will be rejected immediately. 21 | 22 | ```js 23 | Promise.delay(500).then(function() { 24 | console.log("500 ms passed"); 25 | return "Hello world"; 26 | }).delay(500).then(function(helloWorldString) { 27 | console.log(helloWorldString); 28 | console.log("another 500 ms passed") ; 29 | }); 30 | ``` 31 | 32 |
33 |
34 | 35 |
36 | 47 | 48 | -------------------------------------------------------------------------------- /docs/docs/api/promise.noconflict.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: promise.noconflict 4 | title: Promise.noConflict 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##Promise.noConflict 11 | 12 | ```js 13 | Promise.noConflict() -> Object 14 | ``` 15 | 16 | 17 | This is relevant to browser environments with no module loader. 18 | 19 | Release control of the `Promise` namespace to whatever it was before this library was loaded. Returns a reference to the library namespace so you can attach it to something else. 20 | 21 | ```html 22 | 23 | 24 | 25 | 32 | ``` 33 |
34 | 35 |
36 | 47 | -------------------------------------------------------------------------------- /docs/docs/api/promise.onpossiblyunhandledrejection.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: promise.onpossiblyunhandledrejection 4 | title: Promise.onPossiblyUnhandledRejection 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##Promise.onPossiblyUnhandledRejection 11 | 12 | ```js 13 | Promise.onPossiblyUnhandledRejection(function(any error, Promise promise) handler) -> undefined 14 | ``` 15 | 16 | 17 | *Note: this hook is specific to the bluebird instance it's called on, application developers should use [global rejection events](/docs/api/error-management-configuration.html#global-rejection-events)* 18 | 19 | Add `handler` as the handler to call when there is a possibly unhandled rejection. The default handler logs the error stack to stderr or `console.error` in browsers. 20 | 21 | ```js 22 | Promise.onPossiblyUnhandledRejection(function(e, promise) { 23 | throw e; 24 | }); 25 | ``` 26 | 27 | Passing no value or a non-function will have the effect of removing any kind of handling for possibly unhandled rejections. 28 |
29 | 30 |
31 | 42 | 43 | -------------------------------------------------------------------------------- /docs/docs/api/promise.onunhandledrejectionhandled.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: promise.onunhandledrejectionhandled 4 | title: Promise.onUnhandledRejectionHandled 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##Promise.onUnhandledRejectionHandled 11 | 12 | ```js 13 | Promise.onUnhandledRejectionHandled(function(Promise promise) handler) -> undefined 14 | ``` 15 | 16 | 17 | *Note: this hook is specific to the bluebird instance its called on, application developers should use [global rejection events](/docs/api/error-management-configuration.html#global-rejection-events)* 18 | 19 | Add `handler` as the handler to call when a rejected promise that was reported as "possibly unhandled rejection" became handled. 20 | 21 | Together with `onPossiblyUnhandledRejection` these hooks can be used to implement a debugger that will show a list 22 | of unhandled promise rejections updated in real time as promises become handled. 23 | 24 | For example: 25 | 26 | ```js 27 | var unhandledPromises = []; 28 | Promise.onPossiblyUnhandledRejection(function(reason, promise) { 29 | unhandledPromises.push(promise); 30 | //Update some debugger UI 31 | }); 32 | 33 | Promise.onUnhandledRejectionHandled(function(promise) { 34 | var index = unhandledPromises.indexOf(promise); 35 | unhandledPromises.splice(index, 1); 36 | //Update the debugger UI 37 | }); 38 | ``` 39 |
40 | 41 |
42 | 53 | -------------------------------------------------------------------------------- /docs/docs/api/promise.race.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: promise.race 4 | title: Promise.race 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##Promise.race 11 | 12 | ```js 13 | Promise.race(Iterable|Promise> input) -> Promise 14 | ``` 15 | 16 | Given an [`Iterable`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols)\(arrays are `Iterable`\), or a promise of an `Iterable`, which produces promises (or a mix of promises and values), iterate over all the values in the `Iterable` into an array and return a promise that is fulfilled or rejected as soon as a promise in the array is fulfilled or rejected with the respective rejection reason or fulfillment value. 17 | 18 | This method is only implemented because it's in the ES6 standard. If you want to race promises to fulfillment the [`.any`](.) method is more appropriate as it doesn't qualify a rejected promise as the winner. It also has less surprises: `.race` must become infinitely pending if an empty array is passed but passing an empty array to [`.any`](.) is more usefully a `RangeError` 19 |
20 | 21 |
22 | 33 | -------------------------------------------------------------------------------- /docs/docs/api/promise.reject.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: promise.reject 4 | title: Promise.reject 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##Promise.reject 11 | 12 | ```js 13 | Promise.reject(any error) -> Promise 14 | ``` 15 | 16 | 17 | Create a promise that is rejected with the given `error`. 18 |
19 | 20 |
21 | 32 | -------------------------------------------------------------------------------- /docs/docs/api/promise.setscheduler.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: promise.setscheduler 4 | title: Promise.setScheduler 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##Promise.setScheduler 11 | 12 | ```js 13 | Promise.setScheduler(function(function fn) scheduler) -> function 14 | ``` 15 | 16 | 17 | Scheduler should be a function that asynchronously schedules the calling of the passed in function: 18 | 19 | ```js 20 | // This is just an example of how to use the api, there is no reason to do this 21 | Promise.setScheduler(function(fn) { 22 | setTimeout(fn, 0); 23 | }); 24 | ``` 25 | 26 | Setting a custom scheduler could be necessary when you need a faster way to schedule functions than bluebird does by default. It also makes bluebird possible to use in platforms where normal timing constructs like `setTimeout` and `process.nextTick` are not available (like Nashhorn). 27 | 28 | You can also use it as a hook: 29 | 30 | ```js 31 | // This will synchronize bluebird promise queue flushing with angulars queue flushing 32 | // Angular is also now responsible for choosing the actual scheduler 33 | Promise.setScheduler(function(fn) { 34 | $rootScope.$evalAsync(fn); 35 | }); 36 | ``` 37 | 38 | > **Danger** - in order to keep bluebird promises [Promises/A+](https://promisesaplus.com/) compliant a scheduler that executes the function asynchronously (like the examples in this page) must be used. 39 | 40 |
41 | 42 |
43 | 54 | 55 | -------------------------------------------------------------------------------- /docs/docs/api/promise.try.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: promise.try 4 | title: Promise.try 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##Promise.try 11 | 12 | ```js 13 | Promise.try(function() fn) -> Promise 14 | ``` 15 | ```js 16 | Promise.attempt(function() fn) -> Promise 17 | ``` 18 | 19 | 20 | Start the chain of promises with `Promise.try`. Any synchronous exceptions will be turned into rejections on the returned promise. 21 | 22 | ```js 23 | function getUserById(id) { 24 | return Promise.try(function() { 25 | if (typeof id !== "number") { 26 | throw new Error("id must be a number"); 27 | } 28 | return db.getUserById(id); 29 | }); 30 | } 31 | ``` 32 | 33 | Now if someone uses this function, they will catch all errors in their Promise `.catch` handlers instead of having to handle both synchronous and asynchronous exception flows. 34 | 35 | *For compatibility with earlier ECMAScript version, an alias `Promise.attempt` is provided for [`Promise.try`](.).* 36 |
37 | 38 |
39 | 50 | -------------------------------------------------------------------------------- /docs/docs/api/promiseinspection.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: promiseinspection 4 | title: PromiseInspection 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##PromiseInspection 11 | 12 | ```js 13 | interface PromiseInspection { 14 | any reason() 15 | any value() 16 | boolean isPending() 17 | boolean isRejected() 18 | boolean isFulfilled() 19 | boolean isCancelled() 20 | } 21 | ``` 22 | 23 | This interface is implemented by `Promise` instances as well as the `PromiseInspection` result given by [.reflect()](.). 24 |
25 | 26 |
27 | 38 | -------------------------------------------------------------------------------- /docs/docs/api/props.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: props 4 | title: .props 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##.props 11 | 12 | ```js 13 | .props() -> Promise 14 | ``` 15 | 16 | Same as [Promise.props(this)](.). 17 |
18 | 19 |
20 | 31 | -------------------------------------------------------------------------------- /docs/docs/api/race.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: race 4 | title: .race 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##.race 11 | 12 | ```js 13 | .race() -> Promise 14 | ``` 15 | 16 | Same as [Promise.race(this)](.). 17 |
18 | 19 |
20 | 31 | -------------------------------------------------------------------------------- /docs/docs/api/reason.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: reason 4 | title: .reason 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##.reason 11 | 12 | ```js 13 | .reason() -> any 14 | ``` 15 | 16 | 17 | Get the rejection reason of this promise. Throws an error if the promise isn't rejected - it is a bug to call this method on an unrejected promise. 18 | 19 | You should check if this promise is [.isRejected()](.) in code paths where it's guaranteed that this promise is rejected. 20 | 21 |
22 |
23 | 24 |
25 | 36 | -------------------------------------------------------------------------------- /docs/docs/api/reduce.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: reduce 4 | title: .reduce 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##.reduce 11 | 12 | ```js 13 | .reduce( 14 | function(any accumulator, any item, int index, int length) reducer, 15 | [any initialValue] 16 | ) -> Promise 17 | ``` 18 | 19 | Same as [Promise.reduce(this, reducer, initialValue)](.). 20 |
21 | 22 |
23 | 34 | 35 | -------------------------------------------------------------------------------- /docs/docs/api/some.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: some 4 | title: .some 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##.some 11 | 12 | ```js 13 | .some(int count) -> Promise 14 | ``` 15 | 16 | Same as [Promise.some(this, count)](.). 17 |
18 | 19 |
20 | 31 | -------------------------------------------------------------------------------- /docs/docs/api/tap.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: tap 4 | title: .tap 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##.tap 11 | 12 | ```js 13 | .tap(function(any value) handler) -> Promise 14 | ``` 15 | Essentially like `.then()`, except that the value passed in is the value returned. 16 | 17 | This means you can insert `.tap()` into a `.then()` chain without affecting what is passed through the chain. (See example below). 18 | 19 | Unlike [`.finally`](.) this is not called for rejections. 20 | 21 | ```js 22 | getUser().tap(function(user) { 23 | //Like in finally, if you return a promise from the handler 24 | //the promise is awaited for before passing the original value through 25 | return recordStatsAsync(); 26 | }).then(function(user) { 27 | //user is the user from getUser(), not recordStatsAsync() 28 | }); 29 | ``` 30 | 31 | Common case includes adding logging to an existing promise chain: 32 | 33 | ```js 34 | doSomething() 35 | .then(...) 36 | .then(...) 37 | .then(...) 38 | .then(...) 39 | ``` 40 | 41 | ```js 42 | doSomething() 43 | .then(...) 44 | .then(...) 45 | .tap(console.log) 46 | .then(...) 47 | .then(...) 48 | ``` 49 | 50 | *Note: in browsers it is necessary to call `.tap` with `console.log.bind(console)` because console methods can not be called as stand-alone functions.* 51 |
52 | 53 |
54 | 65 | 66 | -------------------------------------------------------------------------------- /docs/docs/api/then.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: then 4 | title: .then 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##.then 11 | 12 | ```js 13 | .then( 14 | [function(any value) fulfilledHandler], 15 | [function(any error) rejectedHandler] 16 | ) -> Promise 17 | ``` 18 | 19 | 20 | [Promises/A+ `.then`](http://promises-aplus.github.io/promises-spec/). If you are new to promises, see the [Beginner's Guide]({{ "/docs/beginners-guide.html" | prepend: site.baseurl }}). 21 |
22 | 23 |
24 | 35 | -------------------------------------------------------------------------------- /docs/docs/api/throw.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: throw 4 | title: .throw 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##.throw 11 | 12 | ```js 13 | .throw(any reason) -> Promise 14 | ``` 15 | ```js 16 | .thenThrow(any reason) -> Promise 17 | ``` 18 | 19 | 20 | Convenience method for: 21 | 22 | ```js 23 | .then(function() { 24 | throw reason; 25 | }); 26 | ``` 27 | 28 | Same limitations regarding to the binding time of `reason` to apply as with [`.return`](.). 29 | 30 | *For compatibility with earlier ECMAScript version, an alias `.thenThrow` is provided for [`.throw`](.).* 31 |
32 | 33 |
34 | 45 | -------------------------------------------------------------------------------- /docs/docs/api/timeout.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: timeout 4 | title: .timeout 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##.timeout 11 | 12 | ```js 13 | .timeout( 14 | int ms, 15 | [String message="operation timed out"] 16 | ) -> Promise 17 | ``` 18 | ```js 19 | .timeout( 20 | int ms, 21 | [Error error] 22 | ) -> Promise 23 | ``` 24 | 25 | 26 | Returns a promise that will be fulfilled with this promise's fulfillment value or rejection reason. However, if this promise is not fulfilled or rejected within `ms` milliseconds, the returned promise is rejected with a [`TimeoutError`](.) or the `error` as the reason. 27 | 28 | When using the first signature, you may specify a custom error message with the `message` parameter. 29 | 30 | 31 | ```js 32 | var Promise = require("bluebird"); 33 | var fs = Promise.promisifyAll(require('fs')); 34 | fs.readFileAsync("huge-file.txt").timeout(100).then(function(fileContents) { 35 | 36 | }).catch(Promise.TimeoutError, function(e) { 37 | console.log("could not read file within 100ms"); 38 | }); 39 | ``` 40 |
41 | 42 |
43 | 54 | 55 | -------------------------------------------------------------------------------- /docs/docs/api/timeouterror.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: timeouterror 4 | title: TimeoutError 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##TimeoutError 11 | 12 | ```js 13 | new TimeoutError(String message) -> TimeoutError 14 | ``` 15 | 16 | 17 | Signals that an operation has timed out. Used as a custom cancellation reason in [`.timeout`](.). 18 |
19 | 20 |
21 | 32 | -------------------------------------------------------------------------------- /docs/docs/api/timers.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: timers 4 | title: Timers 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##Timers 11 | 12 | Methods to delay and time promises out. 13 | 14 |
15 |
16 | 17 |
18 | 29 | -------------------------------------------------------------------------------- /docs/docs/api/utility.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: utility 4 | title: Utility 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##Utility 11 | 12 | Functions that could potentially be handy in some situations. 13 | 14 |
15 |
16 | 17 |
18 | 29 | -------------------------------------------------------------------------------- /docs/docs/api/value.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: api 3 | id: value 4 | title: .value 5 | --- 6 | 7 | 8 | [← Back To API Reference](/docs/api-reference.html) 9 |
10 | ##.value 11 | 12 | ```js 13 | .value() -> any 14 | ``` 15 | 16 | 17 | Get the fulfillment value of this promise. Throws an error if the promise isn't fulfilled - it is a bug to call this method on an unfulfilled promise. 18 | 19 | You should check if this promise is [.isFulfilled()](.) in code paths where it's not guaranteed that this promise is fulfilled. 20 |
21 | 22 |
23 | 34 | 35 | -------------------------------------------------------------------------------- /docs/docs/beginners-guide.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: beginners-guide 3 | title: Beginner's Guide 4 | --- 5 | 6 | [beginners-guide](unfinished-article) 7 | -------------------------------------------------------------------------------- /docs/docs/download-api-reference.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: download-api-reference 3 | title: Download API Reference 4 | --- 5 | 6 | In order to use the documentation offline (without a stable internet connection). 7 | 8 | - Go to [the GitHub Pages Branch `gh-pages`](https://github.com/petkaantonov/bluebird/tree/gh-pages). 9 | - Click "Clone Or Download". 10 | - Click "Download Zip". 11 | - Extract the contents of the zip and open the "docs" folder. 12 | - Open `api-reference.html` which is the documentation root. 13 | -------------------------------------------------------------------------------- /docs/docs/getting-started.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: getting-started 3 | title: Getting Started 4 | redirect_from: "/index.html" 5 | redirect_from: "/docs/index.html" 6 | --- 7 | 8 | [getting-started](unfinished-article) 9 | 10 | ## Node.js 11 | 12 | npm install bluebird 13 | 14 | Then: 15 | 16 | ```js 17 | var Promise = require("bluebird"); 18 | ``` 19 | 20 | Alternatively in ES6 21 | 22 | ```js 23 | import * as Promise from "bluebird"; 24 | ``` 25 | 26 | If that ES6 import [doesn't work](https://github.com/petkaantonov/bluebird/pull/1594) 27 | 28 | ```js 29 | import {Promise} from "bluebird"; 30 | ``` 31 | 32 | ## Browsers 33 | 34 | (See also [Installation](install.html).) 35 | 36 | There are many ways to use bluebird in browsers: 37 | 38 | - Direct downloads 39 | - Full build [bluebird.js](https://cdn.jsdelivr.net/bluebird/latest/bluebird.js) 40 | - Full build minified [bluebird.min.js](https://cdn.jsdelivr.net/bluebird/latest/bluebird.min.js) 41 | - Core build [bluebird.core.js](https://cdn.jsdelivr.net/bluebird/latest/bluebird.core.js) 42 | - Core build minified [bluebird.core.min.js](https://cdn.jsdelivr.net/bluebird/latest/bluebird.core.min.js) 43 | - You may use browserify on the main export 44 | - You may use the [bower](http://bower.io) package. 45 | 46 | When using script tags the global variables `Promise` and `P` (alias for `Promise`) become available. Bluebird runs on a wide variety of browsers including older versions. We'd like to thank BrowserStack for giving us a free account which helps us test that. 47 | -------------------------------------------------------------------------------- /docs/docs/support.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: support 3 | title: Support 4 | --- 5 | 6 | Depending on the nature of your problem there are a few possible ways of getting help with your problem. 7 | 8 | ###Stack Overflow 9 | 10 | Stack Overflow has an active community answering questions on both the [bluebird](http://stackoverflow.com/questions/tagged/bluebird) and [promise](http://stackoverflow.com/questions/tagged/promise) tags. If you are unfamiliar with Stack Overflow, do review [the asking guidelines](http://stackoverflow.com/help/asking) before asking a new question there. 11 | 12 | ###Google Groups mailing list 13 | 14 | The [bluebird-js@googlegroups.com](https://groups.google.com/forum/#!forum/bluebird-js) mailing list is the best place to ask any question that cannot be easily fit in the stack overflow question format. 15 | 16 | ###IRC 17 | 18 | You can usually get fast answers on the freenode.net channels [#bluebird](irc://chat.freenode.net/bluebird) and [#promises](irc://chat.freenode.net/promises). 19 | 20 | ###Gitter 21 | 22 | If you are not comfortable using IRC you can also join the [bluebird gitter chat](https://gitter.im/petkaantonov/bluebird) 23 | 24 | ###Github issue tracker 25 | 26 | If you feel that your problem is caused by a bug or a missing feature that should be added, you should use the [Github issue tracker](https://github.com/petkaantonov/bluebird/issues/) to report it. However in any other case the issue tracker is not the appropriate channel. 27 | -------------------------------------------------------------------------------- /docs/docs/what-about-generators.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: what-about-generators 3 | title: What About Generators? 4 | --- 5 | 6 | There is an [excellent article](https://www.promisejs.org/generators/) on promisejs.org detailing how to combine promises with generators to achieve much cleaner code. Instead of the `async` function the article proposes, you can use [Promise.coroutine](.). 7 | 8 | [what-about-generators](unfinished-article) 9 | -------------------------------------------------------------------------------- /docs/docs/why-performance.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: why-performance 3 | title: Why Performance? 4 | --- 5 | 6 | [why-performance](unfinished-article) 7 | -------------------------------------------------------------------------------- /docs/helpers.rb: -------------------------------------------------------------------------------- 1 | require "sanitize" 2 | 3 | class Helpers 4 | def self.clean(input) 5 | return Sanitize.fragment(input) 6 | .downcase 7 | .gsub(/\s+/, "-") 8 | .gsub(/^([A-Za-z0-9\-_.:]+).*?$/, "\\1") 9 | .gsub(/^\./, "") 10 | .gsub(/\.$/, "") 11 | .gsub(/[^A-Za-z0-9\-_.]/, "") 12 | .sub(/^-+/, "") 13 | .sub(/-+$/, "") 14 | 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /docs/img/README.txt: -------------------------------------------------------------------------------- 1 | SVG available upon request. 2 | -------------------------------------------------------------------------------- /docs/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petkaantonov/bluebird/c220cfe480868e2f5c5de4fe8bb3b04b97588d7f/docs/img/favicon.png -------------------------------------------------------------------------------- /docs/img/libbblog_v3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petkaantonov/bluebird/c220cfe480868e2f5c5de4fe8bb3b04b97588d7f/docs/img/libbblog_v3.png -------------------------------------------------------------------------------- /docs/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petkaantonov/bluebird/c220cfe480868e2f5c5de4fe8bb3b04b97588d7f/docs/img/logo.png -------------------------------------------------------------------------------- /docs/img/supportlogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/petkaantonov/bluebird/c220cfe480868e2f5c5de4fe8bb3b04b97588d7f/docs/img/supportlogo.png -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Redirecting... 4 | 5 | 6 |

Redirecting...

7 | Click here if you are not redirected. 8 | 9 | -------------------------------------------------------------------------------- /issue_template.md: -------------------------------------------------------------------------------- 1 | (This issue tracker is only for bug reports or feature requests, if this is neither, please choose appropriate channel from http://bluebirdjs.com/docs/support.html) 2 | 3 | Please answer the questions the best you can: 4 | 5 | 1) What version of bluebird is the issue happening on? 6 | 7 | 2) What platform and version? (For example Node.js 0.12 or Google Chrome 32) 8 | 9 | 3) Did this issue happen with earlier version of bluebird? 10 | 11 | (Write description of your issue here, stack traces from errors and code that reproduces the issue are helpful) 12 | 13 | -------------------------------------------------------------------------------- /src/any.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | module.exports = function(Promise) { 3 | var SomePromiseArray = Promise._SomePromiseArray; 4 | var ASSERT = require("./assert"); 5 | 6 | function any(promises) { 7 | var ret = new SomePromiseArray(promises); 8 | var promise = ret.promise(); 9 | ASSERT(promise.isPending()); 10 | ASSERT(ret instanceof SomePromiseArray); 11 | ret.setHowMany(1); 12 | ret.setUnwrap(); 13 | ret.init(); 14 | return promise; 15 | } 16 | 17 | Promise.any = function (promises) { 18 | return any(promises); 19 | }; 20 | 21 | Promise.prototype.any = function () { 22 | return any(this); 23 | }; 24 | 25 | }; 26 | -------------------------------------------------------------------------------- /src/assert.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | module.exports = (function(){ 3 | var AssertionError = (function() { 4 | function AssertionError(a) { 5 | this.constructor$(a); 6 | this.message = a; 7 | this.name = "AssertionError"; 8 | } 9 | AssertionError.prototype = new Error(); 10 | AssertionError.prototype.constructor = AssertionError; 11 | AssertionError.prototype.constructor$ = Error; 12 | return AssertionError; 13 | })(); 14 | 15 | function getParams(args) { 16 | var params = []; 17 | for (var i = 0; i < args.length; ++i) params.push("arg" + i); 18 | return params; 19 | } 20 | 21 | function nativeAssert(callName, args, expect) { 22 | try { 23 | var params = getParams(args); 24 | var constructorArgs = params; 25 | constructorArgs.push("return " + 26 | callName + "("+ params.join(",") + ");"); 27 | var fn = Function.apply(null, constructorArgs); 28 | return fn.apply(null, args); 29 | } catch (e) { 30 | if (!(e instanceof SyntaxError)) { 31 | throw e; 32 | } else { 33 | return expect; 34 | } 35 | } 36 | } 37 | 38 | return function assert(boolExpr, message) { 39 | if (boolExpr === true) return; 40 | 41 | if (typeof boolExpr === "string" && 42 | boolExpr.charAt(0) === "%") { 43 | var nativeCallName = boolExpr; 44 | INLINE_SLICE(args, arguments, 2); 45 | if (nativeAssert(nativeCallName, args, message) === message) return; 46 | message = (nativeCallName + " !== " + message); 47 | } 48 | 49 | var ret = new AssertionError(message); 50 | if (Error.captureStackTrace) { 51 | Error.captureStackTrace(ret, assert); 52 | } 53 | throw ret; 54 | }; 55 | })(); 56 | -------------------------------------------------------------------------------- /src/bluebird.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var old; 3 | if (typeof Promise !== "undefined") old = Promise; 4 | function noConflict() { 5 | try { if (Promise === bluebird) Promise = old; } 6 | catch (e) {} 7 | return bluebird; 8 | } 9 | var bluebird = require("./promise")(); 10 | bluebird.noConflict = noConflict; 11 | module.exports = bluebird; 12 | -------------------------------------------------------------------------------- /src/catch_filter.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | module.exports = function(NEXT_FILTER) { 3 | var util = require("./util"); 4 | var getKeys = require("./es5").keys; 5 | var tryCatch = util.tryCatch; 6 | var errorObj = util.errorObj; 7 | 8 | function catchFilter(instances, cb, promise) { 9 | return function(e) { 10 | var boundTo = promise._boundValue(); 11 | predicateLoop: for (var i = 0; i < instances.length; ++i) { 12 | var item = instances[i]; 13 | 14 | if (item === Error || 15 | (item != null && item.prototype instanceof Error)) { 16 | if (e instanceof item) { 17 | return tryCatch(cb).call(boundTo, e); 18 | } 19 | } else if (typeof item === "function") { 20 | var matchesPredicate = tryCatch(item).call(boundTo, e); 21 | if (matchesPredicate === errorObj) { 22 | return matchesPredicate; 23 | } else if (matchesPredicate) { 24 | return tryCatch(cb).call(boundTo, e); 25 | } 26 | } else if (util.isObject(e)) { 27 | var keys = getKeys(item); 28 | for (var j = 0; j < keys.length; ++j) { 29 | var key = keys[j]; 30 | if (item[key] != e[key]) { 31 | continue predicateLoop; 32 | } 33 | } 34 | return tryCatch(cb).call(boundTo, e); 35 | } 36 | } 37 | return NEXT_FILTER; 38 | }; 39 | } 40 | 41 | return catchFilter; 42 | }; 43 | -------------------------------------------------------------------------------- /src/direct_resolve.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | module.exports = function(Promise) { 3 | function returner() { 4 | return this.value; 5 | } 6 | function thrower() { 7 | throw this.reason; 8 | } 9 | 10 | Promise.prototype["return"] = 11 | Promise.prototype.thenReturn = function (value) { 12 | if (value instanceof Promise) value.suppressUnhandledRejections(); 13 | return this._then( 14 | returner, undefined, undefined, {value: value}, undefined); 15 | }; 16 | 17 | Promise.prototype["throw"] = 18 | Promise.prototype.thenThrow = function (reason) { 19 | return this._then( 20 | thrower, undefined, undefined, {reason: reason}, undefined); 21 | }; 22 | 23 | Promise.prototype.catchThrow = function (reason) { 24 | if (arguments.length <= 1) { 25 | return this._then( 26 | undefined, thrower, undefined, {reason: reason}, undefined); 27 | } else { 28 | var _reason = arguments[1]; 29 | var handler = function() {throw _reason;}; 30 | return this.caught(reason, handler); 31 | } 32 | }; 33 | 34 | Promise.prototype.catchReturn = function (value) { 35 | if (arguments.length <= 1) { 36 | if (value instanceof Promise) value.suppressUnhandledRejections(); 37 | return this._then( 38 | undefined, returner, undefined, {value: value}, undefined); 39 | } else { 40 | var _value = arguments[1]; 41 | if (_value instanceof Promise) _value.suppressUnhandledRejections(); 42 | var handler = function() {return _value;}; 43 | return this.caught(value, handler); 44 | } 45 | }; 46 | }; 47 | -------------------------------------------------------------------------------- /src/each.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | module.exports = function(Promise, INTERNAL) { 3 | var PromiseReduce = Promise.reduce; 4 | var PromiseAll = Promise.all; 5 | 6 | function promiseAllThis() { 7 | return PromiseAll(this); 8 | } 9 | 10 | function PromiseMapSeries(promises, fn) { 11 | return PromiseReduce(promises, fn, INTERNAL, INTERNAL); 12 | } 13 | 14 | Promise.prototype.each = function (fn) { 15 | return PromiseReduce(this, fn, INTERNAL, 0) 16 | ._then(promiseAllThis, undefined, undefined, this, undefined); 17 | }; 18 | 19 | Promise.prototype.mapSeries = function (fn) { 20 | return PromiseReduce(this, fn, INTERNAL, INTERNAL); 21 | }; 22 | 23 | Promise.each = function (promises, fn) { 24 | return PromiseReduce(promises, fn, INTERNAL, 0) 25 | ._then(promiseAllThis, undefined, undefined, promises, undefined); 26 | }; 27 | 28 | Promise.mapSeries = PromiseMapSeries; 29 | }; 30 | 31 | -------------------------------------------------------------------------------- /src/filter.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | module.exports = function(Promise, INTERNAL) { 3 | var PromiseMap = Promise.map; 4 | 5 | Promise.prototype.filter = function (fn, options) { 6 | return PromiseMap(this, fn, options, INTERNAL); 7 | }; 8 | 9 | Promise.filter = function (promises, fn, options) { 10 | return PromiseMap(promises, fn, options, INTERNAL); 11 | }; 12 | }; 13 | -------------------------------------------------------------------------------- /src/method.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | module.exports = 3 | function(Promise, INTERNAL, tryConvertToPromise, apiRejection, debug) { 4 | var util = require("./util"); 5 | var ASSERT = require("./assert"); 6 | var tryCatch = util.tryCatch; 7 | 8 | Promise.method = function (fn) { 9 | if (typeof fn !== "function") { 10 | throw new Promise.TypeError(FUNCTION_ERROR + util.classString(fn)); 11 | } 12 | return function () { 13 | var ret = new Promise(INTERNAL); 14 | ret._captureStackTrace(); 15 | ret._pushContext(); 16 | var value = tryCatch(fn).apply(this, arguments); 17 | var promiseCreated = ret._popContext(); 18 | debug.checkForgottenReturns( 19 | value, promiseCreated, "Promise.method", ret); 20 | ret._resolveFromSyncValue(value); 21 | return ret; 22 | }; 23 | }; 24 | 25 | Promise.attempt = Promise["try"] = function (fn) { 26 | if (typeof fn !== "function") { 27 | return apiRejection(FUNCTION_ERROR + util.classString(fn)); 28 | } 29 | var ret = new Promise(INTERNAL); 30 | ret._captureStackTrace(); 31 | ret._pushContext(); 32 | var value; 33 | if (arguments.length > 1) { 34 | debug.deprecated("calling Promise.try with more than 1 argument"); 35 | var arg = arguments[1]; 36 | var ctx = arguments[2]; 37 | value = util.isArray(arg) ? tryCatch(fn).apply(ctx, arg) 38 | : tryCatch(fn).call(ctx, arg); 39 | } else { 40 | value = tryCatch(fn)(); 41 | } 42 | var promiseCreated = ret._popContext(); 43 | debug.checkForgottenReturns( 44 | value, promiseCreated, "Promise.try", ret); 45 | ret._resolveFromSyncValue(value); 46 | return ret; 47 | }; 48 | 49 | Promise.prototype._resolveFromSyncValue = function (value) { 50 | ASSERT(!this._isFollowing()); 51 | if (value === util.errorObj) { 52 | this._rejectCallback(value.e, false); 53 | } else { 54 | this._resolveCallback(value, true); 55 | } 56 | }; 57 | }; 58 | -------------------------------------------------------------------------------- /src/nodeback.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var util = require("./util"); 3 | var maybeWrapAsError = util.maybeWrapAsError; 4 | var errors = require("./errors"); 5 | var OperationalError = errors.OperationalError; 6 | var es5 = require("./es5"); 7 | 8 | function isUntypedError(obj) { 9 | return obj instanceof Error && 10 | es5.getPrototypeOf(obj) === Error.prototype; 11 | } 12 | 13 | var rErrorKey = /^(?:name|message|stack|cause)$/; 14 | function wrapAsOperationalError(obj) { 15 | var ret; 16 | if (isUntypedError(obj)) { 17 | ret = new OperationalError(obj); 18 | ret.name = obj.name; 19 | ret.message = obj.message; 20 | ret.stack = obj.stack; 21 | var keys = es5.keys(obj); 22 | for (var i = 0; i < keys.length; ++i) { 23 | var key = keys[i]; 24 | if (!rErrorKey.test(key)) { 25 | ret[key] = obj[key]; 26 | } 27 | } 28 | return ret; 29 | } 30 | util.markAsOriginatingFromRejection(obj); 31 | return obj; 32 | } 33 | 34 | function nodebackForPromise(promise, multiArgs) { 35 | return function(err, value) { 36 | if (promise === null) return; 37 | if (err) { 38 | var wrapped = wrapAsOperationalError(maybeWrapAsError(err)); 39 | promise._attachExtraTrace(wrapped); 40 | promise._reject(wrapped); 41 | } else if (!multiArgs) { 42 | promise._fulfill(value); 43 | } else { 44 | INLINE_SLICE(args, arguments, 1); 45 | promise._fulfill(args); 46 | } 47 | promise = null; 48 | }; 49 | } 50 | 51 | module.exports = nodebackForPromise; 52 | -------------------------------------------------------------------------------- /src/nodeify.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | module.exports = function(Promise) { 3 | var util = require("./util"); 4 | var async = Promise._async; 5 | var ASSERT = require("./assert"); 6 | var tryCatch = util.tryCatch; 7 | var errorObj = util.errorObj; 8 | 9 | function spreadAdapter(val, nodeback) { 10 | var promise = this; 11 | if (!util.isArray(val)) return successAdapter.call(promise, val, nodeback); 12 | var ret = 13 | tryCatch(nodeback).apply(promise._boundValue(), [null].concat(val)); 14 | if (ret === errorObj) { 15 | async.throwLater(ret.e); 16 | } 17 | } 18 | 19 | function successAdapter(val, nodeback) { 20 | var promise = this; 21 | var receiver = promise._boundValue(); 22 | ASSERT(typeof nodeback == "function"); 23 | var ret = val === undefined 24 | ? tryCatch(nodeback).call(receiver, null) 25 | : tryCatch(nodeback).call(receiver, null, val); 26 | if (ret === errorObj) { 27 | async.throwLater(ret.e); 28 | } 29 | } 30 | function errorAdapter(reason, nodeback) { 31 | var promise = this; 32 | if (!reason) { 33 | var newReason = new Error(reason + ""); 34 | newReason.cause = reason; 35 | reason = newReason; 36 | ASSERT(!!reason); 37 | } 38 | ASSERT(typeof nodeback == "function"); 39 | var ret = tryCatch(nodeback).call(promise._boundValue(), reason); 40 | if (ret === errorObj) { 41 | async.throwLater(ret.e); 42 | } 43 | } 44 | 45 | Promise.prototype.asCallback = Promise.prototype.nodeify = function (nodeback, 46 | options) { 47 | if (typeof nodeback == "function") { 48 | var adapter = successAdapter; 49 | if (options !== undefined && Object(options).spread) { 50 | adapter = spreadAdapter; 51 | } 52 | this._then( 53 | adapter, 54 | errorAdapter, 55 | undefined, 56 | this, 57 | nodeback 58 | ); 59 | } 60 | return this; 61 | }; 62 | }; 63 | -------------------------------------------------------------------------------- /src/race.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | module.exports = function( 3 | Promise, INTERNAL, tryConvertToPromise, apiRejection) { 4 | var util = require("./util"); 5 | 6 | var raceLater = function (promise) { 7 | return promise.then(function(array) { 8 | return race(array, promise); 9 | }); 10 | }; 11 | 12 | function race(promises, parent) { 13 | var maybePromise = tryConvertToPromise(promises); 14 | 15 | if (maybePromise instanceof Promise) { 16 | return raceLater(maybePromise); 17 | } else { 18 | promises = util.asArray(promises); 19 | if (promises === null) 20 | return apiRejection(COLLECTION_ERROR + util.classString(promises)); 21 | } 22 | 23 | var ret = new Promise(INTERNAL); 24 | if (parent !== undefined) { 25 | ret._propagateFrom(parent, PROPAGATE_ALL); 26 | } 27 | var fulfill = ret._fulfill; 28 | var reject = ret._reject; 29 | for (var i = 0, len = promises.length; i < len; ++i) { 30 | var val = promises[i]; 31 | 32 | if (val === undefined && !(i in promises)) { 33 | continue; 34 | } 35 | 36 | Promise.cast(val)._then(fulfill, reject, undefined, ret, null); 37 | } 38 | //Yes, if promises were empty, it will be forever pending :-) 39 | return ret; 40 | } 41 | 42 | Promise.race = function (promises) { 43 | return race(promises, undefined); 44 | }; 45 | 46 | Promise.prototype.race = function () { 47 | return race(this, undefined); 48 | }; 49 | 50 | }; 51 | -------------------------------------------------------------------------------- /src/settle.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | module.exports = 3 | function(Promise, PromiseArray, debug) { 4 | var ASSERT = require("./assert"); 5 | var PromiseInspection = Promise.PromiseInspection; 6 | var util = require("./util"); 7 | 8 | function SettledPromiseArray(values) { 9 | this.constructor$(values); 10 | } 11 | util.inherits(SettledPromiseArray, PromiseArray); 12 | 13 | SettledPromiseArray.prototype._promiseResolved = function (index, inspection) { 14 | ASSERT(typeof index === "number"); 15 | this._values[index] = inspection; 16 | var totalResolved = ++this._totalResolved; 17 | if (totalResolved >= this._length) { 18 | this._resolve(this._values); 19 | return true; 20 | } 21 | return false; 22 | }; 23 | 24 | //override 25 | SettledPromiseArray.prototype._promiseFulfilled = function (value, index) { 26 | ASSERT(!this._isResolved()); 27 | ASSERT(typeof index === "number"); 28 | var ret = new PromiseInspection(); 29 | ret._bitField = IS_FULFILLED; 30 | ret._settledValueField = value; 31 | return this._promiseResolved(index, ret); 32 | }; 33 | //override 34 | SettledPromiseArray.prototype._promiseRejected = function (reason, index) { 35 | ASSERT(!this._isResolved()); 36 | ASSERT(typeof index === "number"); 37 | var ret = new PromiseInspection(); 38 | ret._bitField = IS_REJECTED; 39 | ret._settledValueField = reason; 40 | return this._promiseResolved(index, ret); 41 | }; 42 | 43 | Promise.settle = function (promises) { 44 | debug.deprecated(".settle()", ".reflect()"); 45 | return new SettledPromiseArray(promises).promise(); 46 | }; 47 | 48 | Promise.allSettled = function (promises) { 49 | return new SettledPromiseArray(promises).promise(); 50 | }; 51 | 52 | Promise.prototype.settle = function () { 53 | return Promise.settle(this); 54 | }; 55 | }; 56 | -------------------------------------------------------------------------------- /test/browser/have_getters.js: -------------------------------------------------------------------------------- 1 | var haveGetters = (function(){ 2 | try { 3 | var o ={}; 4 | 5 | if( Object.__defineGetter__ ) { 6 | o.__defineGetter__( "fn", function(){ 7 | return 3; 8 | }); 9 | return o.fn === 3; 10 | } 11 | else if( Object.defineProperty ) { 12 | Object.defineProperty(o, "fn", {get: function(){return 3}}); 13 | return o.fn === 3; 14 | } 15 | return false; 16 | } 17 | catch(e) { 18 | return false; 19 | } 20 | })(); 21 | -------------------------------------------------------------------------------- /test/browser/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /test/browser/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bluebird-nw", 3 | "version": "1.0.0", 4 | "main": "index.html" 5 | } 6 | -------------------------------------------------------------------------------- /test/browser/promise_debug.js: -------------------------------------------------------------------------------- 1 | var Promise = require("../../js/browser/bluebird.min.js"); 2 | Promise.longStackTraces(); 3 | Promise.config({cancellation:true}); 4 | self.Promise = Promise; 5 | self.adapter = Promise; 6 | -------------------------------------------------------------------------------- /test/browser/promise_instrumented.js: -------------------------------------------------------------------------------- 1 | var Promise = require("../../js/instrumented/bluebird.js"); 2 | window.Promise = Promise; 3 | window.adapter = Promise; 4 | Promise.config({cancellation:true}); 5 | -------------------------------------------------------------------------------- /test/browser/worker.js: -------------------------------------------------------------------------------- 1 | self.importScripts("./worker_bundle.js"); 2 | 3 | var currentPromise; 4 | 5 | function handler(ev) { 6 | ev.preventDefault(); 7 | self.postMessage(ev.type); 8 | if (ev.type === "unhandledrejection") { 9 | currentPromise.catch(function () {}); 10 | } 11 | } 12 | 13 | self.addEventListener("unhandledrejection", handler); 14 | self.addEventListener("rejectionhandled", handler); 15 | 16 | self.onmessage = function onmessage(ev) { 17 | if (ev.data === "reject") { 18 | currentPromise = Promise.reject(new Error("rejected")); 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /test/mocha/2.2.1.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var adapter = global.adapter; 4 | var fulfilled = adapter.fulfilled; 5 | var rejected = adapter.rejected; 6 | 7 | var dummy = { dummy: "dummy" }; // we fulfill or reject with this when we don't intend to test against it 8 | 9 | describe("2.2.1: Both `onFulfilled` and `onRejected` are optional arguments.", function () { 10 | describe("2.2.1.1: If `onFulfilled` is not a function, it must be ignored.", function () { 11 | function testNonFunction(nonFunction, stringRepresentation) { 12 | specify("`onFulfilled` is " + stringRepresentation, function (done) { 13 | rejected(dummy).then(nonFunction, function () { 14 | done(); 15 | }); 16 | }); 17 | } 18 | 19 | testNonFunction(undefined, "`undefined`"); 20 | testNonFunction(null, "`null`"); 21 | testNonFunction(false, "`false`"); 22 | testNonFunction(5, "`5`"); 23 | testNonFunction({}, "an object"); 24 | }); 25 | 26 | describe("2.2.1.2: If `onRejected` is not a function, it must be ignored.", function () { 27 | function testNonFunction(nonFunction, stringRepresentation) { 28 | specify("`onRejected` is " + stringRepresentation, function (done) { 29 | fulfilled(dummy).then(function () { 30 | done(); 31 | }, nonFunction); 32 | }); 33 | } 34 | 35 | testNonFunction(undefined, "`undefined`"); 36 | testNonFunction(null, "`null`"); 37 | testNonFunction(false, "`false`"); 38 | testNonFunction(5, "`5`"); 39 | testNonFunction({}, "an object"); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /test/mocha/2.2.5.js: -------------------------------------------------------------------------------- 1 | /*jshint strict: false */ 2 | 3 | var assert = require("assert"); 4 | 5 | var adapter = global.adapter; 6 | var fulfilled = adapter.fulfilled; 7 | var rejected = adapter.rejected; 8 | 9 | var dummy = { dummy: "dummy" }; // we fulfill or reject with this when we don't intend to test against it 10 | 11 | var undefinedThisStrict = (function() { 12 | "use strict"; 13 | return this; 14 | })(); 15 | 16 | var undefinedThisSloppy = (function() { 17 | return this; 18 | })(); 19 | 20 | describe("2.2.5 `onFulfilled` and `onRejected` must be called as functions (i.e. with no `this` value).", function () { 21 | describe("strict mode", function () { 22 | specify("fulfilled", function (done) { 23 | fulfilled(dummy).then(function onFulfilled() { 24 | "use strict"; 25 | 26 | assert(this === undefinedThisStrict || 27 | this === undefinedThisSloppy); 28 | done(); 29 | }); 30 | }); 31 | 32 | specify("rejected", function (done) { 33 | rejected(dummy).then(null, function onRejected() { 34 | "use strict"; 35 | 36 | assert(this === undefinedThisStrict || 37 | this === undefinedThisSloppy); 38 | done(); 39 | }); 40 | }); 41 | }); 42 | 43 | describe("sloppy mode", function () { 44 | specify("fulfilled", function (done) { 45 | fulfilled(dummy).then(function onFulfilled() { 46 | assert.strictEqual(this, undefinedThisSloppy); 47 | done(); 48 | }); 49 | }); 50 | 51 | specify("rejected", function (done) { 52 | rejected(dummy).then(null, function onRejected() { 53 | assert.strictEqual(this, undefinedThisSloppy); 54 | done(); 55 | }); 56 | }); 57 | }); 58 | }); 59 | -------------------------------------------------------------------------------- /test/mocha/2.3.1.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var assert = require("assert"); 4 | 5 | var adapter = global.adapter; 6 | var fulfilled = adapter.fulfilled; 7 | var rejected = adapter.rejected; 8 | 9 | var dummy = { dummy: "dummy" }; // we fulfill or reject with this when we don't intend to test against it 10 | 11 | describe("2.3.1: If `promise` and `x` refer to the same object, reject `promise` with a `TypeError' as the reason.", 12 | function () { 13 | specify("via return from a fulfilled promise", function (done) { 14 | var promise = fulfilled(dummy).then(function () { 15 | return promise; 16 | }); 17 | 18 | promise.then(null, function (reason) { 19 | assert(reason instanceof adapter.TypeError); 20 | done(); 21 | }); 22 | }); 23 | 24 | specify("via return from a rejected promise", function (done) { 25 | var promise = rejected(dummy).then(null, function () { 26 | return promise; 27 | }); 28 | 29 | promise.then(null, function (reason) { 30 | assert(reason instanceof adapter.TypeError); 31 | done(); 32 | }); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /test/mocha/3.2.1.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var adapter = global.adapter; 4 | var fulfilled = adapter.fulfilled; 5 | var rejected = adapter.rejected; 6 | 7 | var dummy = { dummy: "dummy" }; // we fulfill or reject with this when we don't intend to test against it 8 | 9 | describe("3.2.1: Both `onFulfilled` and `onRejected` are optional arguments.", function () { 10 | describe("3.2.1.1: If `onFulfilled` is not a function, it must be ignored.", function () { 11 | function testNonFunction(nonFunction, stringRepresentation) { 12 | specify("`onFulfilled` is " + stringRepresentation, function (done) { 13 | rejected(dummy).then(nonFunction, function () { 14 | done(); 15 | }); 16 | }); 17 | } 18 | 19 | testNonFunction(undefined, "`undefined`"); 20 | testNonFunction(null, "`null`"); 21 | testNonFunction(false, "`false`"); 22 | testNonFunction(5, "`5`"); 23 | testNonFunction({}, "an object"); 24 | }); 25 | 26 | describe("3.2.1.2: If `onRejected` is not a function, it must be ignored.", function () { 27 | function testNonFunction(nonFunction, stringRepresentation) { 28 | specify("`onRejected` is " + stringRepresentation, function (done) { 29 | fulfilled(dummy).then(function () { 30 | done(); 31 | }, nonFunction); 32 | }); 33 | } 34 | 35 | testNonFunction(undefined, "`undefined`"); 36 | testNonFunction(null, "`null`"); 37 | testNonFunction(false, "`false`"); 38 | testNonFunction(5, "`5`"); 39 | testNonFunction({}, "an object"); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /test/mocha/3.2.4.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var assert = require("assert"); 4 | var testFulfilled = require("./helpers/testThreeCases").testFulfilled; 5 | var testRejected = require("./helpers/testThreeCases").testRejected; 6 | 7 | var dummy = { dummy: "dummy" }; // we fulfill or reject with this when we don't intend to test against it 8 | 9 | describe("3.2.4: `then` must return before `onFulfilled` or `onRejected` is called", function () { 10 | testFulfilled(dummy, function (promise, done) { 11 | var thenHasReturned = false; 12 | 13 | promise.then(function onFulfilled() { 14 | assert(thenHasReturned); 15 | done(); 16 | }); 17 | 18 | thenHasReturned = true; 19 | }); 20 | 21 | testRejected(dummy, function (promise, done) { 22 | var thenHasReturned = false; 23 | 24 | promise.then(null, function onRejected() { 25 | assert(thenHasReturned); 26 | done(); 27 | }); 28 | 29 | thenHasReturned = true; 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /test/mocha/call.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var assert = require("assert"); 4 | var testUtils = require("./helpers/util.js"); 5 | 6 | 7 | var c = { 8 | val: 3, 9 | method: function() { 10 | return [].slice.call(arguments).concat(this.val); 11 | } 12 | }; 13 | 14 | describe("call", function() { 15 | specify("0 args", function() { 16 | return Promise.resolve(c).call("method").then(function(res) { 17 | assert.deepEqual([3], res); 18 | }); 19 | }); 20 | specify("1 args", function() { 21 | return Promise.resolve(c).call("method", 1).then(function(res) { 22 | assert.deepEqual([1, 3], res); 23 | }); 24 | }); 25 | specify("2 args", function() { 26 | return Promise.resolve(c).call("method", 1, 2).then(function(res) { 27 | assert.deepEqual([1, 2, 3], res); 28 | }); 29 | }); 30 | specify("3 args", function() { 31 | return Promise.resolve(c).call("method", 1, 2, 3).then(function(res) { 32 | assert.deepEqual([1, 2, 3, 3], res); 33 | }); 34 | }); 35 | specify("10 args", function() { 36 | return Promise.resolve(c).call("method", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10).then(function(res) { 37 | assert.deepEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 3], res); 38 | }); 39 | }); 40 | specify("method not found", function() { 41 | var promises = [ 42 | Promise.resolve([]).call("abc").then(assert.fail, testUtils.noop), 43 | Promise.resolve([]).call("abc", 1, 2, 3, 4, 5, 6, 7).then(assert.fail, testUtils.noop), 44 | Promise.resolve([]).call("abc ").then(assert.fail, testUtils.noop), 45 | Promise.resolve(null).call("abc", 1, 2, 3, 4, 5, 6, 7).then(assert.fail, testUtils.noop), 46 | Promise.resolve(null).call("abc").then(assert.fail, testUtils.noop), 47 | Promise.resolve(null).call("abc ").then(assert.fail, testUtils.noop) 48 | ]; 49 | 50 | return Promise.all(promises).then(function(errors) { 51 | for (var i = 0; i < errors.length; ++i) { 52 | var message = errors[i].message || errors[i].toString(); 53 | assert(message.indexOf("has no method") >= 0); 54 | } 55 | }); 56 | }); 57 | }); 58 | -------------------------------------------------------------------------------- /test/mocha/getNewLibraryCopy.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var assert = require("assert"); 4 | var testUtils = require("./helpers/util.js"); 5 | 6 | describe("Promise.getNewLibraryCopy", function() { 7 | it("should return an independent copy of Bluebird library", function() { 8 | var Promise2 = Promise.getNewLibraryCopy(); 9 | Promise2.x = 123; 10 | 11 | assert.equal(typeof Promise2.prototype.then, "function"); 12 | assert.notEqual(Promise2, Promise); 13 | 14 | assert.equal(Promise2.x, 123); 15 | assert.notEqual(Promise.x, 123); 16 | }); 17 | it("should return copy of Bluebird library with its own getNewLibraryCopy method", function() { 18 | var Promise2 = Promise.getNewLibraryCopy(); 19 | var Promise3 = Promise2.getNewLibraryCopy(); 20 | Promise3.x = 123; 21 | 22 | assert.equal(typeof Promise3.prototype.then, "function"); 23 | assert.notEqual(Promise3, Promise); 24 | assert.notEqual(Promise3, Promise2); 25 | 26 | assert.equal(Promise3.x, 123); 27 | assert.notEqual(Promise.x, 123); 28 | assert.notEqual(Promise2.x, 123); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /test/mocha/github-2xx-76.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | 4 | Promise.longStackTraces(); 5 | var assert = require("assert"); 6 | var testUtils = require("./helpers/util.js"); 7 | var isNodeJS = testUtils.isNodeJS; 8 | 9 | 10 | if (isNodeJS) { 11 | describe("github276 - stack trace cleaner", function(){ 12 | specify("message with newline and a$_b should not be removed", function(){ 13 | return Promise.resolve(1).then(function() { 14 | throw new Error("Blah\n a$_b"); 15 | }).then(assert.fail, function(e) { 16 | var msg = e.stack.split('\n')[1] 17 | assert(msg.indexOf('a$_b') >= 0, 'message should contain a$_b'); 18 | }); 19 | }); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /test/mocha/github-3.6.4.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var assert = require("assert"); 4 | var Promise = adapter; 5 | 6 | function defer() { 7 | var resolve, reject; 8 | var promise = new Promise(function() { 9 | resolve = arguments[0]; 10 | reject = arguments[1]; 11 | }); 12 | return { 13 | resolve: resolve, 14 | reject: reject, 15 | promise: promise 16 | }; 17 | } 18 | 19 | 20 | describe("github-364", function() { 21 | specify("resolve between thens", function(done) { 22 | var calls = 0; 23 | var def = defer(); 24 | 25 | def.promise.then(function() { 26 | calls++ 27 | }); 28 | def.resolve(); 29 | def.promise.then(function() { 30 | calls++ 31 | }).then(function() { 32 | calls++ 33 | }).then(function() { 34 | Promise.delay(11).then(function() { 35 | assert.equal(calls, 3); 36 | done(); 37 | }); 38 | }); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /test/mocha/github-3.7.3.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var assert = require("assert"); 4 | var testUtils = require("./helpers/util.js"); 5 | var Promise = adapter; 6 | 7 | describe("github-373", function() { 8 | specify("unhandled unsuccessful Promise.join should result in correct error being reported", function() { 9 | var err = new Error("test"); 10 | var rejected = Promise.delay(1).thenThrow(err); 11 | Promise.join(rejected, Promise.resolve(1), function(){}); 12 | return testUtils.onUnhandledSucceed(err); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test/mocha/github-4.1.7.js: -------------------------------------------------------------------------------- 1 | var Promise = adapter; 2 | var assert = require("assert"); 3 | 4 | describe("Github #417", function() { 5 | 6 | specify("minimal repro", function() { 7 | var promise = new Promise(function(resolve) { 8 | resolve(Promise.resolve().then(function() { 9 | return new Promise(function(resolve) { 10 | setTimeout(resolve, 1); 11 | }); 12 | })); 13 | }); 14 | 15 | return promise.then(function() { 16 | assert(promise.isResolved()); 17 | }); 18 | }); 19 | 20 | specify("original repro", function() { 21 | var called = 0; 22 | var bar = Promise.method(function() { 23 | return Promise.bind(this) 24 | .then(Promise.method(function() { 25 | called++; 26 | })); 27 | }); 28 | 29 | var foo = Promise.method(function() { 30 | return Promise.bind(this) 31 | .then(Promise.method(function() { 32 | return bar(); 33 | })) 34 | .bind(this) 35 | .lastly(Promise.method(function() { 36 | called++; 37 | })); 38 | }); 39 | 40 | return foo().then(function() { 41 | called++; 42 | assert.equal(3, called); 43 | }); 44 | }); 45 | }); 46 | 47 | -------------------------------------------------------------------------------- /test/mocha/github36.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var assert = require("assert"); 4 | var testUtils = require("./helpers/util.js"); 5 | 6 | 7 | describe("github36", function(){ 8 | specify("should work", function() { 9 | return new Promise(function(resolve, reject) { 10 | var called = 0; 11 | var donecalled = false; 12 | var _d = Promise.defer(); 13 | 14 | _d.resolve() 15 | 16 | var f1 = function() { 17 | return _d.promise.then(function() { 18 | return true; 19 | }) 20 | } 21 | 22 | var f2 = function() { 23 | var d1 = Promise.defer() 24 | 25 | setTimeout(function() { 26 | d1.resolve() 27 | }, 1) 28 | 29 | return d1.promise.then(function() { 30 | return _d.promise.then(function() { 31 | }) 32 | }); 33 | } 34 | 35 | var f3 = function() { 36 | called++; 37 | if (called > 15) { 38 | return resolve(); 39 | } 40 | var promise = f1().then(function() { 41 | f2() 42 | .then(function() { 43 | f3() 44 | }) 45 | }) 46 | 47 | promise.lastly(function() { 48 | setTimeout(function() { 49 | f3() 50 | }, 1) 51 | }) 52 | 53 | } 54 | 55 | f3(); 56 | }); 57 | }); 58 | }); 59 | 60 | -------------------------------------------------------------------------------- /test/mocha/helpers/error.js: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /test/mocha/helpers/reasons.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | // This module exports some valid rejection reason factories, keyed by human-readable versions of their names. 4 | 5 | var adapter = global.adapter; 6 | var fulfilled = adapter.fulfilled; 7 | var rejected = adapter.rejected; 8 | 9 | var dummy = { dummy: "dummy" }; 10 | 11 | exports["`undefined`"] = function () { 12 | return undefined; 13 | }; 14 | 15 | exports["`null`"] = function () { 16 | return null; 17 | }; 18 | 19 | exports["`false`"] = function () { 20 | return false; 21 | }; 22 | 23 | exports["`0`"] = function () { 24 | return 0; 25 | }; 26 | 27 | exports["an error"] = function () { 28 | return new Error(); 29 | }; 30 | 31 | exports["an error without a stack"] = function () { 32 | var error = new Error(); 33 | delete error.stack; 34 | 35 | return error; 36 | }; 37 | 38 | exports["a date"] = function () { 39 | return new Date(); 40 | }; 41 | 42 | exports["an object"] = function () { 43 | return {}; 44 | }; 45 | 46 | exports["an always-pending thenable"] = function () { 47 | return { then: function () { } }; 48 | }; 49 | 50 | exports["a fulfilled promise"] = function () { 51 | return fulfilled(dummy); 52 | }; 53 | 54 | exports["a rejected promise"] = function () { 55 | return rejected(dummy); 56 | }; 57 | -------------------------------------------------------------------------------- /test/mocha/helpers/testThreeCases.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var adapter = global.adapter; 4 | var fulfilled = adapter.fulfilled; 5 | var rejected = adapter.rejected; 6 | var pending = adapter.pending; 7 | 8 | function success(done) { 9 | return function() { 10 | done(); 11 | }; 12 | } 13 | 14 | function fail(done) { 15 | return function(err) { 16 | done(err); 17 | }; 18 | } 19 | 20 | function handlePromise(val, done) { 21 | if (val && typeof val.then === "function") { 22 | val.then(success(done), fail(done)); 23 | } 24 | } 25 | 26 | exports.testFulfilled = function (value, test) { 27 | specify("already-fulfilled", function (done) { 28 | handlePromise(test(fulfilled(value), done), done); 29 | }); 30 | 31 | specify("immediately-fulfilled", function (done) { 32 | var tuple = pending(); 33 | handlePromise(test(tuple.promise, done), done); 34 | tuple.fulfill(value); 35 | }); 36 | 37 | specify("eventually-fulfilled", function (done) { 38 | var tuple = pending(); 39 | handlePromise(test(tuple.promise, done), done); 40 | setTimeout(function () { 41 | tuple.fulfill(value); 42 | }, 1); 43 | }); 44 | }; 45 | 46 | exports.testRejected = function (reason, test) { 47 | specify("already-rejected", function (done) { 48 | handlePromise(test(rejected(reason), done), done); 49 | }); 50 | 51 | specify("immediately-rejected", function (done) { 52 | var tuple = pending(); 53 | handlePromise(test(tuple.promise, done), done); 54 | tuple.reject(reason); 55 | }); 56 | 57 | specify("eventually-rejected", function (done) { 58 | var tuple = pending(); 59 | handlePromise(test(tuple.promise, done), done); 60 | setTimeout(function () { 61 | tuple.reject(reason); 62 | }, 1); 63 | }); 64 | }; 65 | -------------------------------------------------------------------------------- /test/mocha/is.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var assert = require("assert"); 4 | var testUtils = require("./helpers/util.js"); 5 | 6 | describe("Promise.is", function() { 7 | it("should return true for trusted promise", function() { 8 | assert.strictEqual(Promise.is(new Promise(function(){})), true); 9 | }); 10 | it("should return false for untrusted promise", function() { 11 | assert.strictEqual(Promise.is({ 12 | then: function() {} 13 | }), false); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/mocha/late_buffer_safety.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var assert = require("assert"); 4 | var testUtils = require("./helpers/util.js"); 5 | var isNodeJS = testUtils.isNodeJS; 6 | 7 | function async(cb){ 8 | return Promise.resolve().nodeify(cb); 9 | } 10 | 11 | if (isNodeJS) { 12 | describe("Late buffer", function() { 13 | specify("shouldn't stop at first error but continue consumption until everything is consumed", function(){ 14 | var length = 10; 15 | var l = length; 16 | var a = 0; 17 | while (l--){ 18 | async(function(){ 19 | throw (a++); 20 | }); 21 | } 22 | var errs = []; 23 | return testUtils.awaitGlobalException(function(e) { 24 | errs.push(e); 25 | if (errs.length === length) { 26 | var a = []; 27 | for (var i = 0, len = length; i < len; ++i) { 28 | a[i] = i; 29 | } 30 | assert.deepEqual(a, errs); 31 | } else { 32 | return false; 33 | } 34 | }); 35 | }); 36 | }); 37 | } 38 | -------------------------------------------------------------------------------- /test/mocha/multiple-copies.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var assert = require("assert"); 4 | var testUtils = require("./helpers/util.js"); 5 | 6 | if (testUtils.isNodeJS) { 7 | describe("multiple copies", function() { 8 | specify("are being loaded", function() { 9 | var a = require("../../js/debug/bluebird.js"); 10 | Object.keys(require.cache).forEach(function(key) { 11 | if (/debug/.test(key)) 12 | delete require.cache[key]; 13 | }); 14 | var b = require("../../js/debug/bluebird.js"); 15 | assert.notEqual(a, b); 16 | }); 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /test/mocha/no_conflict.js: -------------------------------------------------------------------------------- 1 | var assert = require("assert"); 2 | var testUtils = require("./helpers/util.js"); 3 | 4 | describe("Promise.noConflict", function() { 5 | specify("should work", function() { 6 | var glob = typeof window !== "undefined" ? window : global; 7 | var bluebird = Promise.noConflict(); 8 | assert(bluebird !== Promise); 9 | glob.Promise = null; 10 | assert.strictEqual(bluebird, bluebird.noConflict()); 11 | try { 12 | delete glob.Promise; 13 | assert.strictEqual(bluebird, bluebird.noConflict()); 14 | } catch (e) { 15 | assert.strictEqual(bluebird, bluebird.noConflict()); 16 | } 17 | glob.Promise = bluebird; 18 | assert.strictEqual(bluebird, Promise.noConflict()); 19 | glob.Promise = bluebird; 20 | }) 21 | }); 22 | -------------------------------------------------------------------------------- /test/mocha/reflect.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var assert = require("assert"); 4 | var testUtils = require("./helpers/util.js"); 5 | var testFulfilled = require("./helpers/testThreeCases").testFulfilled; 6 | var testRejected = require("./helpers/testThreeCases").testRejected; 7 | 8 | describe(".reflect()", function() { 9 | testFulfilled(1, function(promise) { 10 | return promise.reflect().then(function(inspection) { 11 | assert(inspection instanceof Promise.PromiseInspection); 12 | assert(inspection.isFulfilled()); 13 | assert(inspection.value() === 1); 14 | }); 15 | }); 16 | testRejected(2, function(promise) { 17 | return promise.reflect().then(function(inspection) { 18 | assert(inspection instanceof Promise.PromiseInspection); 19 | assert(inspection.isRejected()); 20 | assert(inspection.reason() === 2); 21 | }); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /test/mocha/schedule.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var assert = require("assert"); 3 | var testUtils = require("./helpers/util.js"); 4 | var schedule = require("../../js/debug/schedule"); 5 | var isNodeJS = testUtils.isNodeJS; 6 | 7 | describe("schedule", function () { 8 | if (isNodeJS) { 9 | describe("for Node.js", function () { 10 | it("should preserve the active domain", function() { 11 | var domain = require("domain"); 12 | var activeDomain = domain.create(); 13 | return new Promise(function(resolve) { 14 | activeDomain.run(function () { 15 | schedule(function () { 16 | assert(domain.active); 17 | assert.equal(domain.active, activeDomain); 18 | resolve(); 19 | }); 20 | }); 21 | }); 22 | 23 | }); 24 | }); 25 | 26 | describe("Promise.setScheduler", function() { 27 | it("should work with synchronous scheduler", function() { 28 | var prev = Promise.setScheduler(function(task) { 29 | task(); 30 | }); 31 | var success = false; 32 | Promise.resolve().then(function() { 33 | success = true; 34 | }); 35 | assert(success); 36 | Promise.setScheduler(prev); 37 | }); 38 | it("should throw for non function", function() { 39 | try { 40 | Promise.setScheduler({}); 41 | } catch (e) { 42 | return Promise.resolve(); 43 | } 44 | assert.fail(); 45 | }); 46 | }); 47 | } 48 | }); 49 | -------------------------------------------------------------------------------- /test/mocha/tap.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var assert = require("assert"); 3 | var testUtils = require("./helpers/util.js"); 4 | 5 | 6 | describe("tap", function () { 7 | specify("passes through value", function() { 8 | return Promise.resolve("test").tap(function() { 9 | return 3; 10 | }).then(function(value){ 11 | assert.equal(value, "test"); 12 | }); 13 | }); 14 | 15 | specify("passes through value after returned promise is fulfilled", function() { 16 | var async = false; 17 | return Promise.resolve("test").tap(function() { 18 | return new Promise(function(r) { 19 | setTimeout(function(){ 20 | async = true; 21 | r(3); 22 | }, 1); 23 | }); 24 | }).then(function(value){ 25 | assert(async); 26 | assert.equal(value, "test"); 27 | }); 28 | }); 29 | 30 | specify("is not called on rejected promise", function() { 31 | var called = false; 32 | return Promise.reject("test").tap(function() { 33 | called = true; 34 | }).then(assert.fail, function(value){ 35 | assert(!called); 36 | }); 37 | }); 38 | 39 | specify("passes immediate rejection", function() { 40 | var err = new Error(); 41 | return Promise.resolve("test").tap(function() { 42 | throw err; 43 | }).tap(assert.fail).then(assert.fail, function(e){ 44 | assert(err === e); 45 | }); 46 | }); 47 | 48 | specify("passes eventual rejection", function() { 49 | var err = new Error(); 50 | return Promise.resolve("test").tap(function() { 51 | return new Promise(function(_, rej) { 52 | setTimeout(function(){ 53 | rej(err); 54 | }, 1) 55 | }); 56 | }).tap(assert.fail).then(assert.fail, function(e) { 57 | assert(err === e); 58 | }); 59 | }); 60 | 61 | specify("passes value", function() { 62 | return Promise.resolve(123).tap(function(a) { 63 | assert(a === 123); 64 | }); 65 | }); 66 | }); 67 | -------------------------------------------------------------------------------- /test/mocha/try.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var assert = require("assert"); 4 | var testUtils = require("./helpers/util.js"); 5 | 6 | var obj = {}; 7 | var error = new Error(); 8 | var thrower = function() { 9 | throw error; 10 | }; 11 | 12 | var identity = function(val) { 13 | return val; 14 | }; 15 | 16 | var array = function() { 17 | return [].slice.call(arguments); 18 | }; 19 | 20 | var receiver = function() { 21 | return this; 22 | }; 23 | 24 | var tryy = Promise["try"]; 25 | 26 | describe("Promise.attempt", function(){ 27 | specify("should reject when the function throws", function() { 28 | var async = false; 29 | var ret = tryy(thrower).then(assert.fail, function(e) { 30 | assert(async); 31 | assert(e === error); 32 | }); 33 | async = true; 34 | return ret; 35 | }); 36 | 37 | specify("should reject when the function is not a function", function() { 38 | var async = false; 39 | var ret = tryy(null).then(assert.fail, function(e) { 40 | assert(async); 41 | assert(e instanceof Promise.TypeError); 42 | }); 43 | async = true; 44 | return ret; 45 | }); 46 | 47 | specify("should unwrap returned promise", function(){ 48 | var d = Promise.defer(); 49 | 50 | var ret = tryy(function(){ 51 | return d.promise; 52 | }).then(function(v){ 53 | assert(v === 3); 54 | }) 55 | 56 | setTimeout(function(){ 57 | d.fulfill(3); 58 | }, 1); 59 | return ret; 60 | }); 61 | specify("should unwrap returned thenable", function(){ 62 | return tryy(function(){ 63 | return { 64 | then: function(f, v) { 65 | f(3); 66 | } 67 | } 68 | }).then(function(v){ 69 | assert(v === 3); 70 | }); 71 | 72 | }); 73 | }); 74 | -------------------------------------------------------------------------------- /tests: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | node tools/test.js "$@" 3 | -------------------------------------------------------------------------------- /tools/README.md: -------------------------------------------------------------------------------- 1 | ## Tools 2 | 3 | Tools that can be run from command line: 4 | 5 | ### test.js 6 | 7 | For running tests. See [Testing](../#testing). 8 | 9 | ### build.js 10 | 11 | For building the library. See [Custom builds](../#custom-builds). 12 | 13 | ### jshintrc_generator.js 14 | 15 | Generates a .jshintrc file in the project root. 16 | 17 | Example: 18 | 19 | node tools/jshintrc_generator 20 | -------------------------------------------------------------------------------- /tools/jshint.js: -------------------------------------------------------------------------------- 1 | var utils = require("./utils.js"); 2 | var path = require("path"); 3 | 4 | module.exports = function() { 5 | var wd = path.join(__dirname, ".."); 6 | return utils.run("node_modules/jshint/bin/jshint", [ 7 | "--verbose", 8 | "--reporter", 9 | "node_modules/jshint-stylish/stylish.js", 10 | "src/" 11 | ], wd); 12 | }; 13 | function log(value) { 14 | process.stdout.write(value.stdout); 15 | process.stderr.write(value.stderr); 16 | } 17 | if (require.main === module) { 18 | module.exports().then(log, log); 19 | } 20 | 21 | -------------------------------------------------------------------------------- /tools/jshintrc_generator.js: -------------------------------------------------------------------------------- 1 | var assert = require("assert"); 2 | assert.equal(require.main, module); 3 | // Since many globals are dynamic, this file is needed to generate jshintrc dynamically 4 | var Promise = require("bluebird"); 5 | var path = require("path"); 6 | Promise.longStackTraces(); 7 | var fs = Promise.promisifyAll(require("fs")); 8 | 9 | var constantsFile = path.join(__dirname, "..", "src", "constants.js"); 10 | var globals = fs.readFileAsync(constantsFile, "utf8").then(function(contents) { 11 | var rconstantname = /CONSTANT\(\s*([^,]+)/g; 12 | var m; 13 | var globals = { 14 | Symbol: false, 15 | Map: false, 16 | JSON: false, 17 | Error: true, 18 | args: true, 19 | chrome: true, 20 | INLINE_SLICE: false, 21 | INLINE_SLICE_LEFT_PADDED: false, 22 | BIT_FIELD_CHECK: false, 23 | BIT_FIELD_READ: false, 24 | USE: false, 25 | global: true, 26 | setImmediate: true, 27 | Promise: true, 28 | WebKitMutationObserver: true, 29 | TypeError: true, 30 | RangeError: true, 31 | __DEBUG__: false, 32 | __BROWSER__: false, 33 | process: true, 34 | self: true, 35 | "console": false, 36 | "require": false, 37 | "module": false, 38 | "define": false 39 | }; 40 | while((m = rconstantname.exec(contents))) { 41 | globals[m[1]] = false; 42 | } 43 | return globals; 44 | }); 45 | 46 | var jshintrcFile = path.join(__dirname, "..", ".jshintrc"); 47 | var jshintrc = fs.readFileAsync(jshintrcFile, "utf8").then(JSON.parse); 48 | 49 | Promise.join(jshintrc, globals, function(jshintrc, globals) { 50 | jshintrc.globals = globals; 51 | var json = JSON.stringify(jshintrc, null, " "); 52 | return fs.writeFileAsync(jshintrcFile, json); 53 | }); 54 | --------------------------------------------------------------------------------