1--TEST--
2Lazy objects: setRawValueWithoutLazyInitialization() may trigger initialization via side effects (__destruct())
3--FILE--
4<?php
5
6class C {
7    public function __construct() {
8        printf("%s\n", __METHOD__);
9        $this->a = 'a';
10        $this->b = 'b';
11    }
12    public $a;
13    public $b;
14}
15
16function test(string $name, object $obj) {
17    printf("# %s\n", $name);
18
19    $reflector = new ReflectionClass(C::class);
20
21    $value = new class($obj) {
22        function __construct(public object $obj) {}
23        function __destruct() {
24            $this->obj->b = '';
25        }
26    };
27    $reflector->getProperty('a')->setRawValueWithoutLazyInitialization($obj, $value);
28    $value = null;
29
30    $reflector->getProperty('a')->setRawValueWithoutLazyInitialization($obj, new stdClass);
31
32    var_dump(!$reflector->isUninitializedLazyObject($obj));
33    var_dump($obj);
34}
35
36$reflector = new ReflectionClass(C::class);
37$obj = $reflector->newLazyGhost(function ($obj) {
38    $obj->__construct();
39});
40
41test('Ghost', $obj);
42
43$obj = $reflector->newLazyProxy(function () {
44    return new C();
45});
46
47test('Proxy', $obj);
48
49?>
50--EXPECTF--
51# Ghost
52C::__construct
53bool(true)
54object(C)#%d (2) {
55  ["a"]=>
56  string(1) "a"
57  ["b"]=>
58  string(0) ""
59}
60# Proxy
61C::__construct
62bool(true)
63lazy proxy object(C)#%d (1) {
64  ["instance"]=>
65  object(C)#%d (2) {
66    ["a"]=>
67    string(1) "a"
68    ["b"]=>
69    string(0) ""
70  }
71}
72