1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Allow objects in define()

This was separately discussed in https://externals.io/message/114863,
but also necessary for consistency now that
https://wiki.php.net/rfc/new_in_initializers has landed.

Closes GH-7149.
This commit is contained in:
Nikita Popov
2021-06-14 12:23:24 +02:00
parent 59a5f89f11
commit 53aed48e5d
6 changed files with 43 additions and 84 deletions

View File

@@ -195,7 +195,7 @@ PHP 8.1 UPGRADE NOTES
RFC: https://wiki.php.net/rfc/fibers
. It is now possible to use "new ClassName()" expressions as parameter
default values, static variable and global constant initializers, as well
as attribute arguments.
as attribute arguments. Objects can also be passed to `define()` now.
RFC: https://wiki.php.net/rfc/new_in_initializers
. Closures for callables can now be created using the syntax `myFunc(...)`,
which is the same as `Closure::fromCallable('myFunc')`. Yes, the `...` is

View File

@@ -16,12 +16,7 @@ var_dump(define("test const", 3));
var_dump(define("test const", 3));
var_dump(define("test", array(1)));
var_dump(define("test1", fopen(__FILE__, 'r')));
try {
var_dump(define("test2", new stdclass));
} catch (TypeError $exception) {
echo $exception->getMessage() . "\n";
}
var_dump(constant(" "));
var_dump(constant("[[["));
@@ -42,7 +37,7 @@ Warning: Constant test const already defined in %s on line %d
bool(false)
bool(true)
bool(true)
define(): Argument #2 ($value) cannot be an object, stdClass given
bool(true)
int(1)
int(2)
int(3)

View File

@@ -13,21 +13,21 @@ class TestClass
define("Bar", new TestClass);
var_dump(Bar);
var_dump((string) Bar);
define("Baz", new stdClass);
var_dump(Baz);
try {
define("Baz", new stdClass);
} catch (TypeError $exception) {
echo $exception->getMessage() . "\n";
}
try {
var_dump(Baz);
} catch (Error $exception) {
echo $exception->getMessage() . "\n";
var_dump((string) Baz);
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
?>
--EXPECT--
object(TestClass)#1 (0) {
}
string(3) "Foo"
define(): Argument #2 ($value) cannot be an object, stdClass given
Undefined constant "Baz"
object(stdClass)#2 (0) {
}
Object of class stdClass could not be converted to string

View File

@@ -23,12 +23,9 @@ define('QUX', $y);
$y[0] = 3;
var_dump($x, $y, QUX);
// ensure objects not allowed in arrays
try {
define('ELEPHPANT', [new StdClass]);
} catch (TypeError $exception) {
echo $exception->getMessage() . "\n";
}
// objects are allowed in arrays
define('ELEPHPANT', [new StdClass]);
var_dump(ELEPHPANT);
// ensure recursion doesn't crash
$recursive = [];
@@ -102,5 +99,9 @@ array(1) {
[0]=>
int(7)
}
define(): Argument #2 ($value) cannot be an object, stdClass given
array(1) {
[0]=>
object(stdClass)#1 (0) {
}
}
define(): Argument #2 ($value) cannot be a recursive array

View File

@@ -3,23 +3,14 @@ Defining constants with non-scalar values
--FILE--
<?php
try {
define('foo', new stdClass);
} catch (TypeError $exception) {
echo $exception->getMessage() . "\n";
}
try {
var_dump(foo);
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
define('foo', fopen(__FILE__, 'r'));
define('foo', new stdClass);
var_dump(foo);
define('bar', fopen(__FILE__, 'r'));
var_dump(bar);
?>
--EXPECT--
define(): Argument #2 ($value) cannot be an object, stdClass given
Undefined constant "foo"
resource(5) of type (stream)
--EXPECTF--
object(stdClass)#1 (0) {
}
resource(%d) of type (stream)

View File

@@ -420,20 +420,12 @@ static bool validate_constant_array_argument(HashTable *ht, int argument_number)
GC_PROTECT_RECURSION(ht);
ZEND_HASH_FOREACH_VAL(ht, val) {
ZVAL_DEREF(val);
if (Z_REFCOUNTED_P(val)) {
if (Z_TYPE_P(val) == IS_ARRAY) {
if (Z_REFCOUNTED_P(val)) {
if (Z_IS_RECURSIVE_P(val)) {
zend_argument_value_error(argument_number, "cannot be a recursive array");
ret = 0;
break;
} else if (!validate_constant_array_argument(Z_ARRVAL_P(val), argument_number)) {
ret = 0;
break;
}
}
} else if (Z_TYPE_P(val) != IS_STRING && Z_TYPE_P(val) != IS_RESOURCE) {
zend_argument_type_error(argument_number, "cannot be an object, %s given", zend_zval_type_name(val));
if (Z_TYPE_P(val) == IS_ARRAY && Z_REFCOUNTED_P(val)) {
if (Z_IS_RECURSIVE_P(val)) {
zend_argument_value_error(argument_number, "cannot be a recursive array");
ret = 0;
break;
} else if (!validate_constant_array_argument(Z_ARRVAL_P(val), argument_number)) {
ret = 0;
break;
}
@@ -496,35 +488,15 @@ ZEND_FUNCTION(define)
ZVAL_UNDEF(&val_free);
switch (Z_TYPE_P(val)) {
case IS_LONG:
case IS_DOUBLE:
case IS_STRING:
case IS_FALSE:
case IS_TRUE:
case IS_NULL:
case IS_RESOURCE:
break;
case IS_ARRAY:
if (Z_REFCOUNTED_P(val)) {
if (!validate_constant_array_argument(Z_ARRVAL_P(val), 2)) {
RETURN_THROWS();
} else {
copy_constant_array(&c.value, val);
goto register_constant;
}
if (Z_TYPE_P(val) == IS_ARRAY) {
if (Z_REFCOUNTED_P(val)) {
if (!validate_constant_array_argument(Z_ARRVAL_P(val), 2)) {
RETURN_THROWS();
} else {
copy_constant_array(&c.value, val);
goto register_constant;
}
break;
case IS_OBJECT:
if (Z_OBJ_HT_P(val)->cast_object(Z_OBJ_P(val), &val_free, IS_STRING) == SUCCESS) {
val = &val_free;
break;
}
ZEND_FALLTHROUGH;
default:
zval_ptr_dtor(&val_free);
zend_argument_type_error(2, "cannot be an object, %s given", zend_zval_type_name(val));
RETURN_THROWS();
}
}
ZVAL_COPY(&c.value, val);