diff --git a/Library/ArgInfoDefinition.php b/Library/ArgInfoDefinition.php index 4930fd58d4..2742032ee5 100644 --- a/Library/ArgInfoDefinition.php +++ b/Library/ArgInfoDefinition.php @@ -135,7 +135,6 @@ private function richRenderStart() $class = escape_class($this->compilationContext->getFullName($class)); } - $this->codePrinter->output('#if PHP_VERSION_ID >= 70200'); $this->codePrinter->output( sprintf( 'ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(%s, %d, %d, %s, %d)', @@ -146,25 +145,11 @@ private function richRenderStart() (int) $this->functionLike->areReturnTypesNullCompatible() ) ); - $this->codePrinter->output('#else'); - $this->codePrinter->output( - sprintf( - 'ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(%s, %d, %d, IS_OBJECT, "%s", %d)', - $this->name, - (int) $this->returnByRef, - $this->functionLike->getNumberOfRequiredParameters(), - $class, - (int) $this->functionLike->areReturnTypesNullCompatible() - ) - ); - $this->codePrinter->output('#endif'); return; } if ($this->functionLike->isVoid()) { - $this->codePrinter->output('#if PHP_VERSION_ID >= 70100'); - $this->codePrinter->output('#if PHP_VERSION_ID >= 70200'); $this->codePrinter->output( sprintf( 'ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(%s, %d, %d, %s, %d)', @@ -176,52 +161,15 @@ private function richRenderStart() ) ); - $this->codePrinter->output('#else'); - - $this->codePrinter->output( - sprintf( - 'ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(%s, %d, %d, %s, NULL, %d)', - $this->name, - (int) $this->returnByRef, - $this->functionLike->getNumberOfRequiredParameters(), - $this->getReturnType(), - (int) $this->functionLike->areReturnTypesNullCompatible() - ) - ); - - $this->codePrinter->output('#endif'); - if (false == $this->hasParameters()) { $this->codePrinter->output('ZEND_END_ARG_INFO()'); } - $this->codePrinter->output('#else'); - - if (true == $this->hasParameters()) { - $this->codePrinter->output( - sprintf( - 'ZEND_BEGIN_ARG_INFO_EX(%s, 0, %d, %d)', - $this->name, - (int) $this->returnByRef, - $this->functionLike->getNumberOfRequiredParameters() - ) - ); - } - - $this->codePrinter->output( - sprintf( - '#define %s NULL', - $this->name - ) - ); - - $this->codePrinter->output('#endif'); $this->codePrinter->outputBlankLine(); return; } - $this->codePrinter->output('#if PHP_VERSION_ID >= 70200'); $this->codePrinter->output( sprintf( 'ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(%s, %d, %d, %s, %d)', @@ -232,21 +180,6 @@ private function richRenderStart() (int) $this->functionLike->areReturnTypesNullCompatible() ) ); - - $this->codePrinter->output('#else'); - - $this->codePrinter->output( - sprintf( - 'ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(%s, %d, %d, %s, NULL, %d)', - $this->name, - (int) $this->returnByRef, - $this->functionLike->getNumberOfRequiredParameters(), - $this->getReturnType(), - (int) $this->functionLike->areReturnTypesNullCompatible() - ) - ); - - $this->codePrinter->output('#endif'); } private function renderEnd() @@ -299,7 +232,6 @@ private function renderEnd() case '1:bool': case '1:boolean': - $this->codePrinter->output('#if PHP_VERSION_ID >= 70200'); $this->codePrinter->output( sprintf( "\tZEND_ARG_TYPE_INFO(%d, %s, %s, %d)", @@ -309,18 +241,12 @@ private function renderEnd() (int) $this->allowNull($parameter) ) ); - $this->codePrinter->output('#else'); - $this->codePrinter->output( - sprintf("\tZEND_ARG_INFO(%d, %s)", $this->passByReference($parameter), $parameter['name']) - ); - $this->codePrinter->output('#endif'); break; case '1:uchar': case '1:int': case '1:uint': case '1:long': case '1:ulong': - $this->codePrinter->output('#if PHP_VERSION_ID >= 70200'); $this->codePrinter->output( sprintf( "\tZEND_ARG_TYPE_INFO(%d, %s, IS_LONG, %d)", @@ -329,14 +255,8 @@ private function renderEnd() (int) $this->allowNull($parameter) ) ); - $this->codePrinter->output('#else'); - $this->codePrinter->output( - sprintf("\tZEND_ARG_INFO(%d, %s)", $this->passByReference($parameter), $parameter['name']) - ); - $this->codePrinter->output('#endif'); break; case '1:double': - $this->codePrinter->output('#if PHP_VERSION_ID >= 70200'); $this->codePrinter->output( sprintf( "\tZEND_ARG_TYPE_INFO(%d, %s, IS_DOUBLE, %d)", @@ -345,15 +265,9 @@ private function renderEnd() (int) $this->allowNull($parameter) ) ); - $this->codePrinter->output('#else'); - $this->codePrinter->output( - sprintf("\tZEND_ARG_INFO(%d, %s)", $this->passByReference($parameter), $parameter['name']) - ); - $this->codePrinter->output('#endif'); break; case '1:char': case '1:string': - $this->codePrinter->output('#if PHP_VERSION_ID >= 70200'); $this->codePrinter->output( sprintf( "\tZEND_ARG_TYPE_INFO(%d, %s, IS_STRING, %d)", @@ -362,11 +276,6 @@ private function renderEnd() (int) $this->allowNull($parameter) ) ); - $this->codePrinter->output('#else'); - $this->codePrinter->output( - sprintf("\tZEND_ARG_INFO(%d, %s)", $this->passByReference($parameter), $parameter['name']) - ); - $this->codePrinter->output('#endif'); break; default: $this->codePrinter->output( diff --git a/Library/ClassDefinition.php b/Library/ClassDefinition.php index f1d60460c6..58a94d6cb1 100644 --- a/Library/ClassDefinition.php +++ b/Library/ClassDefinition.php @@ -1266,7 +1266,6 @@ public function compile(CompilationContext $compilationContext) $codePrinter->outputBlankLine(); } else { $codePrinter->output('ZEPHIR_DOC_METHOD('.$this->getCNamespace().'_'.$this->getName().', '.$method->getName().');'); - $codePrinter->outputBlankLine(); } } @@ -1439,16 +1438,68 @@ public function getClassEntryByClassName($className, CompilationContext $compila $this->compiler = $compilationContext->compiler; switch (strtolower($className)) { - /* - * Zend classes + /** + * Zend exceptions */ + case 'throwable': + $classEntry = 'zend_ce_throwable'; + break; + case 'exception': - $classEntry = 'zend_exception_get_default()'; + $classEntry = 'zend_ce_exception'; + break; + + case 'errorexception': + $classEntry = 'zend_ce_error_exception'; + break; + + case 'error': + $classEntry = 'zend_ce_error'; + break; + + case 'compileerror': + $classEntry = 'zend_ce_compile_error'; + break; + + case 'parseerror': + $classEntry = 'zend_ce_parse_error'; + break; + + case 'typeerror': + $classEntry = 'zend_ce_type_error'; + break; + + case 'argumentcounterror': + $classEntry = 'zend_ce_argument_count_error'; + break; + + case 'valueerror': + $classEntry = 'zend_ce_value_error'; + break; + + case 'arithmeticerror': + $classEntry = 'zend_ce_arithmetic_error'; + break; + + case 'divisionbyzeroerror': + $classEntry = 'zend_ce_division_by_zero_error'; + break; + + case 'unhandledmatcherror': + $classEntry = 'zend_ce_unhandled_match_error'; break; /* * Zend interfaces (Zend/zend_interfaces.h) */ + case 'traversable': + $classEntry = 'zend_ce_traversable'; + break; + + case 'aggregate': + $classEntry = 'zend_ce_aggregate'; + break; + case 'iterator': $classEntry = 'zend_ce_iterator'; break; @@ -1461,8 +1512,12 @@ public function getClassEntryByClassName($className, CompilationContext $compila $classEntry = 'zend_ce_serializable'; break; - case 'iteratoraggregate': - $classEntry = 'zend_ce_aggregate'; + case 'countable': + $classEntry = 'zend_ce_countable'; + break; + + case 'stringable': + $classEntry = 'zend_ce_stringable'; break; /* @@ -1755,6 +1810,14 @@ public function getClassEntryByClassName($className, CompilationContext $compila $classEntry = 'php_date_get_timezone_ce()'; break; + /** + * PHP Ext session + */ + case 'sessionhandlerinterface': + $compilationContext->headersManager->add('ext/session/php_session'); + $classEntry = 'php_session_iface_entry'; + break; + // Reflection /*case 'reflector': $compilationContext->headersManager->add('ext/reflection/php_reflection'); diff --git a/Library/ClassMethod.php b/Library/ClassMethod.php index 881f317dfa..050eac24de 100644 --- a/Library/ClassMethod.php +++ b/Library/ClassMethod.php @@ -1880,13 +1880,13 @@ public function compile(CompilationContext $compilationContext) */ $initCode = ''; $code = ''; + $requiredParams = []; + $optionalParams = []; if (\is_object($parameters)) { /** * Round 2. Fetch the parameters in the method. */ $params = []; - $requiredParams = []; - $optionalParams = []; $numberRequiredParams = 0; $numberOptionalParams = 0; foreach ($parameters->getParameters() as $parameter) { @@ -2205,6 +2205,40 @@ public function compile(CompilationContext $compilationContext) $codePrinter->preOutputBlankLine(); } + /** + * ZEND_PARSE_PARAMETERS + */ + $tempCodePrinter = new CodePrinter(); + if (is_object($parameters) && !empty($parameters->getParameters())) { + $tempCodePrinter->output('#if PHP_VERSION_ID >= 80000'); + $tempCodePrinter->output("\t".'bool is_null_true = 1;'); + + $tempCodePrinter->output(sprintf( + "\t".'ZEND_PARSE_PARAMETERS_START(%d, %d)', + count($requiredParams), + count($requiredParams) + count($optionalParams) + )); + + foreach ($requiredParams as $requiredParam) { + $tempCodePrinter->output("\t"."\t".$this->detectParam($requiredParam, $compilationContext)); + } + + if (!empty($optionalParams)) { + $tempCodePrinter->output("\t"."\t".'Z_PARAM_OPTIONAL'); + + foreach ($optionalParams as $optionalParam) { + $tempCodePrinter->output("\t"."\t".$this->detectParam($optionalParam, $compilationContext)); + } + } + + $tempCodePrinter->output("\t".'ZEND_PARSE_PARAMETERS_END();'); + $tempCodePrinter->outputBlankLine(); + + $tempCodePrinter->output('#endif'); + } + + $codePrinter->preOutput($tempCodePrinter->getOutput()); + /* * Generate the variable definition for variables used. */ @@ -2441,4 +2475,235 @@ public function areReturnTypesCompatible() return true; } + + /** + * Determine Z_PARAM_* + * + * @param array $parameter + * @param CompilationContext $compilationContext + * @return string + * @throws Exception + */ + public function detectParam(array $parameter, CompilationContext $compilationContext): string + { + $name = $parameter['name']; + if (!isset($parameter['data-type'])) { + return sprintf('Z_PARAM_ZVAL(%s)', $name); + } + + /** + * In case of unknown type, just return generic param type. + */ + $param = sprintf('Z_PARAM_ZVAL(%s)', $name); + $hasDefaultNull = isset($parameter['default']['type']) && $parameter['default']['type'] === 'null'; + + switch ($parameter['data-type']) { + case 'array': + if ($hasDefaultNull) { + $param = sprintf('Z_PARAM_ARRAY_OR_NULL(%s)', $name); + } else { + $param = sprintf('Z_PARAM_ARRAY(%s)', $name); + } + + break; + + case 'bool': + if ($hasDefaultNull) { + $param = sprintf('Z_PARAM_BOOL_OR_NULL(%s, is_null_true)', $name); + } else { + $param = sprintf('Z_PARAM_BOOL(%s)', $name); + } + + break; + + case 'float': + if ($hasDefaultNull) { + $param = sprintf('Z_PARAM_DOUBLE_OR_NULL(%s, is_null_true)', $name); + } else { + $param = sprintf('Z_PARAM_DOUBLE(%s)', $name); + } + + break; + + case 'int': + if ($hasDefaultNull) { + $param = sprintf('Z_PARAM_LONG_OR_NULL(%s, is_null_true)', $name); + } else { + $param = sprintf('Z_PARAM_LONG(%s)', $name); + } + + break; + + case 'object': + if ($hasDefaultNull) { + $param = sprintf('Z_PARAM_OBJECT_OF_CLASS_OR_NULL(%s)', $name); + } else { + $param = sprintf('Z_PARAM_OBJECT(%s)', $name); + } + + break; + + case 'resource': + if ($hasDefaultNull) { + $param = sprintf('Z_PARAM_RESOURCE_OR_NULL(%s)', $name); + } else { + $param = sprintf('Z_PARAM_RESOURCE(%s)', $name); + } + + break; + + case 'string': + if ($hasDefaultNull) { + $param = sprintf('Z_PARAM_STR_OR_NULL(%s)', $name); + } else { + $param = sprintf('Z_PARAM_STR(%s)', $name); + } + + break; + + case 'variable': + if (isset($parameter['cast']) && $parameter['cast']['type'] === 'variable' && $parameter['cast']['value']) { + $classEntry = $this->detectClassNameEntry($parameter['cast']['value'], $compilationContext); + if ($classEntry !== null) { + if ($hasDefaultNull) { + $param = sprintf('Z_PARAM_OBJECT_OF_CLASS_OR_NULL(%s, %s)', $name, $classEntry); + } else { + $param = sprintf('Z_PARAM_OBJECT_OF_CLASS(%s, %s)', $name, $classEntry); + } + } + } + + break; + } + + return $param; + } + + /** + * @param string $className + * @param CompilationContext $compilationContext + * @return string|null + * @throws Exception + */ + private function detectClassNameEntry(string $className, CompilationContext $compilationContext): ?string + { + if ($this->classDefinition === null) { + return null; + } + + $isAlias = false; + $aliasManager = $this->classDefinition->getAliasManager(); + if ($aliasManager->isAlias($className)) { + $isAlias = true; + $className = $aliasManager->getAlias($className); + } + + /** + * PSR + */ + if (strpos($className, 'Psr') === 0 || strpos($className, '\Psr') === 0) { + $className = ltrim($className, '\\'); + + $psrHeaderFiles = [ + 'psr_http_message' => [ + 'Psr\Http\Message\StreamInterface', + 'Psr\Http\Message\StreamFactoryInterface', + 'Psr\Http\Message\UriFactoryInterface', + 'Psr\Http\Message\UriInterface', + 'Psr\Http\Message\RequestInterface', + 'Psr\Http\Message\RequestFactoryInterface', + 'Psr\Http\Message\ResponseInterface', + 'Psr\Http\Message\ResponseFactoryInterface', + 'Psr\Http\Message\ServerRequestInterface', + 'Psr\Http\Message\ServerRequestFactoryInterface', + 'Psr\Http\Message\UploadedFileInterface', + 'Psr\Http\Message\UploadedFileFactoryInterface', + ], + 'psr_simple_cache' => [ + 'Psr\SimpleCache\CacheInterface', + 'Psr\SimpleCache\CacheException', + 'Psr\SimpleCache\InvalidArgumentException', + ], + 'psr_container' => [ + 'Psr\Container\ContainerInterface', + ], + 'psr_log' => [ + 'Psr\Log\AbstractLogger', + 'Psr\Log\LoggerInterface', + 'Psr\Log\LogLevel', + ], + 'psr_link' => [ + 'Psr\Link\EvolvableLinkInterface', + 'Psr\Link\EvolvableLinkProviderInterface', + 'Psr\Link\LinkInterface', + 'Psr\Link\LinkProviderInterface', + ], + 'psr_http_server_middleware' => [ + 'Psr\Http\Server\MiddlewareInterface', + ], + 'psr_http_server_handler' => [ + 'Psr\Http\Server\RequestHandlerInterface', + ], + ]; + foreach ($psrHeaderFiles as $file => $classes) { + if (in_array($className, $classes)) { + $compilationContext->headersManager->add('ext/psr/' . $file); + } + } + + return str_replace('\\', '', $className) . '_ce_ptr'; + } + + try { + return $this + ->classDefinition + ->getClassEntryByClassName( + preg_replace(['/^\\\\/'], '', $className), + $compilationContext, + false + ); + } catch (CompilerException $exception) { + // Continue below execution + } + + /** + * Full namespace with class name + */ + if (strpos($className, '\\') === 0) { + $classNamespace = explode('\\', $className); + $classNamespace = array_filter($classNamespace); + + /** + * External class + */ + if (count($classNamespace) === 1) { + return null; + } + + /** + * External class, we don't know its ClassEntry in C world. + */ + if (!preg_match('/^'.$classNamespace[0].'/', $this->classDefinition->getNamespace())) { + return null; + } + + $className = end($classNamespace); + } + + /** + * Check for partial namespace specification + * Example: Oo\Param, while namespace at the top is Stub + */ + $classNamespace = explode('\\', $className); + $className = end($classNamespace); + array_pop($classNamespace); + + if ($isAlias === false) { + array_unshift($classNamespace, $this->classDefinition->getNamespace()); + } + + $namespace = join('\\', $classNamespace); + + return (new ClassDefinition($namespace, $className))->getClassEntry(); + } } diff --git a/Library/Stubs/Generator.php b/Library/Stubs/Generator.php index 11af1fec9b..242c6109c7 100644 --- a/Library/Stubs/Generator.php +++ b/Library/Stubs/Generator.php @@ -382,16 +382,16 @@ protected function wrapPHPValue(array $parameter): string { switch ($parameter['default']['type']) { case 'null': - return 'null'; + $returnValue = 'null'; break; case 'string': case 'char': - return '\''.addslashes($parameter['default']['value']).'\''; + $returnValue = '\''.addslashes($parameter['default']['value']).'\''; break; case 'empty-array': - return 'array()'; + $returnValue = 'array()'; break; case 'array': @@ -413,17 +413,17 @@ protected function wrapPHPValue(array $parameter): string ]); } - return 'array('.implode(', ', $parameters).')'; + $returnValue = 'array('.implode(', ', $parameters).')'; break; case 'static-constant-access': - return $parameter['default']['left']['value'].'::'.$parameter['default']['right']['value']; + $returnValue = $parameter['default']['left']['value'].'::'.$parameter['default']['right']['value']; break; case 'int': case 'double': case 'bool': - return $parameter['default']['value']; + $returnValue = $parameter['default']['value']; break; default: @@ -433,7 +433,8 @@ protected function wrapPHPValue(array $parameter): string $parameter['default']['type'] ) ); - break; } + + return $returnValue; } } diff --git a/kernels/ZendEngine3/array.c b/kernels/ZendEngine3/array.c index 49267eb4df..10c2b799c5 100755 --- a/kernels/ZendEngine3/array.c +++ b/kernels/ZendEngine3/array.c @@ -1052,8 +1052,6 @@ void zephir_fast_array_merge(zval *return_value, zval *array1, zval *array2) } array_init_size(return_value, init_size); - php_array_merge(Z_ARRVAL_P(return_value), Z_ARRVAL_P(array1)); - php_array_merge(Z_ARRVAL_P(return_value), Z_ARRVAL_P(array2)); } diff --git a/kernels/ZendEngine3/fcall.c b/kernels/ZendEngine3/fcall.c index e2c7587875..00cf4d0e85 100755 --- a/kernels/ZendEngine3/fcall.c +++ b/kernels/ZendEngine3/fcall.c @@ -45,11 +45,7 @@ static int zephir_make_fcall_key(zend_string* s, zephir_call_type type, zend_cla const zend_class_entry *calling_scope; unsigned char t; -#if PHP_VERSION_ID >= 70100 calling_scope = zend_get_executed_scope(); -#else - calling_scope = EG(scope); -#endif switch (type) { case zephir_fcall_parent: @@ -205,15 +201,9 @@ static void populate_fcic(zend_fcall_info_cache* fcic, zephir_call_type type, ze { zend_class_entry* calling_scope; -#if PHP_VERSION_ID < 70300 - fcic->initialized = 0; -#endif fcic->function_handler = NULL; if (type == zephir_fcall_function && Z_TYPE_P(func) == IS_STRING) { -#if PHP_VERSION_ID < 70300 - fcic->initialized = 1; -#endif fcic->called_scope = NULL; fcic->calling_scope = NULL; fcic->object = NULL; @@ -329,10 +319,6 @@ static void populate_fcic(zend_fcall_info_cache* fcic, zephir_call_type type, ze default: return; } - -#if PHP_VERSION_ID < 70300 - fcic->initialized = 1; -#endif } /** diff --git a/kernels/ZendEngine3/file.c b/kernels/ZendEngine3/file.c index 96aabd071c..afc6dca351 100755 --- a/kernels/ZendEngine3/file.c +++ b/kernels/ZendEngine3/file.c @@ -88,7 +88,6 @@ int zephir_file_exists(zval *filename) */ int zephir_compare_mtime(zval *filename1, zval *filename2) { - php_stream_statbuf statbuffer1, statbuffer2; if (Z_TYPE_P(filename1) != IS_STRING || Z_TYPE_P(filename2) != IS_STRING) { @@ -111,7 +110,6 @@ int zephir_compare_mtime(zval *filename1, zval *filename2) void zephir_fwrite(zval *return_value, zval *stream_zval, zval *data) { - int num_bytes; php_stream *stream; @@ -152,7 +150,6 @@ void zephir_fwrite(zval *return_value, zval *stream_zval, zval *data) int zephir_feof(zval *stream_zval) { - php_stream *stream; if (Z_TYPE_P(stream_zval) != IS_RESOURCE) { @@ -256,11 +253,7 @@ void zephir_file_put_contents(zval *return_value, zval *filename, zval *data) case IS_DOUBLE: case IS_TRUE: case IS_FALSE: -#if PHP_VERSION_ID < 70300 - case IS_CONSTANT: -#else case IS_CONSTANT_AST: -#endif use_copy = zend_make_printable_zval(data, ©); if (use_copy) { data = © @@ -315,7 +308,6 @@ void zephir_filemtime(zval *return_value, zval *path) */ void zephir_prepare_virtual_path(zval *return_value, zval *path, zval *virtual_separator) { - unsigned int i; unsigned char ch; smart_str virtual_str = {0}; diff --git a/kernels/ZendEngine3/filter.c b/kernels/ZendEngine3/filter.c index 0cdc4faf4f..ab4ffb23d9 100755 --- a/kernels/ZendEngine3/filter.c +++ b/kernels/ZendEngine3/filter.c @@ -40,8 +40,8 @@ /** * Filter alphanum string */ -void zephir_filter_alphanum(zval *return_value, zval *param) { - +void zephir_filter_alphanum(zval *return_value, zval *param) +{ unsigned int i; unsigned char ch; smart_str filtered_str = {0}; @@ -83,7 +83,6 @@ void zephir_filter_alphanum(zval *return_value, zval *param) { */ void zephir_is_basic_charset(zval *return_value, const zval *param) { - unsigned int i; unsigned int ch; int iso88591 = 0; @@ -127,8 +126,8 @@ static long zephir_unpack(char *data, int size, int issigned, int *map) /** * Converts an unsigned long to a char* */ -static inline char *zephir_longtohex(unsigned long value) { - +static inline char *zephir_longtohex(unsigned long value) +{ static char digits[] = "0123456789abcdef"; char buf[(sizeof(unsigned long) << 3) + 1]; char *ptr, *end; @@ -148,7 +147,6 @@ static inline char *zephir_longtohex(unsigned long value) { */ void zephir_escape_multi(zval *return_value, zval *param, const char *escape_char, unsigned int escape_length, char escape_extra, int use_whitelist) { - unsigned int i; zval copy; smart_str escaped_str = {0}; diff --git a/kernels/ZendEngine3/memory.h b/kernels/ZendEngine3/memory.h index b7b0493a6d..453a898804 100755 --- a/kernels/ZendEngine3/memory.h +++ b/kernels/ZendEngine3/memory.h @@ -179,10 +179,3 @@ int zephir_set_symbol_str(char *key_name, unsigned int key_length, zval *value); } while (0) #endif - -/* Backwards compatibility for GC API change in PHP 7.3 */ -#if PHP_VERSION_ID < 70300 -# define GC_ADDREF(p) ++GC_REFCOUNT(p) -# define GC_DELREF(p) --GC_REFCOUNT(p) -# define GC_SET_REFCOUNT(p, rc) GC_REFCOUNT(p) = rc -#endif diff --git a/kernels/ZendEngine3/object.c b/kernels/ZendEngine3/object.c index 93496a87e5..3afc15dd34 100755 --- a/kernels/ZendEngine3/object.c +++ b/kernels/ZendEngine3/object.c @@ -95,7 +95,6 @@ int zephir_zval_is_traversable(zval *object) */ void zephir_get_called_class(zval *return_value) { -#if PHP_VERSION_ID >= 70100 zend_class_entry *called_scope = zend_get_called_scope(EG(current_execute_data)); if (called_scope) { ZVAL_STR(return_value, zend_string_dup(called_scope->name, 0)); @@ -104,17 +103,6 @@ void zephir_get_called_class(zval *return_value) if (!zend_get_executed_scope()) { php_error_docref(NULL, E_WARNING, "zephir_get_called_class() called from outside a class"); } -#else - if (EG(current_execute_data)->called_scope) { - zend_string *ret = EG(current_execute_data)->called_scope->name; - zend_string_addref(ret); - RETURN_STR(ret); - } - - if (!EG(scope)) { - php_error_docref(NULL, E_WARNING, "zephir_get_called_class() called from outside a class"); - } -#endif } zend_class_entry *zephir_fetch_class_str_ex(const char *class_name, size_t length, int fetch_type) @@ -150,7 +138,6 @@ void zephir_get_class(zval *result, zval *object, int lower) zval *z = Z_ISREF_P(object) ? Z_REFVAL_P(object) : object; if (Z_TYPE_P(z) == IS_OBJECT) { - ce = Z_OBJCE_P(z); //zval_ptr_dtor(result); class_name = zend_string_init(ZSTR_VAL(ce->name), ZSTR_LEN(ce->name), 0); @@ -223,7 +210,6 @@ void zephir_get_class_ns(zval *result, zval *object, int lower) if (lower) { zend_str_tolower(Z_STRVAL_P(result), Z_STRLEN_P(result)); } - } /** @@ -373,19 +359,10 @@ int zephir_clone(zval *destination, zval *obj) int zephir_isset_property(zval *object, const char *property_name, unsigned int property_length) { if (Z_TYPE_P(object) == IS_OBJECT) { - /* - if (Z_OBJ_HANDLER_P(object, has_property)) { - zval member; - int retval; - ZVAL_STRINGL(&member, property_name, property_length); - retval = Z_OBJ_HT_P(object)->has_property(object, &member, 2, NULL); - zval_ptr_dtor(&member); - return retval; - } - */ if (EXPECTED(zend_hash_str_exists(&Z_OBJCE_P(object)->properties_info, property_name, property_length))) { return 1; } + #if PHP_VERSION_ID >= 80000 return zend_hash_str_exists( Z_OBJ_HT_P(object)->get_properties(Z_OBJ_P(object)), @@ -411,15 +388,9 @@ int zephir_isset_property_zval(zval *object, const zval *property) { if (Z_TYPE_P(object) == IS_OBJECT) { if (Z_TYPE_P(property) == IS_STRING) { - /* - if (Z_OBJ_HANDLER_P(object, has_property)) { - return Z_OBJ_HT_P(object)->has_property(object, property, 2, NULL); - } - */ if (EXPECTED(zend_hash_str_exists(&Z_OBJCE_P(object)->properties_info, Z_STRVAL_P(property), Z_STRLEN_P(property)))) { return 1; } else { - #if PHP_VERSION_ID >= 80000 return zend_hash_str_exists( Z_OBJ_HT_P(object)->get_properties(Z_OBJ_P(object)), @@ -443,10 +414,11 @@ int zephir_isset_property_zval(zval *object, const zval *property) /** * Lookup for the real owner of the property */ -static inline -zend_class_entry *zephir_lookup_class_ce(zend_class_entry *ce, - const char *property_name, - unsigned int property_length) { +static inline zend_class_entry *zephir_lookup_class_ce( + zend_class_entry *ce, + const char *property_name, + unsigned int property_length +) { zend_class_entry *original_ce = ce; zend_property_info *info; zend_class_entry *scope; @@ -487,9 +459,12 @@ zend_class_entry *zephir_lookup_class_ce(zend_class_entry *ce, * This function is intended to use in initializer. Do not use it for a * regular property updating. */ -int zephir_read_property_ex(zval *result, zval *object, const char *property_name, - uint32_t property_length, int flags) -{ +int zephir_read_property_ex( + zval *result, + zval *object, + const char *property_name, + uint32_t property_length, int flags +) { zend_class_entry *scope; int retval; @@ -522,9 +497,12 @@ int zephir_read_property_ex(zval *result, zval *object, const char *property_nam /** * Checks whether obj is an object and reads a property from this object */ -int zephir_read_property(zval *result, zval *object, const char *property_name, - uint32_t property_length, int flags) -{ +int zephir_read_property( + zval *result, + zval *object, + const char *property_name, + uint32_t property_length, int flags +) { zval property, tmp; zval *res; @@ -532,9 +510,7 @@ int zephir_read_property(zval *result, zval *object, const char *property_name, if (Z_TYPE_P(object) != IS_OBJECT) { if ((flags & PH_NOISY) == PH_NOISY) { - php_error_docref(NULL, E_NOTICE, - "Trying to get property '%s' of non-object", - property_name); + php_error_docref(NULL, E_NOTICE, "Trying to get property '%s' of non-object", property_name); } ZVAL_NULL(result); @@ -542,9 +518,7 @@ int zephir_read_property(zval *result, zval *object, const char *property_name, } if (!Z_OBJ_HT_P(object)->read_property) { - zend_error(E_CORE_ERROR, - "Property %s of class %s cannot be read", - property_name, ZSTR_VAL(Z_OBJCE_P(object)->name)); + zend_error(E_CORE_ERROR, "Property %s of class %s cannot be read", property_name, ZSTR_VAL(Z_OBJCE_P(object)->name)); } ZVAL_STRINGL(&property, property_name, property_length); @@ -579,7 +553,6 @@ int zephir_fetch_property(zval *result, zval *object, const char *property_name, return 1; } - //zval_ptr_dtor(result); ZVAL_NULL(result); return 0; } @@ -632,9 +605,12 @@ int zephir_read_property_zval(zval *result, zval *object, zval *property, int fl * This function is intended to use in initializer. Do not use it for a * regular property updating. */ -int zephir_update_property_zval_ex(zval *object, const char *property_name, - unsigned int property_length, zval *value) -{ +int zephir_update_property_zval_ex( + zval *object, + const char *property_name, + unsigned int property_length, + zval *value +) { zend_class_entry *scope; int retval; @@ -667,22 +643,21 @@ int zephir_update_property_zval_ex(zval *object, const char *property_name, /** * Checks whether obj is an object and updates property with another zval */ -int zephir_update_property_zval(zval *object, const char *property_name, - unsigned int property_length, zval *value) -{ +int zephir_update_property_zval( + zval *object, + const char *property_name, + unsigned int property_length, + zval *value +) { zval property, sep_value; if (Z_TYPE_P(object) != IS_OBJECT) { - php_error_docref(NULL, E_WARNING, - "Attempt to assign property '%s' of non-object", - property_name); + php_error_docref(NULL, E_WARNING, "Attempt to assign property '%s' of non-object", property_name); return FAILURE; } if (!Z_OBJ_HT_P(object)->write_property) { - zend_error(E_CORE_ERROR, - "Property %s of class %s cannot be updated", - property_name, ZSTR_VAL(Z_OBJCE_P(object)->name)); + zend_error(E_CORE_ERROR, "Property %s of class %s cannot be updated", property_name, ZSTR_VAL(Z_OBJCE_P(object)->name)); } ZVAL_STRINGL(&property, property_name, property_length); @@ -987,7 +962,6 @@ int zephir_unset_property_array(zval *object, char *property, unsigned int prope int separated = 0; if (Z_TYPE_P(object) == IS_OBJECT) { - zephir_read_property(&tmp, object, property, property_length, PH_NOISY_CC); Z_TRY_DELREF(tmp); @@ -1067,9 +1041,11 @@ int zephir_method_exists(zval *object, const zval *method_name) zend_error(E_WARNING, "method_exists expected a string"); return 0; } + char *lcname = zend_str_tolower_dup(Z_STRVAL_P(method_name), Z_STRLEN_P(method_name)); int res = zephir_method_exists_ex(object, lcname, Z_STRLEN_P(method_name)); efree(lcname); + return res; } @@ -1077,43 +1053,26 @@ int zephir_read_static_property_ce(zval *result, zend_class_entry *ce, const cha { zval *tmp = zend_read_static_property(ce, property, len, (zend_bool) ZEND_FETCH_CLASS_SILENT); - //zval_ptr_dtor(result); ZVAL_NULL(result); - if (tmp) - { + if (tmp) { if ((flags & PH_READONLY) == PH_READONLY) { ZVAL_COPY_VALUE(result, tmp); } else { ZVAL_COPY(result, tmp); } + return SUCCESS; } + return FAILURE; } +/** + * TODO: Use directly zend_update_static_property() + */ int zephir_update_static_property_ce(zend_class_entry *ce, const char *property_name, uint32_t property_length, zval *value) { -// Disabled due to: -// https://github.com/phalcon/zephir/issues/1941#issuecomment-538654340 -// -//#if PHP_VERSION_ID < 70300 -// zval *property, garbage; -// property = zend_read_static_property(ce, property_name, property_length, (zend_bool)ZEND_FETCH_CLASS_SILENT); -// if (property) { -// if (Z_ISREF_P(property)) { -// ZVAL_DEREF(property); -// } -// if (Z_ISREF_P(value)) { -// ZVAL_DEREF(value); -// } -// ZVAL_COPY_VALUE(&garbage, property); -// ZVAL_COPY(property, value); -// zval_ptr_dtor(&garbage); -// return 1; -// } -//#else return zend_update_static_property(ce, property_name, property_length, value); -//#endif } int zephir_add_static_property_ce(zend_class_entry *ce, const char *property_name, uint32_t property_length, zval *value) @@ -1135,8 +1094,16 @@ int zephir_sub_static_property_ce(zend_class_entry *ce, const char *property_nam /* * Multiple array-offset update */ -int zephir_update_static_property_array_multi_ce(zend_class_entry *ce, const char *property, uint32_t property_length, zval *value, const char *types, int types_length, int types_count, ...) -{ +int zephir_update_static_property_array_multi_ce( + zend_class_entry *ce, + const char *property, + uint32_t property_length, + zval *value, + const char *types, + int types_length, + int types_count, + ... +) { va_list ap; zval tmp_arr; int separated = 0; @@ -1173,6 +1140,7 @@ int zephir_update_static_property_array_multi_ce(zend_class_entry *ce, const cha array_init(&tmp_arr); separated = 1; } + if (Z_REFCOUNTED(tmp_arr)) { if (Z_REFCOUNT(tmp_arr) > 1) { if (!Z_ISREF(tmp_arr)) { @@ -1225,7 +1193,6 @@ int zephir_property_incr_decr(zval *object, char *property_name, unsigned int pr zephir_read_property(&tmp, object, property_name, property_length, 0); if (Z_TYPE(tmp) > IS_UNDEF) { - Z_TRY_DELREF(tmp); /** Separation only when refcount > 1 */ @@ -1267,11 +1234,7 @@ typedef struct _zend_closure { zend_function func; zval this_ptr; zend_class_entry *called_scope; -#if PHP_VERSION_ID >= 70300 zif_handler orig_internal_handler; -#else - void (*orig_internal_handler)(INTERNAL_FUNCTION_PARAMETERS); -#endif } zend_closure; /** @@ -1326,10 +1289,6 @@ int zephir_create_instance(zval *return_value, const zval *class_name) zend_class_entry* ce = Z_OBJCE_P(return_value); fci.size = sizeof(fci); -#if PHP_VERSION_ID < 70100 - fci.function_table = &ce->function_table; - fci.symbol_table = NULL; -#endif fci.object = obj; fci.retval = 0; fci.param_count = 0; @@ -1339,11 +1298,9 @@ int zephir_create_instance(zval *return_value, const zval *class_name) #else fci.named_params = NULL; #endif + ZVAL_NULL(&fci.function_name); -#if PHP_VERSION_ID < 70300 - fcc.initialized = 1; -#endif fcc.object = obj; fcc.called_scope = ce; fcc.calling_scope = ce; @@ -1394,10 +1351,6 @@ int zephir_create_instance_params(zval *return_value, const zval *class_name, zv zend_class_entry* ce = Z_OBJCE_P(return_value); fci.size = sizeof(fci); -#if PHP_VERSION_ID < 70100 - fci.function_table = &ce->function_table; - fci.symbol_table = NULL; -#endif fci.object = obj; fci.retval = 0; fci.param_count = 0; @@ -1409,9 +1362,6 @@ int zephir_create_instance_params(zval *return_value, const zval *class_name, zv #endif ZVAL_NULL(&fci.function_name); -#if PHP_VERSION_ID < 70300 - fcc.initialized = 1; -#endif fcc.object = obj; fcc.called_scope = ce; fcc.calling_scope = ce; diff --git a/kernels/ZendEngine3/require.c b/kernels/ZendEngine3/require.c index a0d5ccfad9..31a35e1ad4 100755 --- a/kernels/ZendEngine3/require.c +++ b/kernels/ZendEngine3/require.c @@ -72,11 +72,7 @@ int zephir_require_ret(zval *return_value_ptr, const char *require_path) zend_destroy_file_handle(&file_handle); } -#if PHP_VERSION_ID >= 70100 new_op_array->scope = EG(fake_scope) ? EG(fake_scope) : zend_get_executed_scope(); -#else - new_op_array->scope = EG(scope); -#endif zend_execute(new_op_array, &local_retval); if (return_value_ptr) { diff --git a/kernels/ZendEngine3/string.c b/kernels/ZendEngine3/string.c index 2b2bc75368..94edd81c94 100755 --- a/kernels/ZendEngine3/string.c +++ b/kernels/ZendEngine3/string.c @@ -151,7 +151,6 @@ void zephir_fast_strtoupper(zval *return_value, zval *str) */ int zephir_start_with(const zval *str, const zval *compared, zval *case_sensitive) { - int i; int sensitive = 0; char *op1_cursor, *op2_cursor; @@ -175,7 +174,6 @@ int zephir_start_with(const zval *str, const zval *compared, zval *case_sensitiv op1_cursor = Z_STRVAL_P(str); op2_cursor = Z_STRVAL_P(compared); for (i = 0; i < Z_STRLEN_P(compared); i++) { - if (tolower(*op1_cursor) != tolower(*op2_cursor)) { return 0; } @@ -217,7 +215,6 @@ int zephir_start_with_str_str(char *str, unsigned int str_length, char *compared */ int zephir_end_with(const zval *str, const zval *compared, zval *case_sensitive) { - int sensitive = 0; int i; char *op1_cursor, *op2_cursor; @@ -259,7 +256,6 @@ int zephir_end_with(const zval *str, const zval *compared, zval *case_sensitive) */ int zephir_end_with_str(const zval *str, char *compared, unsigned int compared_length) { - if (Z_TYPE_P(str) != IS_STRING) { return 0; } @@ -433,7 +429,6 @@ void zephir_append_printable_array(smart_str *implstr, const zval *value) */ void zephir_unique_key(zval *return_value, const zval *prefix, zval *value) { - smart_str implstr = {0}; if (Z_TYPE_P(prefix) == IS_STRING) { @@ -568,7 +563,6 @@ void zephir_fast_join_str(zval *return_value, char *glue, unsigned int glue_leng */ void zephir_camelize(zval *return_value, const zval *str, const zval *delimiter) { - int i, len, delim_len, pre_del = 1; smart_str camelize_str = {0}; char *marker, ch, *delim; @@ -669,7 +663,6 @@ void zephir_uncamelize(zval *return_value, const zval *str, const zval *delimite */ int zephir_memnstr(const zval *haystack, const zval *needle ZEPHIR_DEBUG_PARAMS) { - if (Z_TYPE_P(haystack) != IS_STRING || Z_TYPE_P(needle) != IS_STRING) { #ifndef ZEPHIR_RELEASE zend_error(E_WARNING, "Invalid arguments supplied for memnstr in %s on line %d", file, line); @@ -889,6 +882,7 @@ static zend_string* php_char_to_str_ex(zend_string *str, char from, char *to, si } } } + *target = 0; return result; } @@ -1071,19 +1065,11 @@ void zephir_preg_match(zval *return_value, zval *regex, zval *subject, zval *mat ZVAL_UNDEF(&tmp_matches); -#if PHP_VERSION_ID < 70400 - if (flags != 0 || offset != 0) { - php_pcre_match_impl(pce, Z_STRVAL_P(subject), Z_STRLEN_P(subject), return_value, &tmp_matches, global, 1, flags, offset); - } else { - php_pcre_match_impl(pce, Z_STRVAL_P(subject), Z_STRLEN_P(subject), return_value, &tmp_matches, global, 0, 0, 0); - } -#else if (flags != 0 || offset != 0) { php_pcre_match_impl(pce, Z_STR_P(subject), return_value, &tmp_matches, global, 1, flags, offset); } else { php_pcre_match_impl(pce, Z_STR_P(subject), return_value, &tmp_matches, global, 0, 0, 0); } -#endif if (matches) { zval *php_matches = &tmp_matches; diff --git a/stub/interfaces/implementint.zep b/stub/interfaces/implementint.zep new file mode 100644 index 0000000000..2aafd93b62 --- /dev/null +++ b/stub/interfaces/implementint.zep @@ -0,0 +1,16 @@ +namespace Stub\Interfaces; + +class ImplementInt implements InterfaceInt +{ + protected val = null; + + public function set(int val) -> void + { + let this->val = val; + } + + public function get() -> int + { + return this->val; + } +} diff --git a/stub/interfaces/implementinterface.zep b/stub/interfaces/implementinterface.zep new file mode 100644 index 0000000000..9434492dee --- /dev/null +++ b/stub/interfaces/implementinterface.zep @@ -0,0 +1,21 @@ +namespace Stub\Interfaces; + +class ImplementInterface implements InterfaceIntSignature +{ + protected obj; + + public function get( obj) -> int + { + return obj->get(); + } + + public function getVoid( obj) -> void + { + let this->obj = obj; + } + + public function getObj() -> + { + return this->obj; + } +} diff --git a/stub/interfaces/interfaceint.zep b/stub/interfaces/interfaceint.zep new file mode 100644 index 0000000000..da7a5f0bb6 --- /dev/null +++ b/stub/interfaces/interfaceint.zep @@ -0,0 +1,8 @@ +namespace Stub\Interfaces; + +interface InterfaceInt +{ + public function set(int val) -> void; + + public function get() -> int; +} diff --git a/stub/interfaces/interfaceintsignature.zep b/stub/interfaces/interfaceintsignature.zep new file mode 100644 index 0000000000..97e4ee7f87 --- /dev/null +++ b/stub/interfaces/interfaceintsignature.zep @@ -0,0 +1,6 @@ +namespace Stub\Interfaces; + +interface InterfaceIntSignature +{ + public function get( obj) -> int; +} diff --git a/tests/Extension/Interfaces/InterfaceMethodSignatureTest.php b/tests/Extension/Interfaces/InterfaceMethodSignatureTest.php new file mode 100644 index 0000000000..8dcd622e91 --- /dev/null +++ b/tests/Extension/Interfaces/InterfaceMethodSignatureTest.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Extension\Interfaces; + +use PHPUnit\Framework\TestCase; +use Stub\Interfaces\ImplementInt; +use Stub\Interfaces\ImplementInterface; + +final class InterfaceMethodSignatureTest extends TestCase +{ + public function testImplementInterfaceInMethodSignature(): void + { + $class = new ImplementInt(); + + $this->assertNull($class->get()); + $class->set(1); + $this->assertSame(1, $class->get()); + $this->assertSame(1, (new ImplementInterface())->get($class)); + } + + public function testImplementInterfaceInMethodSignatureInt(): void + { + $this->expectException(\TypeError::class); + $this->expectExceptionMessageMatches('/must be of (the\s)?type int, bool given/'); + + (new ImplementInt())->set(true); + } + + public function testImplementInterfaceInMethodSignatureInterface(): void + { + $this->expectException(\TypeError::class); + $this->expectExceptionMessageMatches( + '/(must be of type|implement interface) Stub\\\\Interfaces\\\\InterfaceInt, bool given/' + ); + + (new ImplementInterface())->getVoid(true); + } +} diff --git a/tests/Extension/MethodArgsTest.php b/tests/Extension/MethodArgsTest.php index 636cc9fe7e..2dd9fd5c69 100644 --- a/tests/Extension/MethodArgsTest.php +++ b/tests/Extension/MethodArgsTest.php @@ -34,7 +34,7 @@ public function testCallable() $this->test->setCallableStrict($callback); $this->assertSame($callback, $this->test->a); - $this->expectException('\Exception'); + $this->expectException(\InvalidArgumentException::class); $this->test->setCallableStrict(true); } @@ -49,7 +49,7 @@ public function testObject() $this->test->setObjectStrict($obj); $this->assertSame($obj, $this->test->a); - $this->expectException('\Exception'); + $this->expectException(\Throwable::class); $this->test->setObjectStrict(true); } @@ -59,7 +59,11 @@ public function testResource() $this->test->setResourceStrict(STDIN); $this->assertSame(STDIN, $this->test->a); - $this->expectException('\Exception'); + if (version_compare(PHP_VERSION, '8.0.0', '>=')) { + $this->expectException(\TypeError::class); + } else { + $this->expectException(\InvalidArgumentException::class); + } $this->test->setResourceStrict(true); } diff --git a/tests/Extension/Oo/OoParamsStrictTest.php b/tests/Extension/Oo/OoParamsStrictTest.php index 90cbae0f24..c65ad891c6 100644 --- a/tests/Extension/Oo/OoParamsStrictTest.php +++ b/tests/Extension/Oo/OoParamsStrictTest.php @@ -91,6 +91,10 @@ public function testShouldThrowInvalidArgumentExceptionForString() public function testShouldThrowInvalidArgumentExceptionForCallFromZephirLand() { + if (version_compare(PHP_VERSION, '8.0.0', '>=')) { + $this->markTestSkipped('Move types check into fcall, instead of PHP_METHOD'); + } + $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage("Parameter 'name' must be of the type string");