rfc:propertygetsetsyntax-implementation-details
Differences
This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
rfc:propertygetsetsyntax-implementation-details [2012/12/30 18:35] – created cpriest | rfc:propertygetsetsyntax-implementation-details [2017/09/22 13:28] (current) – external edit 127.0.0.1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
====== Internal Implementation Details for Property Accessors ====== | ====== Internal Implementation Details for Property Accessors ====== | ||
- | * Version: 1.1 (to be updated prior to vote) | + | * Version: 1.2 |
- | * Created: 2012-12-29 | + | * Updated: 2013-01-17 |
* Author: Clint Priest <phpdev at zerocue dot com> | * Author: Clint Priest <phpdev at zerocue dot com> | ||
* Contributors: | * Contributors: | ||
+ | * RFC Document: [[https:// | ||
+ | * The code for this RFC are available here: https:// | ||
- | * RFC Document: [[https:// | + | ==== Overview ==== |
- | * The changes for this RFC are available here: https:// | + | |
- | ===== Internal Implementation ===== | + | The current implementation of property accessors can be thought of as properties which have their read/ |
+ | guarded by accessor functions, the primary changes that permit this functionality to work are all within standard zend object handling | ||
+ | function calls. | ||
- | **Note: These implementation details have not been kept up with the semi-rapidly changing internal implementation and will be updated near the beginning | + | The rest of the code changes are involved in compilation |
- | Accessor information is stored in a new zend_accessor_info struct. | + | Finally |
- | <code c> | + | ==== Memory Structure Changes ==== |
- | typedef struct _zend_accessor_info { | + | |
- | zend_uint flags; | + | |
- | const char *doc_comment; | + | |
- | int doc_comment_len; | + | |
- | zend_function *getter; | + | |
- | zend_function *setter; | + | |
- | zend_function *isset; | + | |
- | zend_function *unset; | + | |
- | } zend_accessor_info; | + | |
- | </ | + | |
- | Internally the accessors are implemented | + | Accessor information is stored |
- | Two new function flags have been defined: | ||
<code c> | <code c> | ||
- | #define ZEND_ACC_READONLY | + | typedef struct _zend_property_info { |
- | #define ZEND_ACC_WRITEONLY | + | /* ... */ |
+ | union _zend_function **accs; | ||
+ | } zend_property_info; | ||
</ | </ | ||
- | An additional byte was added to zend_internal_function: | + | The memory space is only allocated for the array of pointers if a property has accessors. |
- | <code c> | + | |
- | zend_uchar purpose; | + | The correct accessor is referenced by using an enum value from the following new enum: |
- | </ | + | |
- | This was in lieu of using 4 additional flag values for which there was not room. There are presently five states purpose can be in, they are: | ||
<code c> | <code c> | ||
- | #define ZEND_FNP_UNDEFINED 0 /* No special purpose function | + | /* Offsets into zend_property_info-> |
- | #define ZEND_FNP_PROP_GETTER 1 / | + | typedef enum { |
- | #define ZEND_FNP_PROP_SETTER 2 / | + | ZEND_ACCESSOR_GET, |
- | #define ZEND_FNP_PROP_ISSETTER 3 / | + | ZEND_ACCESSOR_SET, |
- | # | + | ZEND_ACCESSOR_ISSET, |
+ | ZEND_ACCESSOR_UNSET, | ||
+ | } zend_acc_index; | ||
+ | # | ||
</ | </ | ||
- | * %%__get()%%, %%__set()%%, %%__isset()%% and %%__unset()%% guards were used and the functionality | + | The '' |
+ | |||
+ | ==== Compilation Changes ==== | ||
+ | |||
+ | During compilation if a guarded property is parsed it will create the given property, allocate the function pointer array | ||
+ | and begin parsing the accessor code within the context of a function. | ||
+ | |||
+ | Note that these functions are not methods of the class entry and are only referenced through the zend_function pointers of the | ||
+ | property_info structure, this also means that they may not be called directly by userland code, only through accessing the | ||
+ | property using ordinary property access syntax. | ||
+ | |||
+ | ==== zend_object_handler.c Changes ==== | ||
+ | |||
+ | Each of the functions that handled read/ | ||
+ | the property and if so checks that there is an accessor for the specific action | ||
+ | handles the situation accordingly. | ||
+ | |||
+ | |||
+ | Much of the pre/post magic call code that %%__get/ | ||
+ | The new accessors also utilize these functions so that all pre/post condition handling | ||
+ | |||
+ | |||
+ | A new function flag was added '' | ||
+ | accessors | ||
+ | recursion is not called from the context of the validly scoped accessor. | ||
+ | |||
+ | |||
+ | For example a get accessor is allowed to get it's own value and does not produce a warning, but instead the ordinary property access routines occur while attempts to read that property from a context other than the get accessor will emit a warning and the value will be returned as NULL. | ||
- | * Error producing lines have been modified to check the function for ZEND_ACC_IS_ACCESSOR mask with more appropriate | + | * Error producing lines have been modified to produce a useful |
==== Static Accessors ==== | ==== Static Accessors ==== | ||
- | There was no built-in mechanism to handle custom get/ | + | Static accessors were abandoned due to the unique way in which static properties |
+ | left for another RFC to refactor | ||
- | This yielded the possibility that a getter call was being made while it should not be allowed (if there was no getter defined) and so pass_two() was changed | + | ==== Tests ==== |
+ | Roughly 80 additional tests were added to test the new accessors functionality, | ||
rfc/propertygetsetsyntax-implementation-details.1356892530.txt.gz · Last modified: 2017/09/22 13:28 (external edit)