This removes the `NewReceiver` method and moves logic for the `Define`
method from the `Engine` method receiver to `Context`.
Moving the `Define` method was required due to a bug/feature where
destroying a `Context` before all defined Receivers have also been
destroyed causes memory errors. Tying method receiver definitions
to the `Context` lifecycle implicitly fixes this issue.
This approach, however, contains a possible flaw, since class names
in PHP are defined in the global scope (i.e. the `Engine`), and
destroying a defined `Receiver` also removes the class entry for that
name, supposedly across all running contexts.
The `Context.Eval` function invariably creates a `Value` which may
or may not end up being passed to the caller. Keep a reference to
the value and destroy it during `Context.Destroy` at the latest.
Previously, `Context.Eval` relied on Zend's `zend_eval_script` function
for executing arbitrary strings. Unfortunately, the above contains a
curious bit of functionality where the string passed is prepended with
a `return` statement depending on whether or not a zval is passed for
writing the return value.
This, of course breaks all but the simplest scripts, as we always write
the return value to a zval (whether the user calling `Context.Eval` is
to use the return value is another matter entirely).
This commit changes the implementation to a more direct (and therefore
more controllable) approach. Some tests have been changed to cover this
bug.
This will allow for better tests, among other things, since
the previous arrangement did not allow for sub-packages of
engine to be tested individually (due to cyclic dependancy
issues).
Signed-off-by: Alex Palaistras <[email protected]>
This contains extensive API changes for the value package C bindings
as well changes to the receiver package (addition of Destroy method
and other small changes). These changes are mainly to address issues
with PHP7 compatibility, but should also benefit PHP5 targets.
Signed-off-by: Alex Palaistras <[email protected]>
This removes all "#ifdef PHP_MAJOR_VERSION" directives for version-specific
header files per supported PHP version. These headers are included only when
building against the specific PHP version, and are intended to abstract
differences between implementations in a fairly clean way.
This is still a mess of preprocessor directives, however.
This adds support for building against PHP 7 when using the `php7`
build tag (i.e. `go build -tags php7`). PHP 5 support remains the
default and does not need passing any tags, currently, though this
may change at some point.
The code builds and basic tests run, but more advanced tests fail
with "zend_mm_heap corrupted". More to come.
Building against a ZTS-enabled build of PHP uncovered several issues,
including:
* Use of missing `tsrm_ls` value. Added calls to TSRMLS_FETCH() where
needed.
* String keys returned with `value_array_keys` are now duplicated,
and as such are correctly passed (and freed) to the caller.
* Functions `value_array_index_get` and `value_array_key_get`
incorrectly returned references of, rather than copies to, the
values required.
* Method `receiverSet` incorrectly called `Destroy` on the member
value.
This breaks API for the `engine.Define` method, which now expects a
receiver name and corresponding constructor method. The constructor
method accepts a slice of parameters as passed in by the PHP context,
and returns an instantiated receiver.
Receiver files have been moved to their own package.
This feature implements defining PHP classes based on Go method receivers
(of any type). It allows for getting and setting internal properties
(in the case of struct method receivers with publicly-accessible fields)
and calling methods attached to the receiver passed.
Functions for writing, logging and setting headers have been moved from
the context package to the engine package, to better match the layout
expected by the core PHP architecture.