Skip to content

Commit d258e40

Browse files
authored
Merge pull request #179 from clue-labs/nullable-v1
[1.x] Improve PHP 8.4+ support by avoiding implicitly nullable types
2 parents 78a6ea5 + 37fa61d commit d258e40

File tree

6 files changed

+66
-3
lines changed

6 files changed

+66
-3
lines changed

src/DuplexResourceStream.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,13 @@ final class DuplexResourceStream extends EventEmitter implements DuplexStreamInt
3838
private $closing = false;
3939
private $listening = false;
4040

41-
public function __construct($stream, LoopInterface $loop = null, $readChunkSize = null, WritableStreamInterface $buffer = null)
41+
/**
42+
* @param resource $stream
43+
* @param ?LoopInterface $loop
44+
* @param ?int $readChunkSize
45+
* @param ?WritableStreamInterface $buffer
46+
*/
47+
public function __construct($stream, $loop = null, $readChunkSize = null, $buffer = null)
4248
{
4349
if (!\is_resource($stream) || \get_resource_type($stream) !== "stream") {
4450
throw new InvalidArgumentException('First parameter must be a valid stream resource');
@@ -56,6 +62,13 @@ public function __construct($stream, LoopInterface $loop = null, $readChunkSize
5662
throw new \RuntimeException('Unable to set stream resource to non-blocking mode');
5763
}
5864

65+
if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1
66+
throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
67+
}
68+
if ($buffer !== null && !$buffer instanceof WritableStreamInterface) { // manual type check to support legacy PHP < 7.1
69+
throw new \InvalidArgumentException('Argument #4 ($buffer) expected null|React\Stream\WritableStreamInterface');
70+
}
71+
5972
// Use unbuffered read operations on the underlying stream resource.
6073
// Reading chunks from the stream may otherwise leave unread bytes in
6174
// PHP's stream buffers which some event loop implementations do not

src/ReadableResourceStream.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,12 @@ final class ReadableResourceStream extends EventEmitter implements ReadableStrea
4040
private $closed = false;
4141
private $listening = false;
4242

43-
public function __construct($stream, LoopInterface $loop = null, $readChunkSize = null)
43+
/**
44+
* @param resource $stream
45+
* @param ?LoopInterface $loop
46+
* @param ?int $readChunkSize
47+
*/
48+
public function __construct($stream, $loop = null, $readChunkSize = null)
4449
{
4550
if (!\is_resource($stream) || \get_resource_type($stream) !== "stream") {
4651
throw new InvalidArgumentException('First parameter must be a valid stream resource');
@@ -58,6 +63,10 @@ public function __construct($stream, LoopInterface $loop = null, $readChunkSize
5863
throw new \RuntimeException('Unable to set stream resource to non-blocking mode');
5964
}
6065

66+
if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1
67+
throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
68+
}
69+
6170
// Use unbuffered read operations on the underlying stream resource.
6271
// Reading chunks from the stream may otherwise leave unread bytes in
6372
// PHP's stream buffers which some event loop implementations do not

src/WritableResourceStream.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,13 @@ final class WritableResourceStream extends EventEmitter implements WritableStrea
2828
private $closed = false;
2929
private $data = '';
3030

31-
public function __construct($stream, LoopInterface $loop = null, $writeBufferSoftLimit = null, $writeChunkSize = null)
31+
/**
32+
* @param resource $stream
33+
* @param ?LoopInterface $loop
34+
* @param ?int $writeBufferSoftLimit
35+
* @param ?int $writeChunkSize
36+
*/
37+
public function __construct($stream, $loop = null, $writeBufferSoftLimit = null, $writeChunkSize = null)
3238
{
3339
if (!\is_resource($stream) || \get_resource_type($stream) !== "stream") {
3440
throw new \InvalidArgumentException('First parameter must be a valid stream resource');
@@ -46,6 +52,10 @@ public function __construct($stream, LoopInterface $loop = null, $writeBufferSof
4652
throw new \RuntimeException('Unable to set stream resource to non-blocking mode');
4753
}
4854

55+
if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1
56+
throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
57+
}
58+
4959
$this->stream = $stream;
5060
$this->loop = $loop ?: Loop::get();
5161
$this->softLimit = ($writeBufferSoftLimit === null) ? 65536 : (int)$writeBufferSoftLimit;

tests/DuplexResourceStreamTest.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,22 @@ public function testConstructorThrowsExceptionIfStreamDoesNotSupportNonBlocking(
106106
new DuplexResourceStream($stream, $loop);
107107
}
108108

109+
public function testContructorThrowsExceptionForInvalidLoop()
110+
{
111+
$stream = fopen('php://temp', 'r+');
112+
113+
$this->setExpectedException('InvalidArgumentException', 'Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
114+
new DuplexResourceStream($stream, 42);
115+
}
116+
117+
public function testContructorThrowsExceptionForInvalidBuffer()
118+
{
119+
$stream = fopen('php://temp', 'r+');
120+
121+
$this->setExpectedException('InvalidArgumentException', 'Argument #4 ($buffer) expected null|React\Stream\WritableStreamInterface');
122+
new DuplexResourceStream($stream, null, null, 42);
123+
}
124+
109125
/**
110126
* @covers React\Stream\DuplexResourceStream::__construct
111127
* @doesNotPerformAssertions

tests/ReadableResourceStreamTest.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,13 @@ public function testConstructorThrowsExceptionIfStreamDoesNotSupportNonBlocking(
105105
new ReadableResourceStream($stream, $loop);
106106
}
107107

108+
public function testContructorThrowsExceptionForInvalidLoop()
109+
{
110+
$stream = fopen('php://temp', 'r+');
111+
112+
$this->setExpectedException('InvalidArgumentException', 'Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
113+
new ReadableResourceStream($stream, 42);
114+
}
108115

109116
public function testCloseShouldEmitCloseEvent()
110117
{

tests/WritableResourceStreamTest.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,14 @@ public function testConstructorThrowsExceptionIfStreamDoesNotSupportNonBlocking(
103103
new WritableResourceStream($stream, $loop);
104104
}
105105

106+
public function testContructorThrowsExceptionForInvalidLoop()
107+
{
108+
$stream = fopen('php://temp', 'r+');
109+
110+
$this->setExpectedException('InvalidArgumentException', 'Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
111+
new WritableResourceStream($stream, 42);
112+
}
113+
106114
/**
107115
* @covers React\Stream\WritableResourceStream::write
108116
* @covers React\Stream\WritableResourceStream::handleWrite

0 commit comments

Comments
 (0)