summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Piotrowski <aaron@trowski.com>2015-05-16 15:30:59 -0500
committerAaron Piotrowski <aaron@trowski.com>2015-05-16 15:30:59 -0500
commitd042d0880796cfe99262bb6fa44225e984c63ace (patch)
treeeb428c9c3d43c4ab9c230b86eeaceccd01e42120
parentc9f27ee4227268bc74fc54e0e06102317e614804 (diff)
downloadphp-git-d042d0880796cfe99262bb6fa44225e984c63ace.tar.gz
Remodel exceptions based on Throwable interface
Added Throwable interface that exceptions must implement in order to be thrown. BaseException was removed, EngineException renamed to Error, and TypeException and ParseException renamed to TypeError and ParseError. Exception and Error no longer extend a common base class, rather they both implement the Throwable interface.
-rw-r--r--Zend/zend.c8
-rw-r--r--Zend/zend_exceptions.c216
-rw-r--r--Zend/zend_exceptions.h9
-rw-r--r--Zend/zend_interfaces.c20
-rw-r--r--Zend/zend_interfaces.h1
-rw-r--r--Zend/zend_language_scanner.c10
-rw-r--r--Zend/zend_language_scanner.l10
-rw-r--r--ext/soap/soap.c8
8 files changed, 156 insertions, 126 deletions
diff --git a/Zend/zend.c b/Zend/zend.c
index f262f8b5d7..1c2cfd6c77 100644
--- a/Zend/zend.c
+++ b/Zend/zend.c
@@ -882,7 +882,7 @@ void zenderror(const char *error) /* {{{ */
return;
}
- zend_throw_exception(zend_get_parse_exception(), error, E_PARSE);
+ zend_throw_exception(zend_get_parse_error(), error, E_PARSE);
}
/* }}} */
@@ -1059,7 +1059,7 @@ static void zend_error_va_list(int type, const char *format, va_list args)
va_start(args, format);
#endif
zend_vspprintf(&message, 0, format, args);
- zend_throw_exception(zend_get_engine_exception(), message, type);
+ zend_throw_exception(zend_get_error(), message, type);
efree(message);
#if !defined(HAVE_NORETURN) || defined(HAVE_NORETURN_ALIAS)
va_end(args);
@@ -1318,7 +1318,7 @@ ZEND_API void zend_type_error(const char *format, ...) /* {{{ */
va_start(va, format);
zend_vspprintf(&message, 0, format, va);
- zend_throw_exception(zend_get_type_exception(), message, E_ERROR);
+ zend_throw_exception(zend_get_type_error(), message, E_ERROR);
efree(message);
va_end(va);
} /* }}} */
@@ -1331,7 +1331,7 @@ ZEND_API void zend_internal_type_error(zend_bool throw_exception, const char *fo
va_start(va, format);
zend_vspprintf(&message, 0, format, va);
if (throw_exception) {
- zend_throw_exception(zend_get_type_exception(), message, E_ERROR);
+ zend_throw_exception(zend_get_type_error(), message, E_ERROR);
} else {
zend_error(E_WARNING, message);
}
diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c
index 671c09cd60..484fcdca60 100644
--- a/Zend/zend_exceptions.c
+++ b/Zend/zend_exceptions.c
@@ -30,33 +30,43 @@
#include "zend_dtrace.h"
#include "zend_smart_str.h"
-static zend_class_entry *base_exception_ce;
static zend_class_entry *default_exception_ce;
static zend_class_entry *error_exception_ce;
-static zend_class_entry *engine_exception_ce;
-static zend_class_entry *parse_exception_ce;
-static zend_class_entry *type_exception_ce;
+static zend_class_entry *error_ce;
+static zend_class_entry *parse_error_ce;
+static zend_class_entry *type_error_ce;
static zend_object_handlers default_exception_handlers;
ZEND_API void (*zend_throw_exception_hook)(zval *ex);
+ZEND_API zend_class_entry *zend_get_exception_base(zval *object)
+{
+ if (instanceof_function(Z_OBJCE_P(object), error_ce)) {
+ return error_ce;
+ }
+
+ return default_exception_ce;
+}
+
void zend_exception_set_previous(zend_object *exception, zend_object *add_previous)
{
zval tmp, *previous, zv, *pzv, rv;
+ zend_class_entry *base_ce;
if (exception == add_previous || !add_previous || !exception) {
return;
}
ZVAL_OBJ(&tmp, add_previous);
- if (!instanceof_function(Z_OBJCE(tmp), base_exception_ce)) {
+ if (!instanceof_function(Z_OBJCE(tmp), zend_ce_throwable)) {
zend_error_noreturn(E_CORE_ERROR, "Cannot set non exception as previous exception");
return;
}
ZVAL_OBJ(&zv, exception);
pzv = &zv;
do {
- previous = zend_read_property(base_exception_ce, pzv, "previous", sizeof("previous")-1, 1, &rv);
+ base_ce = zend_get_exception_base(pzv);
+ previous = zend_read_property(base_ce, pzv, "previous", sizeof("previous")-1, 1, &rv);
if (Z_TYPE_P(previous) == IS_NULL) {
- zend_update_property(base_exception_ce, pzv, "previous", sizeof("previous")-1, &tmp);
+ zend_update_property(base_ce, pzv, "previous", sizeof("previous")-1, &tmp);
GC_REFCOUNT(add_previous)--;
return;
}
@@ -110,7 +120,7 @@ ZEND_API void zend_throw_exception_internal(zval *exception) /* {{{ */
}
}
if (!EG(current_execute_data)) {
- if (exception && Z_OBJCE_P(exception) == parse_exception_ce) {
+ if (exception && Z_OBJCE_P(exception) == parse_error_ce) {
return;
}
if(EG(exception)) {
@@ -158,6 +168,7 @@ static zend_object *zend_default_exception_new_ex(zend_class_entry *class_type,
zval obj;
zend_object *object;
zval trace;
+ zend_class_entry *base_ce;
Z_OBJ(obj) = object = zend_objects_new(class_type);
Z_OBJ_HT(obj) = &default_exception_handlers;
@@ -170,15 +181,17 @@ static zend_object *zend_default_exception_new_ex(zend_class_entry *class_type,
array_init(&trace);
}
Z_SET_REFCOUNT(trace, 0);
+
+ base_ce = zend_get_exception_base(&obj);
- if (EXPECTED(class_type != parse_exception_ce)) {
- zend_update_property_string(base_exception_ce, &obj, "file", sizeof("file")-1, zend_get_executed_filename());
- zend_update_property_long(base_exception_ce, &obj, "line", sizeof("line")-1, zend_get_executed_lineno());
+ if (EXPECTED(class_type != parse_error_ce)) {
+ zend_update_property_string(base_ce, &obj, "file", sizeof("file")-1, zend_get_executed_filename());
+ zend_update_property_long(base_ce, &obj, "line", sizeof("line")-1, zend_get_executed_lineno());
} else {
- zend_update_property_string(base_exception_ce, &obj, "file", sizeof("file")-1, zend_get_compiled_filename()->val);
- zend_update_property_long(base_exception_ce, &obj, "line", sizeof("line")-1, zend_get_compiled_lineno());
+ zend_update_property_string(base_ce, &obj, "file", sizeof("file")-1, zend_get_compiled_filename()->val);
+ zend_update_property_long(base_ce, &obj, "line", sizeof("line")-1, zend_get_compiled_lineno());
}
- zend_update_property(base_exception_ce, &obj, "trace", sizeof("trace")-1, &trace);
+ zend_update_property(base_ce, &obj, "trace", sizeof("trace")-1, &trace);
return object;
}
@@ -196,6 +209,12 @@ static zend_object *zend_error_exception_new(zend_class_entry *class_type) /* {{
}
/* }}} */
+static zval *zend_get_exception_property(zval *object, const char *name, size_t name_length, zend_bool silent, zval *rv) /* {{{ */
+{
+ return zend_read_property(zend_get_exception_base(object), object, name, name_length, silent, rv);
+}
+/* }}} */
+
/* {{{ proto Exception Exception::__clone()
Clone the exception object */
ZEND_METHOD(exception, __clone)
@@ -212,25 +231,27 @@ ZEND_METHOD(exception, __construct)
zend_string *message = NULL;
zend_long code = 0;
zval *object, *previous = NULL;
+ zend_class_entry *base_ce;
int argc = ZEND_NUM_ARGS();
- if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc, "|SlO!", &message, &code, &previous, base_exception_ce) == FAILURE) {
+ object = getThis();
+ base_ce = zend_get_exception_base(object);
+
+ if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc, "|SlO!", &message, &code, &previous, base_ce) == FAILURE) {
zend_error(E_EXCEPTION | E_ERROR, "Wrong parameters for Exception([string $exception [, long $code [, Exception $previous = NULL]]])");
return;
}
- object = getThis();
-
if (message) {
- zend_update_property_str(base_exception_ce, object, "message", sizeof("message")-1, message);
+ zend_update_property_str(base_ce, object, "message", sizeof("message")-1, message);
}
if (code) {
- zend_update_property_long(base_exception_ce, object, "code", sizeof("code")-1, code);
+ zend_update_property_long(base_ce, object, "code", sizeof("code")-1, code);
}
if (previous) {
- zend_update_property(base_exception_ce, object, "previous", sizeof("previous")-1, previous);
+ zend_update_property(base_ce, object, "previous", sizeof("previous")-1, previous);
}
}
/* }}} */
@@ -244,8 +265,8 @@ ZEND_METHOD(error_exception, __construct)
zval *object, *previous = NULL;
int argc = ZEND_NUM_ARGS();
size_t message_len, filename_len;
-
- if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc, "|sllslO!", &message, &message_len, &code, &severity, &filename, &filename_len, &lineno, &previous, base_exception_ce) == FAILURE) {
+
+ if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc, "|sllslO!", &message, &message_len, &code, &severity, &filename, &filename_len, &lineno, &previous, default_exception_ce) == FAILURE) {
zend_error(E_EXCEPTION | E_ERROR, "Wrong parameters for ErrorException([string $exception [, long $code, [ long $severity, [ string $filename, [ long $lineno [, Exception $previous = NULL]]]]]])");
return;
}
@@ -253,25 +274,25 @@ ZEND_METHOD(error_exception, __construct)
object = getThis();
if (message) {
- zend_update_property_string(base_exception_ce, object, "message", sizeof("message")-1, message);
+ zend_update_property_string(default_exception_ce, object, "message", sizeof("message")-1, message);
}
if (code) {
- zend_update_property_long(base_exception_ce, object, "code", sizeof("code")-1, code);
+ zend_update_property_long(default_exception_ce, object, "code", sizeof("code")-1, code);
}
if (previous) {
- zend_update_property(base_exception_ce, object, "previous", sizeof("previous")-1, previous);
+ zend_update_property(default_exception_ce, object, "previous", sizeof("previous")-1, previous);
}
- zend_update_property_long(base_exception_ce, object, "severity", sizeof("severity")-1, severity);
+ zend_update_property_long(error_exception_ce, object, "severity", sizeof("severity")-1, severity);
if (argc >= 4) {
- zend_update_property_string(base_exception_ce, object, "file", sizeof("file")-1, filename);
+ zend_update_property_string(default_exception_ce, object, "file", sizeof("file")-1, filename);
if (argc < 5) {
lineno = 0; /* invalidate lineno */
}
- zend_update_property_long(base_exception_ce, object, "line", sizeof("line")-1, lineno);
+ zend_update_property_long(default_exception_ce, object, "line", sizeof("line")-1, lineno);
}
}
/* }}} */
@@ -282,9 +303,9 @@ ZEND_METHOD(error_exception, __construct)
}
#define GET_PROPERTY(object, name) \
- zend_read_property(base_exception_ce, (object), name, sizeof(name) - 1, 0, &rv)
+ zend_get_exception_property((object), name, sizeof(name) - 1, 0, &rv)
#define GET_PROPERTY_SILENT(object, name) \
- zend_read_property(base_exception_ce, (object), name, sizeof(name) - 1, 1, &rv)
+ zend_get_exception_property((object), name, sizeof(name) - 1, 1, &rv)
/* {{{ proto string Exception::getFile()
Get the file in which the exception occurred */
@@ -551,12 +572,17 @@ ZEND_METHOD(exception, getTraceAsString)
{
zval *trace, *frame, rv;
zend_ulong index;
+ zval *object;
+ zend_class_entry *base_ce;
smart_str str = {0};
uint32_t num = 0;
DEFAULT_0_PARAMS;
+
+ object = getThis();
+ base_ce = zend_get_exception_base(object);
- trace = zend_read_property(base_exception_ce, getThis(), "trace", sizeof("trace")-1, 1, &rv);
+ trace = zend_read_property(base_ce, getThis(), "trace", sizeof("trace")-1, 1, &rv);
if (Z_TYPE_P(trace) != IS_ARRAY) {
RETURN_FALSE;
}
@@ -618,6 +644,7 @@ zend_string *zend_strpprintf(size_t max_len, const char *format, ...) /* {{{ */
ZEND_METHOD(exception, __toString)
{
zval trace, *exception;
+ zend_class_entry *base_ce;
zend_string *str;
zend_fcall_info fci;
zval fname, rv;
@@ -675,9 +702,12 @@ ZEND_METHOD(exception, __toString)
}
zval_dtor(&fname);
+ exception = getThis();
+ base_ce = zend_get_exception_base(exception);
+
/* We store the result in the private property string so we can access
* the result in uncaught exception handlers without memleaks. */
- zend_update_property_str(base_exception_ce, getThis(), "string", sizeof("string")-1, str);
+ zend_update_property_str(base_ce, exception, "string", sizeof("string")-1, str);
RETURN_STR(str);
}
@@ -734,66 +764,48 @@ void zend_register_default_exception(void) /* {{{ */
zend_class_entry ce;
zend_property_info *prop;
- INIT_CLASS_ENTRY(ce, "BaseException", default_exception_functions);
- base_exception_ce = zend_register_internal_class(&ce);
- base_exception_ce->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
- base_exception_ce->create_object = NULL;
+ INIT_CLASS_ENTRY(ce, "Exception", default_exception_functions);
+ default_exception_ce = zend_register_internal_class_ex(&ce, NULL);
+ default_exception_ce->create_object = zend_default_exception_new;
memcpy(&default_exception_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
default_exception_handlers.clone_obj = NULL;
-
- zend_declare_property_string(base_exception_ce, "message", sizeof("message")-1, "", ZEND_ACC_PROTECTED);
- zend_declare_property_string(base_exception_ce, "string", sizeof("string")-1, "", ZEND_ACC_PRIVATE);
- zend_declare_property_long(base_exception_ce, "code", sizeof("code")-1, 0, ZEND_ACC_PROTECTED);
- zend_declare_property_null(base_exception_ce, "file", sizeof("file")-1, ZEND_ACC_PROTECTED);
- zend_declare_property_null(base_exception_ce, "line", sizeof("line")-1, ZEND_ACC_PROTECTED);
- zend_declare_property_null(base_exception_ce, "trace", sizeof("trace")-1, ZEND_ACC_PRIVATE);
- zend_declare_property_null(base_exception_ce, "previous", sizeof("previous")-1, ZEND_ACC_PRIVATE);
-
- INIT_CLASS_ENTRY(ce, "Exception", NULL);
- default_exception_ce = zend_register_internal_class_ex(&ce, base_exception_ce);
- default_exception_ce->create_object = zend_default_exception_new;
-
- /* A trick, to make visible private properties of BaseException */
- ZEND_HASH_FOREACH_PTR(&default_exception_ce->properties_info, prop) {
- if (prop->flags & ZEND_ACC_SHADOW) {
- if (prop->name->len == sizeof("\0BaseException\0string")-1) {
- prop->flags &= ~ZEND_ACC_SHADOW;
- prop->flags |= ZEND_ACC_PRIVATE;
- prop->ce = default_exception_ce;
- } else if (prop->name->len == sizeof("\0BaseException\0trace")-1) {
- prop->flags &= ~ZEND_ACC_SHADOW;
- prop->flags |= ZEND_ACC_PRIVATE;
- prop->ce = default_exception_ce;
- } else if (prop->name->len == sizeof("\0BaseException\0previous")-1) {
- prop->flags &= ~ZEND_ACC_SHADOW;
- prop->flags |= ZEND_ACC_PRIVATE;
- prop->ce = default_exception_ce;
- }
- }
- } ZEND_HASH_FOREACH_END();
+ zend_class_implements(default_exception_ce, 1, zend_ce_throwable);
+
+ zend_declare_property_string(default_exception_ce, "message", sizeof("message")-1, "", ZEND_ACC_PROTECTED);
+ zend_declare_property_string(default_exception_ce, "string", sizeof("string")-1, "", ZEND_ACC_PRIVATE);
+ zend_declare_property_long(default_exception_ce, "code", sizeof("code")-1, 0, ZEND_ACC_PROTECTED);
+ zend_declare_property_null(default_exception_ce, "file", sizeof("file")-1, ZEND_ACC_PROTECTED);
+ zend_declare_property_null(default_exception_ce, "line", sizeof("line")-1, ZEND_ACC_PROTECTED);
+ zend_declare_property_null(default_exception_ce, "trace", sizeof("trace")-1, ZEND_ACC_PRIVATE);
+ zend_declare_property_null(default_exception_ce, "previous", sizeof("previous")-1, ZEND_ACC_PRIVATE);
INIT_CLASS_ENTRY(ce, "ErrorException", error_exception_functions);
error_exception_ce = zend_register_internal_class_ex(&ce, default_exception_ce);
error_exception_ce->create_object = zend_error_exception_new;
zend_declare_property_long(error_exception_ce, "severity", sizeof("severity")-1, E_ERROR, ZEND_ACC_PROTECTED);
- INIT_CLASS_ENTRY(ce, "EngineException", NULL);
- engine_exception_ce = zend_register_internal_class_ex(&ce, base_exception_ce);
- engine_exception_ce->create_object = zend_default_exception_new;
-
- INIT_CLASS_ENTRY(ce, "ParseException", NULL);
- parse_exception_ce = zend_register_internal_class_ex(&ce, base_exception_ce);
- parse_exception_ce->create_object = zend_default_exception_new;
+ INIT_CLASS_ENTRY(ce, "Error", default_exception_functions);
+ error_ce = zend_register_internal_class_ex(&ce, NULL);
+ error_ce->create_object = zend_default_exception_new;
+ memcpy(&default_exception_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
+ default_exception_handlers.clone_obj = NULL;
+ zend_class_implements(error_ce, 1, zend_ce_throwable);
+
+ zend_declare_property_string(error_ce, "message", sizeof("message")-1, "", ZEND_ACC_PROTECTED);
+ zend_declare_property_string(error_ce, "string", sizeof("string")-1, "", ZEND_ACC_PRIVATE);
+ zend_declare_property_long(error_ce, "code", sizeof("code")-1, 0, ZEND_ACC_PROTECTED);
+ zend_declare_property_null(error_ce, "file", sizeof("file")-1, ZEND_ACC_PROTECTED);
+ zend_declare_property_null(error_ce, "line", sizeof("line")-1, ZEND_ACC_PROTECTED);
+ zend_declare_property_null(error_ce, "trace", sizeof("trace")-1, ZEND_ACC_PRIVATE);
+ zend_declare_property_null(error_ce, "previous", sizeof("previous")-1, ZEND_ACC_PRIVATE);
- INIT_CLASS_ENTRY(ce, "TypeException", NULL);
- type_exception_ce = zend_register_internal_class_ex(&ce, engine_exception_ce);
- type_exception_ce->create_object = zend_default_exception_new;
-}
-/* }}} */
+ INIT_CLASS_ENTRY(ce, "ParseError", NULL);
+ parse_error_ce = zend_register_internal_class_ex(&ce, error_ce);
+ parse_error_ce->create_object = zend_default_exception_new;
-ZEND_API zend_class_entry *zend_exception_get_base(void) /* {{{ */
-{
- return base_exception_ce;
+ INIT_CLASS_ENTRY(ce, "TypeError", NULL);
+ type_error_ce = zend_register_internal_class_ex(&ce, error_ce);
+ type_error_ce->create_object = zend_default_exception_new;
}
/* }}} */
@@ -809,21 +821,21 @@ ZEND_API zend_class_entry *zend_get_error_exception(void) /* {{{ */
}
/* }}} */
-ZEND_API zend_class_entry *zend_get_engine_exception(void) /* {{{ */
+ZEND_API zend_class_entry *zend_get_error(void) /* {{{ */
{
- return engine_exception_ce;
+ return error_ce;
}
/* }}} */
-ZEND_API zend_class_entry *zend_get_parse_exception(void) /* {{{ */
+ZEND_API zend_class_entry *zend_get_parse_error(void) /* {{{ */
{
- return parse_exception_ce;
+ return parse_error_ce;
}
/* }}} */
-ZEND_API zend_class_entry *zend_get_type_exception(void) /* {{{ */
+ZEND_API zend_class_entry *zend_get_type_error(void) /* {{{ */
{
- return type_exception_ce;
+ return type_error_ce;
}
/* }}} */
@@ -833,8 +845,8 @@ ZEND_API zend_object *zend_throw_exception(zend_class_entry *exception_ce, const
zval ex;
if (exception_ce) {
- if (!instanceof_function(exception_ce, base_exception_ce)) {
- zend_error(E_NOTICE, "Exceptions must be derived from the Exception base class");
+ if (!instanceof_function(exception_ce, zend_ce_throwable)) {
+ zend_error(E_NOTICE, "Exceptions must implement Throwable");
exception_ce = default_exception_ce;
}
} else {
@@ -844,10 +856,10 @@ ZEND_API zend_object *zend_throw_exception(zend_class_entry *exception_ce, const
if (message) {
- zend_update_property_string(base_exception_ce, &ex, "message", sizeof("message")-1, message);
+ zend_update_property_string(exception_ce, &ex, "message", sizeof("message")-1, message);
}
if (code) {
- zend_update_property_long(base_exception_ce, &ex, "code", sizeof("code")-1, code);
+ zend_update_property_long(exception_ce, &ex, "code", sizeof("code")-1, code);
}
zend_throw_exception_internal(&ex);
@@ -875,7 +887,7 @@ ZEND_API zend_object *zend_throw_error_exception(zend_class_entry *exception_ce,
zval ex;
zend_object *obj = zend_throw_exception(exception_ce, message, code);
ZVAL_OBJ(&ex, obj);
- zend_update_property_long(base_exception_ce, &ex, "severity", sizeof("severity")-1, severity);
+ zend_update_property_long(error_exception_ce, &ex, "severity", sizeof("severity")-1, severity);
return obj;
}
/* }}} */
@@ -908,13 +920,13 @@ ZEND_API void zend_exception_error(zend_object *ex, int severity) /* {{{ */
ZVAL_OBJ(&exception, ex);
ce_exception = Z_OBJCE(exception);
EG(exception) = NULL;
- if (ce_exception == parse_exception_ce || ce_exception == type_exception_ce) {
+ if (ce_exception == parse_error_ce || ce_exception == type_error_ce) {
zend_string *message = zval_get_string(GET_PROPERTY(&exception, "message"));
zend_string *file = zval_get_string(GET_PROPERTY_SILENT(&exception, "file"));
zend_long line = zval_get_long(GET_PROPERTY_SILENT(&exception, "line"));
zend_long code = zval_get_long(GET_PROPERTY_SILENT(&exception, "code"));
- if (ce_exception == type_exception_ce && strstr(message->val, ", called in ")) {
+ if (ce_exception == type_error_ce && strstr(message->val, ", called in ")) {
zend_error_helper(code, file->val, line, "%s and defined", message->val);
} else {
zend_error_helper(code, file->val, line, "%s", message->val);
@@ -922,7 +934,7 @@ ZEND_API void zend_exception_error(zend_object *ex, int severity) /* {{{ */
zend_string_release(file);
zend_string_release(message);
- } else if (instanceof_function(ce_exception, base_exception_ce)) {
+ } else if (instanceof_function(ce_exception, default_exception_ce) || instanceof_function(ce_exception, error_ce)) {
zval tmp, rv;
zend_string *str, *file = NULL;
zend_long line = 0;
@@ -932,7 +944,7 @@ ZEND_API void zend_exception_error(zend_object *ex, int severity) /* {{{ */
if (Z_TYPE(tmp) != IS_STRING) {
zend_error(E_WARNING, "%s::__toString() must return a string", ce_exception->name->val);
} else {
- zend_update_property_string(base_exception_ce, &exception, "string", sizeof("string")-1, EG(exception) ? ce_exception->name->val : Z_STRVAL(tmp));
+ zend_update_property_string(zend_get_exception_base(&exception), &exception, "string", sizeof("string")-1, EG(exception) ? ce_exception->name->val : Z_STRVAL(tmp));
}
}
zval_ptr_dtor(&tmp);
@@ -942,10 +954,8 @@ ZEND_API void zend_exception_error(zend_object *ex, int severity) /* {{{ */
ZVAL_OBJ(&zv, EG(exception));
/* do the best we can to inform about the inner exception */
- if (instanceof_function(ce_exception, base_exception_ce)) {
- file = zval_get_string(GET_PROPERTY_SILENT(&zv, "file"));
- line = zval_get_long(GET_PROPERTY_SILENT(&zv, "line"));
- }
+ file = zval_get_string(GET_PROPERTY_SILENT(&zv, "file"));
+ line = zval_get_long(GET_PROPERTY_SILENT(&zv, "line"));
zend_error_va(E_WARNING, (file && file->len > 0) ? file->val : NULL, line,
"Uncaught %s in exception handling during call to %s::__tostring()",
@@ -983,8 +993,8 @@ ZEND_API void zend_throw_exception_object(zval *exception) /* {{{ */
exception_ce = Z_OBJCE_P(exception);
- if (!exception_ce || !instanceof_function(exception_ce, base_exception_ce)) {
- zend_error(E_EXCEPTION | E_ERROR, "Exceptions must be valid objects derived from the Exception base class");
+ if (!exception_ce || !instanceof_function(exception_ce, zend_ce_throwable)) {
+ zend_error(E_EXCEPTION | E_ERROR, "Exceptions must be valid objects implementing Throwable");
return;
}
zend_throw_exception_internal(exception);
diff --git a/Zend/zend_exceptions.h b/Zend/zend_exceptions.h
index e2c1f1fac7..bae4c35a78 100644
--- a/Zend/zend_exceptions.h
+++ b/Zend/zend_exceptions.h
@@ -34,12 +34,13 @@ ZEND_API void zend_throw_exception_internal(zval *exception);
void zend_register_default_exception(void);
-ZEND_API zend_class_entry *zend_exception_get_base(void);
+ZEND_API zend_class_entry *zend_get_exception_base(zval *object);
+
ZEND_API zend_class_entry *zend_exception_get_default(void);
ZEND_API zend_class_entry *zend_get_error_exception(void);
-ZEND_API zend_class_entry *zend_get_engine_exception(void);
-ZEND_API zend_class_entry *zend_get_parse_exception(void);
-ZEND_API zend_class_entry *zend_get_type_exception(void);
+ZEND_API zend_class_entry *zend_get_error(void);
+ZEND_API zend_class_entry *zend_get_parse_error(void);
+ZEND_API zend_class_entry *zend_get_type_error(void);
ZEND_API void zend_register_default_classes(void);
/* exception_ce NULL or zend_exception_get_default() or a derived class
diff --git a/Zend/zend_interfaces.c b/Zend/zend_interfaces.c
index 54f8f8c117..2b8f8a25bc 100644
--- a/Zend/zend_interfaces.c
+++ b/Zend/zend_interfaces.c
@@ -28,6 +28,7 @@ ZEND_API zend_class_entry *zend_ce_aggregate;
ZEND_API zend_class_entry *zend_ce_iterator;
ZEND_API zend_class_entry *zend_ce_arrayaccess;
ZEND_API zend_class_entry *zend_ce_serializable;
+ZEND_API zend_class_entry *zend_ce_throwable;
/* {{{ zend_call_method
Only returns the returned zval if retval_ptr != NULL */
@@ -502,6 +503,19 @@ static int zend_implement_serializable(zend_class_entry *interface, zend_class_e
}
/* }}}*/
+/* {{{ zend_implement_traversable */
+static int zend_implement_throwable(zend_class_entry *interface, zend_class_entry *class_type)
+{
+ if (instanceof_function(class_type, zend_exception_get_default()) || instanceof_function(class_type, zend_get_error())) {
+ return SUCCESS;
+ }
+ zend_error_noreturn(E_CORE_ERROR, "Class %s cannot implement interface %s, extend Exception instead",
+ class_type->name->val,
+ interface->name->val);
+ return FAILURE;
+}
+/* }}} */
+
/* {{{ function tables */
const zend_function_entry zend_funcs_aggregate[] = {
ZEND_ABSTRACT_ME(iterator, getIterator, NULL)
@@ -551,6 +565,8 @@ const zend_function_entry zend_funcs_serializable[] = {
};
/* }}} */
+const zend_function_entry *zend_funcs_throwable = NULL;
+
#define REGISTER_ITERATOR_INTERFACE(class_name, class_name_str) \
{\
zend_class_entry ce;\
@@ -575,7 +591,9 @@ ZEND_API void zend_register_interfaces(void)
REGISTER_ITERATOR_INTERFACE(arrayaccess, ArrayAccess);
- REGISTER_ITERATOR_INTERFACE(serializable, Serializable)
+ REGISTER_ITERATOR_INTERFACE(serializable, Serializable);
+
+ REGISTER_ITERATOR_INTERFACE(throwable, Throwable);
}
/* }}} */
diff --git a/Zend/zend_interfaces.h b/Zend/zend_interfaces.h
index 8a8e0ce988..daf0aae5dc 100644
--- a/Zend/zend_interfaces.h
+++ b/Zend/zend_interfaces.h
@@ -31,6 +31,7 @@ extern ZEND_API zend_class_entry *zend_ce_aggregate;
extern ZEND_API zend_class_entry *zend_ce_iterator;
extern ZEND_API zend_class_entry *zend_ce_arrayaccess;
extern ZEND_API zend_class_entry *zend_ce_serializable;
+extern ZEND_API zend_class_entry *zend_ce_throwable;
typedef struct _zend_user_iterator {
zend_object_iterator it;
diff --git a/Zend/zend_language_scanner.c b/Zend/zend_language_scanner.c
index abf93d587c..e3b2de1a79 100644
--- a/Zend/zend_language_scanner.c
+++ b/Zend/zend_language_scanner.c
@@ -998,7 +998,7 @@ static int zend_scan_escape_string(zval *zendlval, char *str, int len, char quot
}
if (!valid) {
- zend_throw_exception(zend_get_parse_exception(),
+ zend_throw_exception(zend_get_parse_error(),
"Invalid UTF-8 codepoint escape sequence", E_PARSE);
zval_ptr_dtor(zendlval);
return FAILURE;
@@ -1009,7 +1009,7 @@ static int zend_scan_escape_string(zval *zendlval, char *str, int len, char quot
/* per RFC 3629, UTF-8 can only represent 21 bits */
if (codepoint > 0x10FFFF || errno) {
- zend_throw_exception(zend_get_parse_exception(),
+ zend_throw_exception(zend_get_parse_error(),
"Invalid UTF-8 codepoint escape sequence: Codepoint too large", E_PARSE);
zval_ptr_dtor(zendlval);
return FAILURE;
@@ -2720,7 +2720,7 @@ yy136:
* Because the lexing itself doesn't do that for us
*/
if (end != yytext + yyleng) {
- zend_throw_exception(zend_get_parse_exception(), "Invalid numeric literal", E_PARSE);
+ zend_throw_exception(zend_get_parse_error(), "Invalid numeric literal", E_PARSE);
return T_ERROR;
}
} else {
@@ -2736,7 +2736,7 @@ yy136:
}
/* Also not an assert for the same reason */
if (end != yytext + yyleng) {
- zend_throw_exception(zend_get_parse_exception(),
+ zend_throw_exception(zend_get_parse_error(),
"Invalid numeric literal", E_PARSE);
return T_ERROR;
}
@@ -2745,7 +2745,7 @@ yy136:
}
/* Also not an assert for the same reason */
if (end != yytext + yyleng) {
- zend_throw_exception(zend_get_parse_exception(), "Invalid numeric literal", E_PARSE);
+ zend_throw_exception(zend_get_parse_error(), "Invalid numeric literal", E_PARSE);
return T_ERROR;
}
}
diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l
index fdba4b9f07..1204287ad9 100644
--- a/Zend/zend_language_scanner.l
+++ b/Zend/zend_language_scanner.l
@@ -996,7 +996,7 @@ static int zend_scan_escape_string(zval *zendlval, char *str, int len, char quot
}
if (!valid) {
- zend_throw_exception(zend_get_parse_exception(),
+ zend_throw_exception(zend_get_parse_error(),
"Invalid UTF-8 codepoint escape sequence", E_PARSE);
zval_ptr_dtor(zendlval);
return FAILURE;
@@ -1007,7 +1007,7 @@ static int zend_scan_escape_string(zval *zendlval, char *str, int len, char quot
/* per RFC 3629, UTF-8 can only represent 21 bits */
if (codepoint > 0x10FFFF || errno) {
- zend_throw_exception(zend_get_parse_exception(),
+ zend_throw_exception(zend_get_parse_error(),
"Invalid UTF-8 codepoint escape sequence: Codepoint too large", E_PARSE);
zval_ptr_dtor(zendlval);
return FAILURE;
@@ -1635,7 +1635,7 @@ NEWLINE ("\r"|"\n"|"\r\n")
* Because the lexing itself doesn't do that for us
*/
if (end != yytext + yyleng) {
- zend_throw_exception(zend_get_parse_exception(), "Invalid numeric literal", E_PARSE);
+ zend_throw_exception(zend_get_parse_error(), "Invalid numeric literal", E_PARSE);
return T_ERROR;
}
} else {
@@ -1651,7 +1651,7 @@ NEWLINE ("\r"|"\n"|"\r\n")
}
/* Also not an assert for the same reason */
if (end != yytext + yyleng) {
- zend_throw_exception(zend_get_parse_exception(),
+ zend_throw_exception(zend_get_parse_error(),
"Invalid numeric literal", E_PARSE);
return T_ERROR;
}
@@ -1660,7 +1660,7 @@ NEWLINE ("\r"|"\n"|"\r\n")
}
/* Also not an assert for the same reason */
if (end != yytext + yyleng) {
- zend_throw_exception(zend_get_parse_exception(), "Invalid numeric literal", E_PARSE);
+ zend_throw_exception(zend_get_parse_error(), "Invalid numeric literal", E_PARSE);
return T_ERROR;
}
}
diff --git a/ext/soap/soap.c b/ext/soap/soap.c
index 120274b272..e6c7e5f4cd 100644
--- a/ext/soap/soap.c
+++ b/ext/soap/soap.c
@@ -1496,10 +1496,10 @@ static void _soap_server_exception(soapServicePtr service, sdlFunctionPtr functi
ZVAL_OBJ(&exception_object, EG(exception));
if (instanceof_function(Z_OBJCE(exception_object), soap_fault_class_entry)) {
soap_server_fault_ex(function, &exception_object, NULL);
- } else if (instanceof_function(Z_OBJCE(exception_object), zend_get_engine_exception())) {
+ } else if (instanceof_function(Z_OBJCE(exception_object), zend_get_error())) {
if (service->send_errors) {
zval rv;
- zend_string *msg = zval_get_string(zend_read_property(zend_exception_get_base(), &exception_object, "message", sizeof("message")-1, 0, &rv));
+ zend_string *msg = zval_get_string(zend_read_property(zend_get_exception_base(&exception_object), &exception_object, "message", sizeof("message")-1, 0, &rv));
add_soap_fault_ex(&exception_object, this_ptr, "Server", msg->val, NULL, NULL);
zend_string_release(msg);
} else {
@@ -2596,13 +2596,13 @@ static int do_request(zval *this_ptr, xmlDoc *request, char *location, char *act
add_soap_fault(this_ptr, "Client", "SoapClient::__doRequest() failed", NULL, NULL);
ret = FALSE;
} else if (Z_TYPE_P(response) != IS_STRING) {
- if (EG(exception) && instanceof_function(EG(exception)->ce, zend_get_engine_exception())) {
+ if (EG(exception) && instanceof_function(EG(exception)->ce, zend_get_error())) {
zval rv;
zend_string *msg;
zval exception_object;
ZVAL_OBJ(&exception_object, EG(exception));
- msg = zval_get_string(zend_read_property(zend_exception_get_base(), &exception_object, "message", sizeof("message")-1, 0, &rv));
+ msg = zval_get_string(zend_read_property(zend_get_exception_base(&exception_object), &exception_object, "message", sizeof("message")-1, 0, &rv));
/* change class */
EG(exception)->ce = soap_fault_class_entry;
set_soap_fault(&exception_object, NULL, "Client", msg->val, NULL, NULL, NULL);