Skip to content

Commit 75c5b40

Browse files
committed
refactor: Fix defer exception unwinding with JMP chaining.
1 parent 0eb6d67 commit 75c5b40

9 files changed

Lines changed: 191 additions & 239 deletions

File tree

Zend/tests/defer/defer_005.phpt

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,19 @@
22
Defer executes on exception
33
--FILE--
44
<?php
5-
function test_defer_on_exception() {
6-
echo "Start\n";
7-
5+
function test() {
86
defer {
9-
echo "Cleanup executed\n";
7+
echo "Defer executed\n";
108
}
11-
12-
echo "Before throw\n";
13-
throw new Exception("Test");
9+
throw new Exception("Test exception");
1410
}
1511

1612
try {
17-
test_defer_on_exception();
13+
test();
1814
} catch (Exception $e) {
1915
echo "Caught: " . $e->getMessage() . "\n";
2016
}
2117
?>
2218
--EXPECT--
23-
Start
24-
Before throw
25-
Cleanup executed
26-
Caught: Test
19+
Defer executed
20+
Caught: Test exception

Zend/tests/defer/defer_008.phpt

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,18 @@
11
--TEST--
2-
Defer with closures and use variables
2+
Multiple defers execute on exception in LIFO order
33
--FILE--
44
<?php
55
function test() {
6-
$name = "Resource";
7-
$value = 42;
8-
9-
echo "Opening $name\n";
10-
116
defer {
12-
echo "Closing $name with value $value\n";
7+
echo "Defer 1\n";
138
}
14-
15-
$value = 100;
16-
echo "Processing with value $value\n";
17-
18-
throw new Exception("Error during processing");
9+
defer {
10+
echo "Defer 2\n";
11+
}
12+
defer {
13+
echo "Defer 3\n";
14+
}
15+
throw new Exception("Test");
1916
}
2017

2118
try {
@@ -25,7 +22,7 @@ try {
2522
}
2623
?>
2724
--EXPECT--
28-
Opening Resource
29-
Processing with value 100
30-
Closing Resource with value 100
31-
Caught: Error during processing
25+
Defer 3
26+
Defer 2
27+
Defer 1
28+
Caught: Test

Zend/tests/defer/defer_009.phpt

Lines changed: 11 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,28 @@
11
--TEST--
2-
Defer with mixed normal and exception paths
2+
Defer with nested function calls and exceptions
33
--FILE--
44
<?php
5-
function testSuccess() {
6-
echo "Success function start\n";
7-
5+
function inner() {
86
defer {
9-
echo "Success defer\n";
7+
echo "Inner defer\n";
108
}
11-
12-
echo "Success function end\n";
13-
return "OK";
9+
throw new Exception("Inner exception");
1410
}
1511

16-
function testFailure() {
17-
echo "Failure function start\n";
18-
12+
function outer() {
1913
defer {
20-
echo "Failure defer\n";
14+
echo "Outer defer\n";
2115
}
22-
23-
throw new Exception("Failed");
16+
inner();
2417
}
2518

26-
$result = testSuccess();
27-
echo "Result: $result\n";
28-
2919
try {
30-
testFailure();
20+
outer();
3121
} catch (Exception $e) {
3222
echo "Caught: " . $e->getMessage() . "\n";
3323
}
34-
35-
echo "All done\n";
3624
?>
3725
--EXPECT--
38-
Success function start
39-
Success function end
40-
Success defer
41-
Result: OK
42-
Failure function start
43-
Failure defer
44-
Caught: Failed
45-
All done
26+
Inner defer
27+
Outer defer
28+
Caught: Inner exception

Zend/tests/defer/defer_010.phpt

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,14 @@
11
--TEST--
2-
Defer with array operations and modifications
2+
Defer can access exception variable
33
--FILE--
44
<?php
55
function test() {
6-
$data = ['items' => []];
6+
$value = "test value";
77

88
defer {
9-
echo "Final data: " . json_encode($data) . "\n";
9+
echo "Defer: $value\n";
1010
}
1111

12-
defer {
13-
$data['items'][] = 'cleanup';
14-
echo "Added cleanup item\n";
15-
}
16-
17-
$data['items'][] = 'first';
18-
$data['items'][] = 'second';
19-
echo "Current data: " . json_encode($data) . "\n";
20-
2112
throw new Exception("Test");
2213
}
2314

@@ -28,7 +19,5 @@ try {
2819
}
2920
?>
3021
--EXPECT--
31-
Current data: {"items":["first","second"]}
32-
Added cleanup item
33-
Final data: {"items":["first","second","cleanup"]}
22+
Defer: test value
3423
Caught: Test

Zend/tests/defer/defer_011.phpt

Lines changed: 12 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,18 @@
11
--TEST--
2-
Defer with object cleanup
2+
Defer executes even when exception thrown in loop
33
--FILE--
44
<?php
5-
class Resource {
6-
public $name;
7-
public $isOpen = false;
8-
9-
public function __construct($name) {
10-
$this->name = $name;
11-
$this->open();
12-
}
13-
14-
public function open() {
15-
echo "Opening resource: {$this->name}\n";
16-
$this->isOpen = true;
17-
}
18-
19-
public function close() {
20-
echo "Closing resource: {$this->name}\n";
21-
$this->isOpen = false;
22-
}
23-
}
24-
255
function test() {
26-
$resource1 = new Resource("Database");
27-
286
defer {
29-
$resource1->close();
7+
echo "Defer executed\n";
308
}
319

32-
$resource2 = new Resource("File");
33-
34-
defer {
35-
$resource2->close();
10+
for ($i = 0; $i < 5; $i++) {
11+
echo "Loop $i\n";
12+
if ($i == 2) {
13+
throw new Exception("Loop exception");
14+
}
3615
}
37-
38-
echo "Using resources\n";
39-
throw new Exception("Error occurred");
4016
}
4117

4218
try {
@@ -46,9 +22,8 @@ try {
4622
}
4723
?>
4824
--EXPECT--
49-
Opening resource: Database
50-
Opening resource: File
51-
Using resources
52-
Closing resource: File
53-
Closing resource: Database
54-
Caught: Error occurred
25+
Loop 0
26+
Loop 1
27+
Loop 2
28+
Defer executed
29+
Caught: Loop exception

Zend/tests/defer/defer_012.phpt

Lines changed: 8 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,22 @@
11
--TEST--
2-
Defer with conditional execution and goto
2+
Exception in defer block replaces original exception
33
--FILE--
44
<?php
5-
function test($shouldFail) {
6-
echo "Test start with shouldFail=$shouldFail\n";
7-
5+
function test() {
86
defer {
9-
echo "Cleanup defer\n";
10-
}
11-
12-
if ($shouldFail) {
13-
goto error;
7+
echo "Defer throwing new exception\n";
8+
throw new Exception("Defer exception");
149
}
1510

16-
echo "Normal path\n";
17-
return "success";
18-
19-
error:
20-
echo "Error path\n";
21-
throw new Exception("Failed");
11+
throw new Exception("Original exception");
2212
}
2313

24-
$result = test(false);
25-
echo "Result: $result\n";
26-
2714
try {
28-
test(true);
15+
test();
2916
} catch (Exception $e) {
3017
echo "Caught: " . $e->getMessage() . "\n";
3118
}
3219
?>
3320
--EXPECT--
34-
Test start with shouldFail=
35-
Normal path
36-
Cleanup defer
37-
Result: success
38-
Test start with shouldFail=1
39-
Error path
40-
Cleanup defer
41-
Caught: Failed
21+
Defer throwing new exception
22+
Caught: Defer exception

Zend/tests/defer/defer_015.phpt

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,30 @@
11
--TEST--
2-
Defer basic exception that propagates
2+
Defer with conditional exception
33
--FILE--
44
<?php
5-
function test() {
6-
echo "Start\n";
7-
5+
function test($throw) {
86
defer {
9-
echo "Defer\n";
7+
echo "Defer executed\n";
8+
}
9+
10+
if ($throw) {
11+
throw new Exception("Conditional exception");
1012
}
1113

12-
throw new Exception("Test");
14+
echo "Normal execution\n";
1315
}
1416

1517
try {
16-
test();
18+
test(false);
19+
echo "---\n";
20+
test(true);
1721
} catch (Exception $e) {
18-
echo "Caught\n";
22+
echo "Caught: " . $e->getMessage() . "\n";
1923
}
2024
?>
2125
--EXPECT--
22-
Start
23-
Defer
24-
Caught
26+
Normal execution
27+
Defer executed
28+
---
29+
Defer executed
30+
Caught: Conditional exception

0 commit comments

Comments
 (0)