parent
aab412084f
commit
b6d0488ea6
14 changed files with 373 additions and 29 deletions
@ -0,0 +1,33 @@ |
||||
--TEST-- |
||||
foreach list destructuring can write into object properties and array dimensions |
||||
--FILE-- |
||||
<?php |
||||
|
||||
class ForeachListWriteBox |
||||
{ |
||||
public $name = ''; |
||||
public $value = 0; |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
$rows = [ |
||||
['first', 10], |
||||
['second', 20], |
||||
]; |
||||
$box = new ForeachListWriteBox(); |
||||
$out = []; |
||||
|
||||
foreach ($rows as [$box->name, $out['value']]) { |
||||
$box->value += $out['value']; |
||||
var_dump($box->name, $out['value'], $box->value); |
||||
} |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
string(5) "first" |
||||
int(10) |
||||
int(10) |
||||
string(6) "second" |
||||
int(20) |
||||
int(30) |
||||
@ -0,0 +1,16 @@ |
||||
--TEST-- |
||||
static arrow function captures local variables by value |
||||
--FILE-- |
||||
<?php |
||||
|
||||
function main(): void |
||||
{ |
||||
$factor = 3; |
||||
$map = static fn (int $value): int => $value * $factor; |
||||
$factor = 10; |
||||
|
||||
var_dump($map(4)); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
int(12) |
||||
@ -0,0 +1,32 @@ |
||||
--TEST-- |
||||
clone operand expression is evaluated once and __clone runs |
||||
--FILE-- |
||||
<?php |
||||
|
||||
class CloneSideEffect |
||||
{ |
||||
public int $value = 1; |
||||
|
||||
public function __clone() |
||||
{ |
||||
echo "__clone\n"; |
||||
$this->value++; |
||||
} |
||||
} |
||||
|
||||
function make_clone_source(): CloneSideEffect |
||||
{ |
||||
echo "make\n"; |
||||
return new CloneSideEffect(); |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
$copy = clone make_clone_source(); |
||||
var_dump($copy->value); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
make |
||||
__clone |
||||
int(2) |
||||
@ -0,0 +1,23 @@ |
||||
--TEST-- |
||||
Error suppression should restore error_reporting after expression evaluation |
||||
--FILE-- |
||||
<?php |
||||
|
||||
function suppressed_reporting_level(): int |
||||
{ |
||||
return error_reporting(); |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
$before = error_reporting(); |
||||
$inside = @suppressed_reporting_level(); |
||||
$after = error_reporting(); |
||||
|
||||
var_dump($inside === $before); |
||||
var_dump($after === $before); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
bool(false) |
||||
bool(true) |
||||
@ -0,0 +1,24 @@ |
||||
--TEST-- |
||||
$GLOBALS array assignment and reference parameter update global slot |
||||
--FILE-- |
||||
<?php |
||||
|
||||
function globals_assign_ref_inc(&$value): void |
||||
{ |
||||
$value++; |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
$GLOBALS['aot_globals_assign_ref_value'] = 40; |
||||
$GLOBALS['aot_globals_assign_ref_value'] += 1; |
||||
globals_assign_ref_inc($GLOBALS['aot_globals_assign_ref_value']); |
||||
|
||||
global $aot_globals_assign_ref_value; |
||||
var_dump($aot_globals_assign_ref_value); |
||||
var_dump($GLOBALS['aot_globals_assign_ref_value']); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
int(42) |
||||
int(42) |
||||
@ -0,0 +1,21 @@ |
||||
--TEST-- |
||||
$GLOBALS array element can be passed to reference parameter |
||||
--FILE-- |
||||
<?php |
||||
|
||||
function globals_ref_inc(&$value): void |
||||
{ |
||||
$value++; |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
global $aot_globals_ref_value; |
||||
$aot_globals_ref_value = 41; |
||||
|
||||
globals_ref_inc($GLOBALS['aot_globals_ref_value']); |
||||
var_dump($aot_globals_ref_value); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
int(42) |
||||
@ -0,0 +1,26 @@ |
||||
--TEST-- |
||||
include path expression side effects and return value |
||||
--FILE-- |
||||
<?php |
||||
|
||||
function include_target(string $name): string |
||||
{ |
||||
echo "target:$name\n"; |
||||
return __DIR__ . '/' . $name; |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
$ret = include include_target('test_include_return.inc'); |
||||
var_dump($ret); |
||||
|
||||
$ret = include_once include_target('test_include_return.inc'); |
||||
var_dump($ret); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
target:test_include_return.inc |
||||
included:test_include_return.inc |
||||
int(123) |
||||
target:test_include_return.inc |
||||
bool(true) |
||||
@ -0,0 +1,3 @@ |
||||
<?php |
||||
echo "included:" . basename(__FILE__) . "\n"; |
||||
return 123; |
||||
@ -0,0 +1,33 @@ |
||||
--TEST-- |
||||
instanceof dynamic class expression side effects |
||||
--FILE-- |
||||
<?php |
||||
|
||||
interface InstanceofMarker {} |
||||
class InstanceofSubject implements InstanceofMarker {} |
||||
|
||||
function make_instanceof_subject(): object |
||||
{ |
||||
echo "object\n"; |
||||
return new InstanceofSubject(); |
||||
} |
||||
|
||||
function make_instanceof_class(string $class): string |
||||
{ |
||||
echo "class:$class\n"; |
||||
return $class; |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
var_dump(make_instanceof_subject() instanceof (make_instanceof_class(InstanceofMarker::class))); |
||||
var_dump(make_instanceof_subject() instanceof (make_instanceof_class(stdClass::class))); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
object |
||||
class:InstanceofMarker |
||||
bool(true) |
||||
object |
||||
class:stdClass |
||||
bool(false) |
||||
@ -0,0 +1,37 @@ |
||||
--TEST-- |
||||
null coalescing assignment with object property and array dim targets |
||||
--FILE-- |
||||
<?php |
||||
|
||||
class CoalesceBox |
||||
{ |
||||
public $value = null; |
||||
public array $items = []; |
||||
} |
||||
|
||||
function make_default(string $label): string |
||||
{ |
||||
echo "default:$label\n"; |
||||
return $label; |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
$box = new CoalesceBox(); |
||||
$box->value ??= make_default('prop'); |
||||
$box->value ??= make_default('prop-skip'); |
||||
var_dump($box->value); |
||||
|
||||
$box->items['name'] ??= make_default('array'); |
||||
$box->items['name'] ??= make_default('array-skip'); |
||||
var_dump($box->items); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
default:prop |
||||
string(4) "prop" |
||||
default:array |
||||
array(1) { |
||||
["name"]=> |
||||
string(5) "array" |
||||
} |
||||
@ -0,0 +1,68 @@ |
||||
--TEST-- |
||||
Nullsafe chain should stop at middle null and skip later arguments |
||||
--FILE-- |
||||
<?php |
||||
|
||||
class NullsafeChainLeaf |
||||
{ |
||||
public function value(string $arg): string |
||||
{ |
||||
echo "leaf:$arg\n"; |
||||
return $arg; |
||||
} |
||||
} |
||||
|
||||
class NullsafeChainMiddle |
||||
{ |
||||
public function __construct(private ?NullsafeChainLeaf $leaf) |
||||
{ |
||||
} |
||||
|
||||
public function leaf(string $arg): ?NullsafeChainLeaf |
||||
{ |
||||
echo "middle:$arg\n"; |
||||
return $this->leaf; |
||||
} |
||||
} |
||||
|
||||
class NullsafeChainRoot |
||||
{ |
||||
public function __construct(private ?NullsafeChainMiddle $middle) |
||||
{ |
||||
} |
||||
|
||||
public function middle(string $arg): ?NullsafeChainMiddle |
||||
{ |
||||
echo "root:$arg\n"; |
||||
return $this->middle; |
||||
} |
||||
} |
||||
|
||||
function make_arg(string $name): string |
||||
{ |
||||
echo "arg:$name\n"; |
||||
return $name; |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
$root = new NullsafeChainRoot(new NullsafeChainMiddle(null)); |
||||
var_dump($root?->middle(make_arg('root'))?->leaf(make_arg('middle'))?->value(make_arg('leaf'))); |
||||
|
||||
$root = new NullsafeChainRoot(new NullsafeChainMiddle(new NullsafeChainLeaf())); |
||||
var_dump($root?->middle(make_arg('root2'))?->leaf(make_arg('middle2'))?->value(make_arg('leaf2'))); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
arg:root |
||||
root:root |
||||
arg:middle |
||||
middle:middle |
||||
NULL |
||||
arg:root2 |
||||
root:root2 |
||||
arg:middle2 |
||||
middle:middle2 |
||||
arg:leaf2 |
||||
leaf:leaf2 |
||||
string(5) "leaf2" |
||||
@ -0,0 +1,36 @@ |
||||
--TEST-- |
||||
static variable dynamic initializer runs only once |
||||
--FILE-- |
||||
<?php |
||||
|
||||
function make_static_items(int $seed): array |
||||
{ |
||||
echo "init:$seed\n"; |
||||
return [$seed]; |
||||
} |
||||
|
||||
function use_static_items(int $seed): void |
||||
{ |
||||
static $items = make_static_items($seed); |
||||
var_dump($items); |
||||
$items[] = $seed; |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
use_static_items(10); |
||||
use_static_items(20); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
init:10 |
||||
array(1) { |
||||
[0]=> |
||||
int(10) |
||||
} |
||||
array(2) { |
||||
[0]=> |
||||
int(10) |
||||
[1]=> |
||||
int(10) |
||||
} |
||||
Loading…
Reference in new issue