Skip to content

Commit eb65ec4

Browse files
committed
Implement Closure::getCurrent() to retrieve current closure
Fixes GH-18163 Closes GH-18167
1 parent d20f4fc commit eb65ec4

File tree

5 files changed

+90
-1
lines changed

5 files changed

+90
-1
lines changed

UPGRADING

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,7 @@ PHP 8.5 UPGRADE NOTES
421421
. The clone language construct is now a function and supports reassigning
422422
(readonly) properties during cloning via the new $withProperties parameter.
423423
RFC: https://wiki.php.net/rfc/clone_with_v2
424+
. Added Closure::getCurrent() to receive currently executing closure.
424425

425426
- Curl:
426427
. curl_multi_get_handles() allows retrieving all CurlHandles current
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
--TEST--
2+
Closure::getCurrent()
3+
--FILE--
4+
<?php
5+
6+
$i = 1;
7+
8+
$c = function ($p) use (&$i) {
9+
$self = Closure::getCurrent();
10+
var_dump($p, $i);
11+
$i++;
12+
if ($p < 10) {
13+
$self($p + 1);
14+
}
15+
};
16+
17+
$c(1);
18+
var_dump($i);
19+
20+
function fail() {
21+
Closure::getCurrent();
22+
}
23+
24+
try {
25+
fail();
26+
} catch (Error $e) {
27+
echo $e->getMessage(), "\n";
28+
}
29+
30+
function foo() {
31+
var_dump(Closure::getCurrent());
32+
}
33+
34+
try {
35+
foo(...)();
36+
} catch (Error $e) {
37+
echo $e->getMessage(), "\n";
38+
}
39+
40+
?>
41+
--EXPECT--
42+
int(1)
43+
int(1)
44+
int(2)
45+
int(2)
46+
int(3)
47+
int(3)
48+
int(4)
49+
int(4)
50+
int(5)
51+
int(5)
52+
int(6)
53+
int(6)
54+
int(7)
55+
int(7)
56+
int(8)
57+
int(8)
58+
int(9)
59+
int(9)
60+
int(10)
61+
int(10)
62+
int(11)
63+
Current function is not a closure
64+
Current function is not a closure

Zend/zend_closures.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,23 @@ ZEND_METHOD(Closure, fromCallable)
418418
}
419419
/* }}} */
420420

421+
ZEND_METHOD(Closure, getCurrent)
422+
{
423+
ZEND_PARSE_PARAMETERS_NONE();
424+
425+
zend_execute_data *prev_ex = EX(prev_execute_data);
426+
427+
if (!prev_ex
428+
|| !prev_ex->func
429+
|| (prev_ex->func->common.fn_flags & (ZEND_ACC_CLOSURE|ZEND_ACC_FAKE_CLOSURE)) != ZEND_ACC_CLOSURE) {
430+
zend_throw_error(NULL, "Current function is not a closure");
431+
RETURN_THROWS();
432+
}
433+
434+
zend_object *obj = ZEND_CLOSURE_OBJECT(prev_ex->func);
435+
RETURN_OBJ_COPY(obj);
436+
}
437+
421438
static ZEND_COLD zend_function *zend_closure_get_constructor(zend_object *object) /* {{{ */
422439
{
423440
zend_throw_error(NULL, "Instantiation of class Closure is not allowed");

Zend/zend_closures.stub.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,6 @@ public function bindTo(?object $newThis, object|string|null $newScope = "static"
2121
public function call(object $newThis, mixed ...$args): mixed {}
2222

2323
public static function fromCallable(callable $callback): Closure {}
24+
25+
public static function getCurrent(): Closure {}
2426
}

Zend/zend_closures_arginfo.h

Lines changed: 6 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)