Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Zend/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ libZend_la_SOURCES=\
zend_default_classes.c \
zend_iterators.c zend_interfaces.c zend_exceptions.c \
zend_strtod.c zend_closures.c zend_float.c zend_string.c zend_signal.c \
zend_generators.c zend_virtual_cwd.c zend_ast.c zend_smart_str.c
zend_generators.c zend_virtual_cwd.c zend_ast.c zend_smart_str.c \
zend_fiber.c

libZend_la_CFLAGS = -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1
libZend_la_LDFLAGS =
Expand Down
11 changes: 11 additions & 0 deletions Zend/tests/fiber/001.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
--TEST--
tests Fiber class
--FILE--
<?php
echo class_exists('Fiber'), "\n";
$f = new Fiber(function () {});
var_dump($f);
--EXPECTF--
1
object(Fiber)#%d (0) {
}
16 changes: 16 additions & 0 deletions Zend/tests/fiber/002.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
--TEST--
tests Fiber await
--FILE--
<?php
$f = new Fiber(function () {
echo "start\n";
await;
echo "end\n";
});
$f->resume();
echo "fiber\n";
$f->resume();
--EXPECTF--
start
fiber
end
25 changes: 25 additions & 0 deletions Zend/tests/fiber/003.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
--TEST--
tests Fiber await variable
--FILE--
<?php
$f = new Fiber(function () {
await "string";
await 1;
await [1, 2];
await new stdclass;
});
var_dump($f->resume());
var_dump($f->resume());
var_dump($f->resume());
var_dump($f->resume());
--EXPECTF--
string(6) "string"
int(1)
array(2) {
[0]=>
int(1)
[1]=>
int(2)
}
object(stdClass)#%d (0) {
}
25 changes: 25 additions & 0 deletions Zend/tests/fiber/004.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
--TEST--
tests Fiber resume args
--FILE--
<?php
$f = new Fiber(function ($a) {
var_dump($a);
var_dump(await);
var_dump(await);
var_dump(await);
});
$f->resume("string");
$f->resume(1);
$f->resume([1,2]);
$f->resume(new stdclass);
--EXPECTF--
string(6) "string"
int(1)
array(2) {
[0]=>
int(1)
[1]=>
int(2)
}
object(stdClass)#%d (0) {
}
26 changes: 26 additions & 0 deletions Zend/tests/fiber/005.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
--TEST--
tests Fiber stackful await
--FILE--
<?php
function foo()
{
echo "before\n";
await;
echo "after\n";
}
$f = new Fiber(function () {
foo();
await;
echo "bye\n";
});
$f->resume();
echo "await\n";
$f->resume();
echo "await2\n";
$f->resume();
--EXPECTF--
before
await
after
await2
bye
28 changes: 28 additions & 0 deletions Zend/tests/fiber/006.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
--TEST--
tests Fiber status
--FILE--
<?php
$f = new Fiber(function () {
await;
});

var_dump($f->status() == Fiber::STATUS_SUSPENDED);
$f->resume();
var_dump($f->status() == Fiber::STATUS_SUSPENDED);
$f->resume();
var_dump($f->status() == Fiber::STATUS_FINISHED);
$f->resume();

$f = new Fiber(function () {
throw new Exception;
});
try {
$f->resume();
} catch (Exception $e) {
}
var_dump($f->status() == Fiber::STATUS_DEAD);
--EXPECTF--
bool(true)
bool(true)
bool(true)
bool(true)
30 changes: 30 additions & 0 deletions Zend/tests/fiber/007.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
--TEST--
tests Fiber status
--FILE--
<?php
function bar()
{
$a = null;
await;
$a->foo();
}
function foo()
{
bar();
}
$f = new Fiber(function () {
foo();
});

$f->resume();
$f->resume();

--EXPECTF--
Fatal error: Uncaught Error: Call to a member function foo() on null in %s/Zend/tests/fiber/007.php:6
Stack trace:
#0 %s/Zend/tests/fiber/007.php(10): bar()
#1 %s/Zend/tests/fiber/007.php(13): foo()
#2 [internal function]: {closure}()
#3 %s/Zend/tests/fiber/007.php(17): Fiber->resume()
#4 {main}
thrown in %s/Zend/tests/fiber/007.php on line 6
22 changes: 22 additions & 0 deletions Zend/tests/fiber/008.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
--TEST--
tests Fiber during internal call
--FILE--
<?php
function foo()
{
await;
}
$f = new Fiber(function () {
array_map('foo', [1,2]);
});

echo $f->resume();
--EXPECTF--
Fatal error: Uncaught Error: Cannot await in internal call in %s/Zend/tests/fiber/008.php:4
Stack trace:
#0 [internal function]: foo(1)
#1 %s/Zend/tests/fiber/008.php(7): array_map('foo', Array)
#2 [internal function]: {closure}()
#3 %s/Zend/tests/fiber/008.php(10): Fiber->resume()
#4 {main}
thrown in %s/Zend/tests/fiber/008.php on line 4
1 change: 1 addition & 0 deletions Zend/zend_ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ enum _zend_ast_kind {
ZEND_AST_INSTANCEOF,
ZEND_AST_YIELD,
ZEND_AST_COALESCE,
ZEND_AST_AWAIT,

ZEND_AST_STATIC,
ZEND_AST_WHILE,
Expand Down
43 changes: 31 additions & 12 deletions Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -1278,7 +1278,7 @@ static void zend_mark_function_as_generator() /* {{{ */

if (ZEND_TYPE_CODE(return_info.type) != IS_ITERABLE) {
const char *msg = "Generators may only declare a return type of Generator, Iterator, Traversable, or iterable, %s is not permitted";

if (!ZEND_TYPE_IS_CLASS(return_info.type)) {
zend_error_noreturn(E_COMPILE_ERROR, msg, zend_get_type_by_const(ZEND_TYPE_CODE(return_info.type)));
}
Expand Down Expand Up @@ -1947,7 +1947,7 @@ ZEND_API size_t zend_dirname(char *path, size_t len)
static void zend_adjust_for_fetch_type(zend_op *opline, uint32_t type) /* {{{ */
{
zend_uchar factor = (opline->opcode == ZEND_FETCH_STATIC_PROP_R) ? 1 : 3;

if (opline->opcode == ZEND_FETCH_THIS) {
return;
}
Expand Down Expand Up @@ -2185,7 +2185,7 @@ static void zend_emit_tick(void) /* {{{ */
if (CG(active_op_array)->last && CG(active_op_array)->opcodes[CG(active_op_array)->last - 1].opcode == ZEND_TICKS) {
return;
}

opline = get_next_op(CG(active_op_array));

opline->opcode = ZEND_TICKS;
Expand Down Expand Up @@ -2612,7 +2612,7 @@ static zend_op *zend_compile_simple_var_no_cv(znode *result, zend_ast *ast, uint
opline = zend_emit_op(result, ZEND_FETCH_R, &name_node, NULL);
}

if (name_node.op_type == IS_CONST &&
if (name_node.op_type == IS_CONST &&
zend_is_auto_global(Z_STR(name_node.u.constant))) {

opline->extended_value = ZEND_FETCH_GLOBAL;
Expand Down Expand Up @@ -4968,7 +4968,7 @@ void zend_compile_switch(zend_ast *ast) /* {{{ */
} else if (expr_node.op_type == IS_CONST
&& Z_TYPE(expr_node.u.constant) == IS_TRUE) {
jmpnz_opnums[i] = zend_emit_cond_jump(ZEND_JMPNZ, &cond_node, 0);
} else {
} else {
opline = zend_emit_op(NULL, ZEND_CASE, &expr_node, &cond_node);
SET_NODE(opline->result, &case_node);
if (opline->op1_type == IS_CONST) {
Expand All @@ -4992,7 +4992,7 @@ void zend_compile_switch(zend_ast *ast) /* {{{ */
if (jumptable) {
zval *cond_zv = zend_ast_get_zval(cond_ast);
zval jmp_target;
ZVAL_LONG(&jmp_target, get_next_op_number(CG(active_op_array)));
ZVAL_LONG(&jmp_target, get_next_op_number(CG(active_op_array)));

ZEND_ASSERT(Z_TYPE_P(cond_zv) == jumptable_type);
if (Z_TYPE_P(cond_zv) == IS_LONG) {
Expand Down Expand Up @@ -5166,7 +5166,7 @@ void zend_compile_try(zend_ast *ast) /* {{{ */
if (finally_ast) {
zend_loop_var discard_exception;
uint32_t opnum_jmp = get_next_op_number(CG(active_op_array)) + 1;

/* Pop FAST_CALL from unwind stack */
zend_stack_del_top(&CG(loop_var_stack));

Expand Down Expand Up @@ -5417,7 +5417,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */
uint32_t i;
zend_op_array *op_array = CG(active_op_array);
zend_arg_info *arg_infos;

if (return_type_ast) {
zend_bool allow_null = 0;

Expand Down Expand Up @@ -5560,7 +5560,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */
"with a float type can only be float, integer, or NULL");
}
break;

case IS_ITERABLE:
if (Z_TYPE(default_node.u.constant) != IS_ARRAY) {
zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters "
Expand All @@ -5572,7 +5572,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */
zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters "
"with an object type can only be NULL");
break;

default:
if (!ZEND_SAME_FAKE_TYPE(ZEND_TYPE_CODE(arg_info->type), Z_TYPE(default_node.u.constant))) {
zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters "
Expand Down Expand Up @@ -5605,7 +5605,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */
} else {
opline->op2.num = -1;
}
}
}
}

/* These are assigned at the end to avoid unitialized memory in case of an error */
Expand Down Expand Up @@ -7397,6 +7397,22 @@ void zend_compile_yield_from(znode *result, zend_ast *ast) /* {{{ */
}
/* }}} */

void zend_compile_await(znode *result, zend_ast *ast) /* {{{ */
{
zend_ast *value_ast = ast->child[0];

znode value_node;
znode *value_node_ptr = NULL;

if (value_ast) {
zend_compile_expr(&value_node, value_ast);
value_node_ptr = &value_node;
}

zend_emit_op(result, ZEND_AWAIT, value_node_ptr, NULL);
}
/* }}} */

void zend_compile_instanceof(znode *result, zend_ast *ast) /* {{{ */
{
zend_ast *obj_ast = ast->child[0];
Expand Down Expand Up @@ -7856,7 +7872,7 @@ static void zend_compile_encaps_list(znode *result, zend_ast *ast) /* {{{ */
i = ((j * sizeof(zend_string*)) + (sizeof(zval) - 1)) / sizeof(zval);
while (i > 1) {
get_temporary_variable(CG(active_op_array));
i--;
i--;
}

zend_end_live_range(CG(active_op_array), range, opline - CG(active_op_array)->opcodes,
Expand Down Expand Up @@ -8278,6 +8294,9 @@ void zend_compile_expr(znode *result, zend_ast *ast) /* {{{ */
case ZEND_AST_YIELD_FROM:
zend_compile_yield_from(result, ast);
return;
case ZEND_AST_AWAIT:
zend_compile_await(result, ast);
return;
case ZEND_AST_INSTANCEOF:
zend_compile_instanceof(result, ast);
return;
Expand Down
2 changes: 2 additions & 0 deletions Zend/zend_default_classes.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "zend_exceptions.h"
#include "zend_closures.h"
#include "zend_generators.h"
#include "zend_fiber.h"


ZEND_API void zend_register_default_classes(void)
Expand All @@ -35,6 +36,7 @@ ZEND_API void zend_register_default_classes(void)
zend_register_iterator_wrapper();
zend_register_closure_ce();
zend_register_generator_ce();
zend_register_fiber_ce();
}

/*
Expand Down
Loading