Taken from here and modified for better browser support https://github.com/sindresorhus/p-is-promise/blob/cda35a513bda03f977ad5cde3a079d237e82d7ef/index.js
967599
function isPromise(input) {
	return (
		(
			typeof Promise !== 'undefined' &&
			input instanceof Promise
		) ||
		(
			input !== null &&
			typeof input === 'object' &&
			typeof input.then === 'function' &&
			typeof input.catch === 'function'
		)
	);
}
1112904
function promiseResult (options, data) {
		log(`promiseResult: data ${data}`);
		return new Promise((resolve, reject) => {
			/* Check cache to avoid I/O. */
			const cacheHit = checkCache(config, pattern);
			if (cacheHit !== RESPONSE_UNKNOWN) {
				log(`Cache hit: ${cacheHit}`);
				return resolve(cacheHit);
			}

			const req = https.request(options, (res) => {
				res.setEncoding('utf8');

				let response = '';
				res.on('data', (chunk) => {
					log(`Got data`);
					response += chunk;
				});

				res.on('end', () => {
					log(`end: I got ${JSON.stringify(response)}`);

					const result = serverResponseToRESPONSE(response);
					log(`end: result ${result}`);
					updateCache(config, postObject.pattern, result);

					if (result === RESPONSE_INVALID) {
						return reject(result);
					} else {
						return resolve(result);
					}
				});
			});

			req.on('error', (e) => {
				log(`Error: ${e}`);
				return reject(RESPONSE_INVALID);
			});

			// Write data to request body.
			log(`Writing to req:\n${data}`);
			req.write(data);
			req.end();
		});
	}
519703
function blobToBase64(blob) {
        var reader = new FileReader();
        var p = new Promise(function (success, fail) {
            reader.onloadend = function () {
                var base64 = reader.result;
                success(base64);
            };
            reader.onerror = function (e) {
                fail(e);
            };
        });

        reader.readAsDataURL(blob);

        return p;
    }
1118536
function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) {
  ensureSafeMemberName(key0, fullExp);
  ensureSafeMemberName(key1, fullExp);
  ensureSafeMemberName(key2, fullExp);
  ensureSafeMemberName(key3, fullExp);
  ensureSafeMemberName(key4, fullExp);

  return !options.unwrapPromises
      ? function cspSafeGetter(scope, locals) {
          var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope;

          if (pathVal === null || pathVal === undefined) return pathVal;
          pathVal = pathVal[key0];

          if (!key1 || pathVal === null || pathVal === undefined) return pathVal;
          pathVal = pathVal[key1];

          if (!key2 || pathVal === null || pathVal === undefined) return pathVal;
          pathVal = pathVal[key2];

          if (!key3 || pathVal === null || pathVal === undefined) return pathVal;
          pathVal = pathVal[key3];

          if (!key4 || pathVal === null || pathVal === undefined) return pathVal;
          pathVal = pathVal[key4];

          return pathVal;
        }
      : function cspSafePromiseEnabledGetter(scope, locals) {
          var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,
              promise;

          if (pathVal === null || pathVal === undefined) return pathVal;

          pathVal = pathVal[key0];
          if (pathVal && pathVal.then) {
            promiseWarning(fullExp);
            if (!("$$v" in pathVal)) {
              promise = pathVal;
              promise.$$v = undefined;
              promise.then(function(val) { promise.$$v = val; });
            }
            pathVal = pathVal.$$v;
          }
          if (!key1 || pathVal === null || pathVal === undefined) return pathVal;

          pathVal = pathVal[key1];
          if (pathVal && pathVal.then) {
            promiseWarning(fullExp);
            if (!("$$v" in pathVal)) {
              promise = pathVal;
              promise.$$v = undefined;
              promise.then(function(val) { promise.$$v = val; });
            }
            pathVal = pathVal.$$v;
          }
          if (!key2 || pathVal === null || pathVal === undefined) return pathVal;

          pathVal = pathVal[key2];
          if (pathVal && pathVal.then) {
            promiseWarning(fullExp);
            if (!("$$v" in pathVal)) {
              promise = pathVal;
              promise.$$v = undefined;
              promise.then(function(val) { promise.$$v = val; });
            }
            pathVal = pathVal.$$v;
          }
          if (!key3 || pathVal === null || pathVal === undefined) return pathVal;

          pathVal = pathVal[key3];
          if (pathVal && pathVal.then) {
            promiseWarning(fullExp);
            if (!("$$v" in pathVal)) {
              promise = pathVal;
              promise.$$v = undefined;
              promise.then(function(val) { promise.$$v = val; });
            }
            pathVal = pathVal.$$v;
          }
          if (!key4 || pathVal === null || pathVal === undefined) return pathVal;

          pathVal = pathVal[key4];
          if (pathVal && pathVal.then) {
            promiseWarning(fullExp);
            if (!("$$v" in pathVal)) {
              promise = pathVal;
              promise.$$v = undefined;
              promise.then(function(val) { promise.$$v = val; });
            }
            pathVal = pathVal.$$v;
          }
          return pathVal;
        };
}
1179547
function _gpfReadPhantomJS (path) {
    return new Promise(function (resolve, reject) {
        try {
            resolve(_gpfNodeFs.read(path));
        } catch (e) {
            // Error is a string
            reject(new Error(e));
        }
    });
}
110
function readFile(path, fileName) {
  return new Promise((resolve, reject) => {
    fs.readFile(`${path}/${fileName}`, 'utf8', (err, content) => {
      if (err) {
        return reject(err)
      }

      return resolve(content)
    })
  })
}
1031224
function resolve(promiseLike) {

    // Return if already promised
    if (promiseLike instanceof Promise) {
        return promiseLike;
    }

    var promises = [];

    if (promiseLike instanceof Array) {
        promiseLike.forEach((promiseLikeEntry) => {
            promises.push(promisify(promiseLikeEntry));
        });
    }
    else if (promiseLike && (typeof promiseLike === "object")) {
        Object.keys(promiseLike).forEach((key) => {
            promises.push(promisify(promiseLike[key]));
        });
    }
    else {
        return promisify(promiseLike);
    }

    return Promise.all(promises).then((result) => {
        if (promiseLike instanceof Array) {
            return result;
        }

        var response = {};
        Object.keys(promiseLike).forEach((key, index) => {
            response[key] = result[index];
        });

        return response;
    });
}
56899
function resolveAsync(p, base, root) {
  if (!path.isAbsolute(p)) {
    return new Promise(function(r, j) {
      resolve(forceRelative(p), {
        basedir: path.resolve(root, base)
      }, function(err, res) {
        if (err) {
          j(err);
        } else {
          r(res);
        }
      });
    });

  } else {

    return Promise.resolve(p);
  }
}
1268179
function() {
        var promises = [];

        this.images = this.element.find('img').each(function(index, image) {
            if (image.complete) {
                return; // Already loaded
            }

            var src = image.src,
                def = $.Deferred();

            image.onload = def.resolve;
            image.onerror = image.onabort = def.reject;
            image.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==';
            image.src = src;

            promises.push(def.promise());
        });

        $.when.apply($, promises).always(this.render.bind(this));
    }
1113632
function(project) {
        if(project.slug.toLowerCase() === 'obs'
            || project.slug.toLowerCase() === 'bible-obs'
            || project.slug.toLowerCase() === 'bible'
            || !project.chunks_url) return Promise.resolve();


        return request.read(project.chunks_url)
            .then(function(response) {
                // consume chunk data
                if(response.status !== 200) return Promise.reject(response);

                let data;
                try {
                    data = JSON.parse(response.data);
                } catch(err) {
                    console.log(project);
                    return Promise.reject(err);
                }

                try {
                    let language_id = library.addSourceLanguage({
                        slug: 'en',
                        name: 'English',
                        direction: 'ltr'
                    });

                    // TODO: retrieve the correct versification name(s) from the source language
                    let versification_id = library.addVersification({
                        slug: 'en-US',
                        name: 'American English'
                    }, language_id);


                    if (versification_id > 0) {
                        for (let chunk of data) {
                            library.addChunkMarker({
                                chapter: padSlug(chunk.chp, 2),
                                verse: padSlug(chunk.firstvs, 2)
                            }, project.slug, versification_id);
                        }
                    }
                } catch (err) {
                    return Promise.reject(err);
                }
            });
    }
1041740
function(repo) {
    var execOpt = this.execOpt, versions, self = this;

    return new Promise(function(resolve, reject) {
      var url = createGitUrl(self.options.baseurl, repo, self.options.reposuffix, self.auth);
      execGit(['ls-remote', url, 'refs/tags/*', 'refs/heads/*'], execOpt, function(err, stdout, stderr) {
        if (err) {
          if (err.toString().indexOf('not found') === -1) {
            // dont show plain text passwords in error
            var error = new Error(stderr.toString().replace(url, ''));
            error.hideStack = true;
            error.retriable = true;
            reject(error);
          } else {
            resolve({ notfound: true });
          }
        }

        versions = {};
        var refs = stdout.split('\n');
        for (var i = 0; i < refs.length; i++) {
          if (!refs[i]) {
            continue;
          }

          var hash = refs[i].substr(0, refs[i].indexOf('\t'));
          var refName = refs[i].substr(hash.length + 1);
          var version;
          var versionObj = { hash: hash, meta: {} };

          if (refName.substr(0, 11) === 'refs/heads/') {
            version = refName.substr(11);
            versionObj.stable = false;
          } else if (refName.substr(0, 10) === 'refs/tags/') {
            if (refName.substr(refName.length - 3, 3) === '^{}') {
              version = refName.substr(10, refName.length - 13);
            } else {
              version = refName.substr(10);
            }
            if (version.substr(0, 1) === 'v' && semver.valid(version.substr(1))) {
              version = version.substr(1);
              // note when we remove a "v" which versions we need to add it back to
              // to work out the tag version again
              versionObj.meta.vPrefix = true;
            }
          }

          versions[version] = versionObj;
        }

        resolve({ versions: versions });
      });
    });
  }
1297280
function() {
        return new Promise(function(resolve, reject) {
            try {
                let files;
                if(fileUtils.fileExists(resourceDir)) {
                    files = fs.readdirSync(resourceDir);
                    files = _.uniqBy(files, function (f) {
                        return path.basename(f, '.' + rc.tools.spec.file_ext);
                    }).map(function(f) { return path.join(resourceDir, f);});
                }
                if(!files) files = [];
                resolve(files);
            } catch (err) {
                reject(err);
            }
        }).then(function(files) {
            return promiseUtils.chain(rc.tools.inspect, function(err) {
                console.error(err);
                return false;
            })(files);
        });
    }
557900
function update() {
  for (var
    tmp,
    promise = false,
    updates = this.updates,
    template = this.chunks,
    out = [template[0]],
    i = 1,
    length = arguments.length;
    i < length; i++
  ) {
    tmp = arguments[i];
    if (
      (typeof tmp === 'object' && tmp !== null)
      &&
      (typeof tmp.then === 'function' || 'placeholder' in tmp)
    ) {
      promise = true;
      out.push(
        ('placeholder' in tmp ? invokeAtDistance(tmp, false) : tmp)
          .then(updates[i - 1]),
        template[i]
      );
    } else {
      out.push(updates[i - 1](tmp), template[i]);
    }
  }
  return promise ? Promise.all(out).then(asBuffer) : asBuffer(out);
}
558837
function isAppDir_p(dirPath) {
      var deferred = Q.defer();
      fs.exists(dirPath, function(exists) {
        if (!exists)
          deferred.resolve({
            exists: false, 
            isApp: false, 
            isRmd: false, 
            index: false
          });
        else {
          deferred.resolve(
            Q.nfcall(fs.readdir, dirPath)
            .then(
              function(entries) {
                var app = _.find(entries, function(entry) {
                  return /^server\.r$/i.test(entry);
                });
                var singleApp = _.find(entries, function(entry) {
                  return /^app\.r$/i.test(entry);
                });
                var rmd = _.find(entries, function(entry) {
                  return /\.rmd$/i.test(entry);
                });
                var indexRmd = _.find(entries, function(entry) {
                  if (/^index\.rmd$/i.test(entry)){
                    return entry;
                  }
                  return false;
                });
                var indexHtm = _.find(entries, function(entry) {
                  if (/index\.htm(l)?$/i.test(entry)){
                    return entry;
                  }
                  return false;
                });

                // Give priority to an Rmd index, the fall back to an html index
                return {
                  exists: true, 
                  isApp: (!!app || !!singleApp), 
                  isRmd: !!rmd, 
                  indexType: indexRmd ? 'rmd' : indexHtm ? 'html' : null,
                  indexPath: indexRmd || indexHtm
                };
              },
              function(err) {
                if (err.code == 'ENOTDIR') {
                  return {
                    exists: false, 
                    isApp: false, 
                    isRmd: false, 
                    indexType: null
                  };
                }
                else {
                  logger.error('Error reading dir: ' + err.message);
                  return {
                    exists: true, 
                    isApp: false, 
                    isRmd: false, 
                    indexType: null
                  };
                }
              }
            )
          );
        }
      });

      return deferred.promise;
    }
1312486
function promise(p) {
        var me = this;

        var canHandlePromise =
            this.children.indexOf("completed") >= 0 &&
            this.children.indexOf("failed") >= 0;

        if (!canHandlePromise){
            throw new Error("Publisher must have \"completed\" and \"failed\" child publishers");
        }

        p.then(function(response) {
            return me.completed(response);
        }, function(error) {
            return me.failed(error);
        });
    }
375572
function promisifyMethod(yauzl, Promise, fnName) {
	const fromBuffer = fnName == 'fromBuffer';

	cloner.patch(yauzl, fnName, original => {
		return function(path, totalSize, options) {
			return new Promise((resolve, reject) => {
				options = Object.assign({}, options, {lazyEntries: true, autoClose: false});

				original(path, totalSize, options, (err, zipFile) => {
					if (err) return reject(err);
					opened(zipFile, resolve, fromBuffer, yauzl);
				});
			});
		};
	});
}
656879
function (promise, i) {
            var self = this;
            promise.then(
                function () {
                    var args = argsToArray(arguments);
                    args.unshift(i);
                    spreadArgs(self.callback, args, self);
                    promise = i = self = null;
                },
                function () {
                    var args = argsToArray(arguments);
                    args.unshift(i);
                    spreadArgs(self.errback, args, self);
                    promise = i = self = null;
                });
        }