Commit 6743175a authored by alexpott's avatar alexpott

Issue #2442411 by jhedstrom: Update react/promise to 2.2.0

parent 0b5587bf
......@@ -1390,16 +1390,16 @@
},
{
"name": "react/promise",
"version": "v2.1.0",
"version": "v2.2.0",
"source": {
"type": "git",
"url": "https://github.com/reactphp/promise.git",
"reference": "937b04f1b0ee8f6d180e75a0830aac778ca4bcd6"
"reference": "365fcee430dfa4ace1fbc75737ca60ceea7eeeef"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/reactphp/promise/zipball/937b04f1b0ee8f6d180e75a0830aac778ca4bcd6",
"reference": "937b04f1b0ee8f6d180e75a0830aac778ca4bcd6",
"url": "https://api.github.com/repos/reactphp/promise/zipball/365fcee430dfa4ace1fbc75737ca60ceea7eeeef",
"reference": "365fcee430dfa4ace1fbc75737ca60ceea7eeeef",
"shasum": ""
},
"require": {
......@@ -1416,7 +1416,7 @@
"React\\Promise\\": "src/"
},
"files": [
"src/functions.php"
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
......@@ -1430,7 +1430,7 @@
}
],
"description": "A lightweight implementation of CommonJS Promises/A for PHP",
"time": "2014-10-15 20:05:57"
"time": "2014-12-30 13:32:42"
},
{
"name": "sdboyer/gliph",
......
......@@ -6,6 +6,6 @@
$baseDir = dirname($vendorDir);
return array(
$vendorDir . '/react/promise/src/functions.php',
$vendorDir . '/react/promise/src/functions_include.php',
$baseDir . '/lib/Drupal.php',
);
......@@ -329,52 +329,6 @@
"parser"
]
},
{
"name": "react/promise",
"version": "v2.1.0",
"version_normalized": "2.1.0.0",
"source": {
"type": "git",
"url": "https://github.com/reactphp/promise.git",
"reference": "937b04f1b0ee8f6d180e75a0830aac778ca4bcd6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/reactphp/promise/zipball/937b04f1b0ee8f6d180e75a0830aac778ca4bcd6",
"reference": "937b04f1b0ee8f6d180e75a0830aac778ca4bcd6",
"shasum": ""
},
"require": {
"php": ">=5.4.0"
},
"time": "2014-10-15 20:05:57",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"React\\Promise\\": "src/"
},
"files": [
"src/functions.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jan Sorgalla",
"email": "jsorgalla@googlemail.com"
}
],
"description": "A lightweight implementation of CommonJS Promises/A for PHP"
},
{
"name": "guzzlehttp/streams",
"version": "3.0.0",
......@@ -3066,5 +3020,51 @@
"keywords": [
"scraper"
]
},
{
"name": "react/promise",
"version": "v2.2.0",
"version_normalized": "2.2.0.0",
"source": {
"type": "git",
"url": "https://github.com/reactphp/promise.git",
"reference": "365fcee430dfa4ace1fbc75737ca60ceea7eeeef"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/reactphp/promise/zipball/365fcee430dfa4ace1fbc75737ca60ceea7eeeef",
"reference": "365fcee430dfa4ace1fbc75737ca60ceea7eeeef",
"shasum": ""
},
"require": {
"php": ">=5.4.0"
},
"time": "2014-12-30 13:32:42",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"React\\Promise\\": "src/"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jan Sorgalla",
"email": "jsorgalla@googlemail.com"
}
],
"description": "A lightweight implementation of CommonJS Promises/A for PHP"
}
]
CHANGELOG
=========
* 2.2.0 (2014-12-30)
* Introduce new ExtendedPromiseInterface implemented by all promises
* Add new .done() method (part of the ExtendedPromiseInterface)
* Add new .otherwise() method (part of the ExtendedPromiseInterface)
* Add new .always() method (part of the ExtendedPromiseInterface)
* Add new .progress() method (part of the ExtendedPromiseInterface)
* Rename Deferred::progress to Deferred::notify to avoid confusion with
ExtendedPromiseInterface::progress (a Deferred::progress alias is still
available for backward compatibility)
* resolve() now always returns a ExtendedPromiseInterface
* 2.1.0 (2014-10-15)
* Introduce new CancellablePromiseInterface implemented by all promises
......
This diff is collapsed.
......@@ -12,7 +12,7 @@
"psr-4": {
"React\\Promise\\": "src/"
},
"files": ["src/functions.php"]
"files": ["src/functions_include.php"]
},
"extra": {
"branch-alias": {
......
......@@ -7,7 +7,7 @@ class Deferred implements PromisorInterface
private $promise;
private $resolveCallback;
private $rejectCallback;
private $progressCallback;
private $notifyCallback;
private $canceller;
public function __construct(callable $canceller = null)
......@@ -18,10 +18,10 @@ public function __construct(callable $canceller = null)
public function promise()
{
if (null === $this->promise) {
$this->promise = new Promise(function ($resolve, $reject, $progress) {
$this->resolveCallback = $resolve;
$this->rejectCallback = $reject;
$this->progressCallback = $progress;
$this->promise = new Promise(function ($resolve, $reject, $notify) {
$this->resolveCallback = $resolve;
$this->rejectCallback = $reject;
$this->notifyCallback = $notify;
}, $this->canceller);
}
......@@ -42,10 +42,19 @@ public function reject($reason = null)
call_user_func($this->rejectCallback, $reason);
}
public function progress($update = null)
public function notify($update = null)
{
$this->promise();
call_user_func($this->progressCallback, $update);
call_user_func($this->notifyCallback, $update);
}
/**
* @deprecated 2.2.0
* @see Deferred::notify()
*/
public function progress($update = null)
{
$this->notify($update);
}
}
<?php
namespace React\Promise;
interface ExtendedPromiseInterface extends PromiseInterface
{
/**
* @return void
*/
public function done(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null);
/**
* @return ExtendedPromiseInterface
*/
public function otherwise(callable $onRejected);
/**
* @return ExtendedPromiseInterface
*/
public function always(callable $onFulfilledOrRejected);
/**
* @return ExtendedPromiseInterface
*/
public function progress(callable $onProgress);
}
......@@ -2,7 +2,7 @@
namespace React\Promise;
class FulfilledPromise implements CancellablePromiseInterface
class FulfilledPromise implements ExtendedPromiseInterface, CancellablePromiseInterface
{
private $value;
......@@ -30,6 +30,38 @@ public function then(callable $onFulfilled = null, callable $onRejected = null,
}
}
public function done(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
{
if (null === $onFulfilled) {
return;
}
$result = $onFulfilled($this->value);
if ($result instanceof ExtendedPromiseInterface) {
$result->done();
}
}
public function otherwise(callable $onRejected)
{
return new FulfilledPromise($this->value);
}
public function always(callable $onFulfilledOrRejected)
{
return $this->then(function ($value) use ($onFulfilledOrRejected) {
return resolve($onFulfilledOrRejected())->then(function () use ($value) {
return $value;
});
});
}
public function progress(callable $onProgress)
{
return new FulfilledPromise($this->value);
}
public function cancel()
{
}
......
......@@ -2,7 +2,7 @@
namespace React\Promise;
class LazyPromise implements CancellablePromiseInterface
class LazyPromise implements ExtendedPromiseInterface, CancellablePromiseInterface
{
private $factory;
private $promise;
......@@ -17,6 +17,27 @@ public function then(callable $onFulfilled = null, callable $onRejected = null,
return $this->promise()->then($onFulfilled, $onRejected, $onProgress);
}
public function done(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
{
return $this->promise()->done($onFulfilled, $onRejected, $onProgress);
}
public function otherwise(callable $onRejected)
{
return $this->promise()->otherwise($onRejected);
}
public function always(callable $onFulfilledOrRejected)
{
return $this->promise()->always($onFulfilledOrRejected);
}
public function progress(callable $onProgress)
{
return $this->promise()->progress($onProgress);
}
public function cancel()
{
return $this->promise()->cancel();
......
......@@ -2,7 +2,7 @@
namespace React\Promise;
class Promise implements CancellablePromiseInterface
class Promise implements ExtendedPromiseInterface, CancellablePromiseInterface
{
private $canceller;
private $result;
......@@ -40,6 +40,51 @@ public function then(callable $onFulfilled = null, callable $onRejected = null,
});
}
public function done(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
{
if (null !== $this->result) {
return $this->result->done($onFulfilled, $onRejected, $onProgress);
}
$this->handlers[] = function (PromiseInterface $promise) use ($onFulfilled, $onRejected) {
$promise
->done($onFulfilled, $onRejected);
};
if ($onProgress) {
$this->progressHandlers[] = $onProgress;
}
}
public function otherwise(callable $onRejected)
{
return $this->then(null, function ($reason) use ($onRejected) {
if (!_checkTypehint($onRejected, $reason)) {
return new RejectedPromise($reason);
}
return $onRejected($reason);
});
}
public function always(callable $onFulfilledOrRejected)
{
return $this->then(function ($value) use ($onFulfilledOrRejected) {
return resolve($onFulfilledOrRejected())->then(function () use ($value) {
return $value;
});
}, function ($reason) use ($onFulfilledOrRejected) {
return resolve($onFulfilledOrRejected())->then(function () use ($reason) {
return new RejectedPromise($reason);
});
});
}
public function progress(callable $onProgress)
{
return $this->then(null, null, $onProgress);
}
public function cancel()
{
if (null === $this->canceller || null !== $this->result) {
......@@ -51,23 +96,23 @@ public function cancel()
private function resolver(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
{
return function ($resolve, $reject, $progress) use ($onFulfilled, $onRejected, $onProgress) {
return function ($resolve, $reject, $notify) use ($onFulfilled, $onRejected, $onProgress) {
if ($onProgress) {
$progressHandler = function ($update) use ($progress, $onProgress) {
$progressHandler = function ($update) use ($notify, $onProgress) {
try {
$progress($onProgress($update));
$notify($onProgress($update));
} catch (\Exception $e) {
$progress($e);
$notify($e);
}
};
} else {
$progressHandler = $progress;
$progressHandler = $notify;
}
$this->handlers[] = function (PromiseInterface $promise) use ($onFulfilled, $onRejected, $resolve, $reject, $progressHandler) {
$promise
->then($onFulfilled, $onRejected)
->then($resolve, $reject, $progressHandler);
->done($resolve, $reject, $progressHandler);
};
$this->progressHandlers[] = $progressHandler;
......@@ -92,7 +137,7 @@ private function reject($reason = null)
$this->settle(reject($reason));
}
private function progress($update = null)
private function notify($update = null)
{
if (null !== $this->result) {
return;
......@@ -103,8 +148,10 @@ private function progress($update = null)
}
}
private function settle(PromiseInterface $result)
private function settle(ExtendedPromiseInterface $promise)
{
$result = $promise;
foreach ($this->handlers as $handler) {
$handler($result);
}
......@@ -125,7 +172,7 @@ function ($reason = null) {
$this->reject($reason);
},
function ($update = null) {
$this->progress($update);
$this->notify($update);
}
);
} catch (\Exception $e) {
......
......@@ -2,7 +2,7 @@
namespace React\Promise;
class RejectedPromise implements CancellablePromiseInterface
class RejectedPromise implements ExtendedPromiseInterface, CancellablePromiseInterface
{
private $reason;
......@@ -28,6 +28,46 @@ public function then(callable $onFulfilled = null, callable $onRejected = null,
}
}
public function done(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
{
if (null === $onRejected) {
throw UnhandledRejectionException::resolve($this->reason);
}
$result = $onRejected($this->reason);
if ($result instanceof self) {
throw UnhandledRejectionException::resolve($result->reason);
}
if ($result instanceof ExtendedPromiseInterface) {
$result->done();
}
}
public function otherwise(callable $onRejected)
{
if (!_checkTypehint($onRejected, $this->reason)) {
return new RejectedPromise($this->reason);
}
return $this->then(null, $onRejected);
}
public function always(callable $onFulfilledOrRejected)
{
return $this->then(null, function ($reason) use ($onFulfilledOrRejected) {
return resolve($onFulfilledOrRejected())->then(function () use ($reason) {
return new RejectedPromise($reason);
});
});
}
public function progress(callable $onProgress)
{
return new RejectedPromise($this->reason);
}
public function cancel()
{
}
......
<?php
namespace React\Promise;
class UnhandledRejectionException extends \RuntimeException
{
private $reason;
public static function resolve($reason)
{
if ($reason instanceof \Exception) {
return $reason;
}
return new static($reason);
}
public function __construct($reason)
{
$this->reason = $reason;
$message = sprintf('Unhandled Rejection: %s', json_encode($reason));
parent::__construct($message, 0);
}
public function getReason()
{
return $this->reason;
}
}
......@@ -4,17 +4,23 @@
function resolve($promiseOrValue = null)
{
if ($promiseOrValue instanceof PromiseInterface) {
if (!$promiseOrValue instanceof PromiseInterface) {
return new FulfilledPromise($promiseOrValue);
}
if ($promiseOrValue instanceof ExtendedPromiseInterface) {
return $promiseOrValue;
}
return new FulfilledPromise($promiseOrValue);
return new Promise(function ($resolve, $reject, $notify) use ($promiseOrValue) {
$promiseOrValue->then($resolve, $reject, $notify);
});
}
function reject($promiseOrValue = null)
{
if ($promiseOrValue instanceof PromiseInterface) {
return $promiseOrValue->then(function ($value) {
return resolve($promiseOrValue)->then(function ($value) {
return new RejectedPromise($value);
});
}
......@@ -37,10 +43,10 @@ function race($promisesOrValues)
return resolve();
}
return new Promise(function ($resolve, $reject, $progress) use ($array) {
return new Promise(function ($resolve, $reject, $notify) use ($array) {
foreach ($array as $promiseOrValue) {
resolve($promiseOrValue)
->then($resolve, $reject, $progress);
->done($resolve, $reject, $notify);
}
});
});
......@@ -62,7 +68,7 @@ function some($promisesOrValues, $howMany)
return resolve([]);
}
return new Promise(function ($resolve, $reject, $progress) use ($array, $howMany) {
return new Promise(function ($resolve, $reject, $notify) use ($array, $howMany) {
$len = count($array);
$toResolve = min($howMany, $len);
$toReject = ($len - $toResolve) + 1;
......@@ -95,7 +101,7 @@ function some($promisesOrValues, $howMany)
};
resolve($promiseOrValue)
->then($fulfiller, $rejecter, $progress);
->done($fulfiller, $rejecter, $notify);
}
});
});
......@@ -109,14 +115,14 @@ function map($promisesOrValues, callable $mapFunc)
return resolve([]);
}
return new Promise(function ($resolve, $reject, $progress) use ($array, $mapFunc) {
return new Promise(function ($resolve, $reject, $notify) use ($array, $mapFunc) {
$toResolve = count($array);
$values = [];
foreach ($array as $i => $promiseOrValue) {
resolve($promiseOrValue)
->then($mapFunc)
->then(
->done(
function ($mapped) use ($i, &$values, &$toResolve, $resolve) {
$values[$i] = $mapped;
......@@ -125,7 +131,7 @@ function ($mapped) use ($i, &$values, &$toResolve, $resolve) {
}
},
$reject,
$progress
$notify
);
}
});
......@@ -158,3 +164,33 @@ function reduce($promisesOrValues, callable $reduceFunc , $initialValue = null)
return array_reduce($array, $wrappedReduceFunc, $initialValue);
});
}
// Internal functions
function _checkTypehint(callable $callback, $object)
{
if (!is_object($object)) {
return true;
}
if (is_array($callback)) {
$callbackReflection = new \ReflectionMethod($callback[0], $callback[1]);
} elseif (is_object($callback) && !$callback instanceof \Closure) {
$callbackReflection = new \ReflectionMethod($callback, '__invoke');
} else {
$callbackReflection = new \ReflectionFunction($callback);
}
$parameters = $callbackReflection->getParameters();
if (!isset($parameters[0])) {
return true;
}
$expectedException = $parameters[0];
if (!$expectedException->getClass()) {
return true;
}
return $expectedException->getClass()->isInstance($object);
}
<?php
if (!function_exists('React\Promise\resolve')) {
require __DIR__.'/functions.php';
}
......@@ -13,11 +13,30 @@ public function getPromiseTestAdapter(callable $canceller = null)
$d = new Deferred($canceller);
return new CallbackPromiseAdapter([
'promise' => [$d, 'promise'],
'resolve' => [$d, 'resolve'],
'reject' => [$d, 'reject'],
'progress' => [$d, 'progress'],
'settle' => [$d, 'resolve'],
'promise' => [$d, 'promise'],
'resolve' => [$d, 'resolve'],
'reject' => [$d, 'reject'],
'notify' => [$d, 'progress'],
'settle' => [$d, 'resolve'],
]);
}
/** @test */
public function progressIsAnAliasForNotify()
{
$deferred = new Deferred();
$sentinel = new \stdClass();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($sentinel);
$deferred->promise()
->then($this->expectCallableNever(), $this->expectCallableNever(), $mock);
$deferred->progress($sentinel);
}
}
......@@ -29,8 +29,8 @@ public function getPromiseTestAdapter(callable $canceller = null)
'reject' => function () {
throw new \LogicException('You cannot call reject() for React\Promise\FulfilledPromise');
},
'progress' => function () {
throw new \LogicException('You cannot call progress() for React\Promise\FulfilledPromise');