All notable changes to this project will be documented in this file.
The format based on Keep a Changelog and this project adheres to Semantic Versioning.
- Added a warning for unrecognized top-level settings in
config.json#2449 - Added a report for an unrecognized key in the
warningsoroptimizationssection, and for an unrecognized-W,-w,-for-fno-flag #2727 - Added an opt-in
<Ns>\Bufferkernel class holding a fixed-size contiguous C array of doubles or integers, readable from C as a raw pointer #2721 - Added a kernel fast path so
buffer[i]in Zephir source reads and writes the element directly instead of dispatchingoffsetGet()oroffsetSet()#2721 - Added support for capturing a method parameter by reference in a closure
use (&x)clause #2668
- Fixed a value written through a
use (&x)capture never releasing the one it replaced #2668 - Fixed a
use (&x)capture inside a nested closure being attributed to a same-named parameter of the enclosing method #2668 - Fixed a static property read and a by-reference function argument writing over a
use (&x)capture instead of into its shared slot #2668 - Fixed a compiler warning being discarded in silence when its key was not registered #2727
- Fixed
non-valid-unset,non-valid-require,non-valid-require-onceandextra-parenthesesnever printing #2727 - Fixed
invalid-array-indexandnon-valid-objectupdatebeing raised under an unregistered key #2727 - Fixed a
warningskey omitted fromconfig.jsonlosing its default instead of keeping it #2727 - Fixed the non-object property increment warning naming the wrong operation #2727
- Fixed
int,uint,long,ulong,doubleandcharextension globals not registering a php.ini directive #2449 - Fixed a string extension global's php.ini directive never reaching the global #2449
- Fixed php.ini values for extension globals being discarded at the start of every request #2449
- Fixed
globals_set()on a namespaced extension global leaking into the next request #2449 - Fixed an
intextension global being declared as a Cintinstead ofzend_long#2449 - Fixed
ZEPHIR_USE_PHP_JSONnever being defined on PHP 8.4 and 8.5, where php-src no longer declaresHAVE_JSON - Fixed a called method name being lower-cased at code generation, so
__call()and__callStatic()now receive the name as it was written at the call site, as they do in PHP #2715 - Fixed a method name held in a variable being lower-cased again at runtime by the call macros #2715
- Fixed a call to an undefined method or function being reported with the lower-cased name instead of the spelling at the call site #2715
- Fixed
.=rejecting adoubleorbooloperand on astringorvarleft-hand side #2664 - Fixed
.= nullleaving the left operand unconverted instead of turning it into a string #2664 - Fixed
.=on an object property overwriting it instead of appending for every operand but a string #2664 - Fixed
.=on a static property overwriting it instead of appending for a literal operand #2664 - Fixed the
.operator rejecting aboolorcharoperand #2664 - Fixed
.=rejecting an array operand on a local variable, where PHP appendsArrayand raisesArray to string conversion#2664
- Added PHP attributes on a class, interface, trait, property, class constant, method and parameter, reported by Reflection as they are for a PHP class #2466
- Added
#[\Attribute]support, so a Zephir class can be used as an attribute class #2466 - Added PHP attributes on a top-level function and its parameters. On a ZTS PHP up to 8.2 a named argument of a function attribute is reported positionally, because php-src's
function_copy_ctor()copies an attribute argument's value without its name; php-src 8.3 removed that copy and reports the name #2466
- Attribute arguments are folded at compile time, so an argument that is not a constant expression is a compile error #2466
- Raised the minimum
ext-zephir_parserto 2.8.0 for the attribute grammar #2466 - A call to an undefined function or method now throws
Errorwith PHP's own message and raises no warning first, instead ofRuntimeException#2712
- Removed the
is_private_property()builtin, whose optimizer emitted a kernel function that does not exist #2712
- Fixed the first write or unset of an array property leaking the separated array, and every object it held, because the dup's only reference was dropped before the release #2698
- Fixed the persistent keys of an array class constant or array property default being freed by a copy written with a runtime built key, which corrupted the heap #2699
- Fixed
unsetof a literal offset on a property leaking the offset and emitting the unset twice, which gave anArrayAccessproperty twooffsetUnset()calls #2702 - Fixed
unsetof an offset held in a nativeintvariable not compiling #2702 - Fixed
unsetof an offset on a plain object, on a reference, and from PHP 8.1 on a scalar orfalse, which stayed silent where PHP reports an error #2702 - Fixed a literal numeric string array offset not resolving to the integer key PHP resolves it to, so
a["3"]anda[3]now name the same element #2708 - Fixed three duplicated code generation branches emitting a string array offset with a length one byte too long #2708
- Fixed
let {"name"} = valueemitting a kernel function removed in 0.18.0, so the generated C did not compile #2710 - Fixed reading a class constant with
static-constant-class-foldingoff emitting an undeclared kernel function, and a value where its address was required #2711 - Fixed an unreachable variable defaults path that called an undefined
add_slashes(), by deleting it #2707 - Fixed a method with an empty or comment only body never releasing the memory frame its parameter conversion opened, which retained 232 to 288 bytes per call #2716
- Fixed a
trywithout acatchclause never releasing its memory frame when its body throws, since the exception is cleared and control carries on #2716
- Added PHP compatible string offsets, so reading, writing,
isset(),empty()andunset()on a string behave as they do in PHP, including negative offsets, out of range warnings, dynamically typed sources andfor c in s#760 - Added an
unassigned-variablewarning, on by default, for a local that is read but never assigned #2654
- Widened the
conditional-initializationwarning to every local that can be read before it is assigned, instead of only one assigned exactly once in a deeper branch #2679
- Fixed
Closure::bindTo(),Closure::bind()andClosure::call()dropping a closure'suse (...)captures, which read back asnullor crashed the process #2667 - Fixed
var_dump()andprint_r()of a closure crashing the process on PHP 8.4 and later, and reporting the internal capture carrier as$thisinstead of the enclosing object on every version #2667 - Fixed a compile error being replaced by a deprecation notice on PHP 8.4 and later, by marking six implicitly nullable parameters as nullable and letting a deprecation report as PHP reports it #2663
- Fixed a by-reference call argument reading a copy of the container instead of its storage slot, which lost or aliased a write to a shared array, reported a missing element PHP creates, and freed the property's array when the callee replaced its argument #2691
- Fixed a by-reference subscript argument borrowing the container value, which lost the write whenever the value was shared and leaked the
offsetGet()result for anArrayAccesscontainer #2691 - Fixed a read-only subscript read of an
ArrayAccessobject releasing the valueoffsetGet()owns, which leaked 96 bytes per call or corrupted the heap, and limited the read-only shortcut to a container proven to hold a native array #2682 - Fixed
explode()returning thelimit = 2result for a limit of0,1or negative, and looping forever on an empty separator where PHP throwsValueError#2674 - Fixed
fetchandempty()on anArrayAccessobject releasing the string offset beforeoffsetGet()received it, so the object was silently handed the keyoffsetget#2656 - Fixed the array
issethelpers never releasing theoffsetExists()return value, and holding no reference to the container across the two userland calls, as PHP's ownzend_std_read_dimension()does #2656 - Fixed
unset obj->propertyleaking the property name string on every call #2656 - Fixed a leaked exception instance when a
throwcannot construct its exception, a leaked callable when an internal call names an unknown function, and an uninitialized return slot in thezephir_return_call_*()helpers #2656 - Fixed a declared but never assigned variable reaching userland as an uninitialized zval, printed by
var_dump()asUNKNOWN:0, where PHP evaluates an unset variable asnull#2654 - Fixed a variable assigned only inside a conditional branch reaching userland as an uninitialized zval on a path that skips the assignment #2679
- Fixed the
zephir_array_*_long()helpers truncating a negative or large index to 32 bits on Windows, whereunsigned longis narrower thanzend_long, sos[-1]read index 4294967295 and a write tried to grow the string to 4 GB #2666 - Fixed Zephir
long/ulongmapping to a Clong, 32-bit on Windows, so a 64-bit value truncated andZ_PARAM_LONG()stored 8 bytes into a 4-byte local #2666 - Fixed the kernel signatures that carry a PHP integer (
zephir_get_intval_ex(), the comparison, division and modulo helpers,zephir_substr(),zephir_fast_explode(),zephir_preg_match()and the multi-dimensional array key) using a Clong#2666 - Fixed a multi-dimensional array index reaching
zephir_array_update_multi()as a Cintwhere the callee reads azend_long, soa[0][1]produced keys such as 140733193388033 on Windows #2666 - Fixed a
uint/ulongmulti-dimensional array index being passed by address, so the pointer value became the array key #2666 - Fixed six
zephir_safe_mod_*()helpers being declared and emitted but never defined, so any%with a float operand died at load withundefined symbol#2666 - Fixed
%yielding a float instead of anint, which lost every result above 2^53 #2666 - Fixed
/ 0and% 0raising anE_WARNINGand returning 0 instead of throwingDivisionByZeroErroras PHP 8 does #2666 - Fixed
PHP_INT_MIN % -1crashing the process with SIGFPE #2666 - Fixed a float divisor being silently truncated to an integer by
/and%#2666 - Fixed a
-Wformatwarning inzephir_fclose()by casting the resource handle tozend_longand formatting it with the portableZEND_LONG_FMTmacro instead of%d, preserving compatibility with PHP 8.0'sinthandle. - A variable whose only consumer is a closure's
use (...)clause now counts as used: it is no longer reported asunused-variable, and it is declared in the generated C. A declared-but-unassigned capture was skipped by both, so the generated code referenced an undeclared identifier and the extension failed to build. Capturing a variable that was never declared now fails withCannot capture variable 'x' because it wasn't declaredinstead of a PHP fatal error #2029 - Fixed array defaults on a class (typed
arrayproperty defaults, trait array property defaults and array class constants), which were one shared table that every instance mutated in place instead of being copy-on-write #2651 - Fixed the unchecked length arithmetic in the
zephir_concat_*()helpers, which now throwString size overflowlike PHP instead of writing past the allocation #2657 - Fixed
let s .= nwith an integer operand calling the declared but never definedzephir_concat_self_long(), so the extension built and then died at load withundefined symbol, and made the same append work on avarleft-hand side #2660 - Fixed closure
use (...)captures being shared by every closure created from the same source line, and implementeduse (&x)as a real reference #2652 - Fixed the closure
use (...)clause droppingconst, which is now a read-only capture, and a by-reference capture of an explicitly typed local #2653 - Fixed a closure declared inside another closure never having its source file generated, so the extension failed to link, and
thisinside it resolving against the outer closure instead of the enclosing class #2655 - Fixed every closure invocation leaking one reference of the closure object and of each captured value #2652
- Anonymous functions can now declare a return type:
function (a) -> int { }, including after ause (...)clause (function () use (base) -> string { }), and withvoid, union (int|string) and<Class>types. The type is declared on the closure's__invoke, so Reflection reports it. Requires Zephir Parser 2.6.0 #1841 - Class constant initializers and class/trait property defaults accept a full constant expression instead of a single literal, so
const INT8_MIN = -0x7f - 1;,const MASK = 0xff << 8 | 0x0f;andpublic size = 1024 * 8;now compile. Arithmetic, bitwise, concatenation, comparison, logical and ternary operators are supported, as are parentheses, other constants (self::KB * 2) and expressions inside array constants; the result is folded to a literal at compile time with PHP's own semantics (4 / 2is anint,PHP_INT_MAX + 1a float). An initializer that is not resolvable at compile time is now rejected by name instead of failing as a syntax error. Parameter defaults are unchanged. The new syntax needs Zephir Parser 2.7.0; an older extension is bypassed in favour of the built-in parser (see below) #2061 - Added an optional
--CONFIG--section to the.zeptformat, holding a JSON object merged into the throwaway project'sconfig.json. This makes a case buildable under a non-default compiler configuration (e.g.{"optimizations": {"internal-call-transformation": true}});namespaceandnamestay derived from the sources #2021 - Added destructuring assignment:
let [a, b, c] = expr;assigns consecutive array elements to several variables at once, andlet [a, , c] = expr;skips slots. The right-hand side is evaluated exactly once, a slot past the end of the source array isnull(as in PHP'slist()), and a non-array source is rejected at compile time. Nested (let [[a, b], c] = expr;) and keyed destructuring are not supported #2496
- The minimum
ext-zephir_parseraccepted as the fast parsing path is now 2.7.0 (was 2.1.0). An installed extension older than that cannot parse everything the compiler accepts, so it is ignored and the built-in pure-PHP parser is used instead — compiling still succeeds, just without the C parser's speed. Upgrade the extension to restore it #2061 zephir buildandzephir installnow report where the extension was installed (Extension installed into /usr/local/lib/php/extensions/no-debug-non-zts-20230831), read from theEXTENSION_DIRthe build was configured with, so it names the right directory for a build retargeted with--with-php-config. The plainExtension installed.is kept when the destination cannot be confirmed. TheAdd "extension=…"hint now names the configuredextension-namerather than the namespace #2467
- Fixed a
breakwritten after areturn(orthrow) inside aswitchclause being reported asUnreachable codeand, worse, stopping theswitchfrom satisfying the method's return-type hint, so the snippet in the issue failed withReached end of the method without returning a valid type specified in the return-type hints. A deadbreak/continueis a no-op that PHP accepts without any diagnostic, and the completeness check now stops at the first statement that actually transfers control instead of looking only at the last one. A deadbreaknested in anifarm is still honoured, because that path leaves theswitchwithout returning #1704 - Fixed the check deciding whether a method can reach its end without returning, which had three overlapping implementations and inspected only one statement of each block. It reported
Reached end of the method without returning a valid type specified in the return-type hintsfor dead code written after areturn, and conversely accepted a method that could fall off its end - anif/elseif/elsewhoseelseifarm does not return (theelseifarms were never looked at), atrywhosecatchbody is empty, or afor/whilebody that returns although the loop can run zero times - in which caseZEPHIR_MM_RESTORE()was skipped too. A single check now modelsif/elseif/else,switch,try/catchand loops, treating aloop/while truewithout abreakas unable to fall through #1704 - Fixed
switchclauses not falling through as they do in PHP. A clause that did notbreakran thedefaultbody instead of the next clause's body, because every clause was emitted as an independentifwithdefaultappended unconditionally;switch a { case 1: let r .= "a"; case 2: let r .= "b"; default: let r .= "d"; }gave"ad"for1instead of"abd". Clause bodies are now emitted in source order behind agotodispatch chain, so fall-through, adefaultwritten in the middle, andcontinuebehaving asbreakinside aswitchall match PHP. Acaseexpression after the first match is no longer evaluated either #1704 - Fixed a
usestatement naming a class of an optional extension warning asdoes not exist at compile timewhen that extension is not loaded in the PHP running Zephir. The bundled prototypes declare those classes, but they were required after theusevalidation, so building Phalcon withoutext-redisorext-memcachedreportedRedis,RedisClusterandMemcachedas nonexistent. The prototypes — and anyprototype-dirof the project — are now loaded before the validation.RedisException, which no prototype declared, was added to theredisprototype phalcon/cphalcon#17517 - Fixed a method declared by a parent interface not being resolved, so
abstract class Base implements Outerwithinterface Outer extends Innerrejectedthis->go()withClass 'Base' does not implement method: 'go'unless the class implementedInnerdirectly. An interface now reports the methods of its parent interfaces at any depth, including when it extends several. A concrete class is likewise held to the whole chain at build time instead of failing later as a PHP fatal error #2635 - Casts now accept every source type. The cast operator enumerated sources per target, so more than half of all combinations failed with
Cannot cast: X to Y— among them(string) 5,(string) "abc",(array) 5,(bool) [],(char) 65,(int)of along, and every use of(uint),(ulong),(uchar)and(var). Results match PHP, including(bool) 0.4beingtruewhere a C cast would truncate it tofalse#1841 - Fixed
(array)and(object)casts overwriting the variable being cast: both lower to kernel conversions that run in place, solet b = (array) aturnedaitself into an array #1841 - Fixed an interface
extendsing a bundled interface declared in a PHP extension header (e.g.interface I extends \JsonSerializable, \SeekableIterator) failing to compile with'php_json_serializable_ce' undeclared. The required#includes were collected but then discarded for interface files, so the emittedzend_class_implements()calls referenced undeclared class entries #2427 - Fixed the
internal-call-transformationoptimization breaking method overriding. It replacedthis->method()with a direct call to the callee's C function, which skips PHP's dispatch, so a subclass override was never reached —Vector::multiply()callingthis->multiplyMatrix()always ranVector's version even on aColumnVector. The direct call is now used only where PHP resolves the target statically anyway: afinalmethod, aprivatemethod of the class being compiled, orthisin afinalclass.self::,parent::andClass::method()calls are unaffected, and a userland PHP class extending a Zephir one now overrides correctly too. Accessors generated from{get}/{set}are always public, so they no longer take the direct call #2021 - Fixed
internalmethods with parameters reading the caller's arguments instead of their own, which crashed the process outright whenever the two arities differed. They are called C-to-C with the caller'sexecute_dataand receive their real arguments as trailing pointers, but still ran aZEND_PARSE_PARAMETERSblock against that frame; the block is now skipped and every parameter type is bound from the arguments actually passed. Affects theinternalkeyword as well asinternal-call-transformation#2021 - Fixed a segfault whenever an exception is created inside an
internalmethod — which includes everythrowout of one, since the constructor runs first. Such a method is called C-to-C on a syntheticzend_execute_datawhosefuncwasNULL, and the engine reads afunc-less frame as a generator placeholder frame only, so the backtrace capture that every Exception constructor performs dereferenced it. The frame now carries an anonymous internal function and is skipped in userland backtraces.debug_backtrace()inside aninternalmethod crashed for the same reason. Affects theinternalkeyword andinternal-call-transformationon PHP 8.1 and later #2639 - Fixed a
.zeptcase being written to the wrong.zeppath when a--FILE--comment happens to contain the wordsclass,interfaceortraitfollowed by a name. The path is derived by matching the declaration over the whole section body, and prose such as "a method of the class being compiled" won, so the build failed withUnexpected class name ... in file: 'stub/being.zep'. A declaration now has to begin a statement #1098 - Fixed
internal-call-transformationemitting body-less C functions forabstractmethods and for generators, and droppingstaticfrom the generated twin. It also generated each parameter conversion twice, because the twin shared the original method's parameter list — a leak forstringandarrayparameters, which allocate #2021 - Fixed capturing a
stringin a closure emitting C that does not compile (ZVAL_STRINGapplied to azval). It affected everystringheld as a zval: a local, a parameter reassigned in the method body, and — withinternal-call-transformationenabled — anystringparameter, which was the last file ofstub/failing to build under that option. Such a capture is no longer boxed a second time #2638 - Fixed
__FUNCTION__and__METHOD__reporting a compiler-generated method name. Both are folded at compile time from the method being compiled, and the compiler recompiles a method body under a mangled name in two cases: the twininternal-call-transformationgenerates (<name>_zephir_internal_call) and the step a generator's body is moved into (zephir_gen_step_<name>). They now report the name declared in the.zepsource, as do compile diagnostics that name the method #2643 - Fixed the stale shared object not being removed before a full rebuild in projects that set
extension-name: the cleanup looked forext/modules/<namespace>.so, while the module is built asext/modules/<extension-name>.so#2467 - Fixed
zephir installandzephir buildreporting success when the extension was never installed. The exit status ofsudo make installwas ignored — only the presence ofext/modules/<name>.so, which plainmakeproduces, was checked — and the CLI discarded the result of the install step on top of that. A missing sudo, a declined password or a read-only extension directory now fails with the exit code and a non-zero status instead of printingExtension installed.#2467
- Added the
::classmagic constant:self::class,parent::classandClassName::classresolve to the fully-qualified class name at compile time, andstatic::classresolves to the called class at runtime (late static binding) #2527 - Trait properties can now have array default values (e.g.
trait T { public opts = [1, 2, 3]; }, including empty, keyed and nested arrays). The default is materialized as a persistent immutable array on the trait's class entry, so it is carried into both Zephir classes and PHP userland classes thatusethe trait, matching native PHP trait semantics. Static array defaults on traits remain rejected (Zephir resolvesself::in a trait to the trait itself, so each using class could not get its own copy) #2607 - Class and trait properties can now declare a type, mirroring PHP's typed properties: builtin (
int,bool,double,string,array,object), nullable (?string), and class types (<My\Class>,?<My\Class>). The type is emitted viazend_declare_typed_property, so Reflection reports it and the engine enforces it; a typed property with no default is uninitialized (public <Foo> conn;) rather thannull, matching PHP #2608 - Added union types (
int | float) on method/function parameters and class/trait properties (e.g.public int|float foo;,function f(float|int bar) -> int|float). Reflection reports aReflectionUnionType; union properties are engine-enforced on write (scalar,null/false, and one or more<Class>members), while a union parameter binds as a mixed value carrying its declared arg-info type mask. Union return types were already supported #2613 - Added
readonlyproperties (e.g.public readonly array foo): the property carriesZEND_ACC_READONLY, so Reflection reports it and the engine enforces write-once after initialization. Like PHP, a readonly property must be typed, cannot declare a default value and cannot be static (each rejected at compile time). Enforced on PHP 8.1+; on PHP 8.0 it degrades to a plain typed property #2614 - Added the
+=(add-assign) operator on arrays, performing PHP array union (let a += [1, 2]), for array literals and botharray-typed and untypedvaroperands #1280 - Added an opt-in
missing-optimizerwarning that reports function calls with no applicable optimizer, which are dispatched by name through the Zend function table at runtime instead of being inlined. It also covers calls an existing optimizer declined because it does not handle that call form (e.g.count(a, 0)), which are otherwise invisible. Enable with-wmissing-optimizer; each function is reported once per run, at its first call site #2468 - Added a
--with-php-config=PATHoption to thebuild,compileandfullcleancommands, so an extension can be built against a PHP installation other than the one in thePATH(e.g. a separate ZTS build).phpizeis taken from the same directory as the givenphp-config, and an unusable or mismatched path is rejected before the build starts. Not available on Windows, where the dev-pack (%PHP_DEVPACK%) selects the target PHP #1834
- Fixed
char/ucharvalues in dynamic (zval) contexts. A string offset read (s[i]) now boxes as a 1-character string when its target is avar/stringvariable or an array element, matching PHP's$s[$i]:string ch; let ch = s[i];used to emit C that did not compile, andlet pieces[] = s[i];was rejected withUnknown type: uchar. A declaredchar/ucharvariable still boxes as its integer byte value (aslet a = [ch]andreturn chalready did) — use(string) chfor the character — and a directreturn s[i]is unchanged #1629 char/ucharare now accepted in the remaining scalar positions, each of which previously threw or emitted invalid C:(uchar)casts,(string)/(char)casts of auchar,ucharmethod parameters and globals, keyed array literals ([1: ch]),let a[k] = ch, object and static property array offsets, anddouble/booltargets. Acharliteral reaching a numeric slot no longer emitsZVAL_LONG(&x, ''a''), and assigning anintto astring(string s; let s = i;) no longer emits dead PHP-5 code #1629- Fixed
acos()andasin()never using their optimizers on case-sensitive filesystems: optimizer lookup derivesAcosOptimizer.php/AsinOptimizer.phpfrom the function name, but the files were namedACosOptimizer.php/ASinOptimizer.php, so both calls compiled to a runtime function call on Linux while macOS and Windows inlined them #2468 - Fixed typed-property and array-class-constant string defaults containing escape sequences (e.g.
protected string x = "A\\B\\C") being emitted with the wrong byte length: the length wasstrlen()of the source-escaped PHP value (a\\counted as two bytes) while the C string literal is shorter, so the runtime string was over-long and corrupted with trailing garbage bytes. The length is now measured by the C compiler (SL()/sizeof), correct for every escape sequence #2617 - Fixed the
Zephir version has changedwarning firing on every rebuild: the version-cache directory existence check usedis_file()on a path that is always a directory, so the check never matched and the warning degraded to "warn whenever the project was already built". It now fires only on a genuine version change and names the old and new versions #2621
- Implemented generator (
yield) support: methods containingyield;/yield expr;/yield key, value;now compile to lazy generators returning an extension-scoped<Namespace>\Generatorobject (\Iterator+send()+getReturn()) with PHP-identical laziness, auto-key, rewind and exhaustion semantics. Suspension works acrosswhile/loop/if/switch,for in <array>(snapshot iteration),range()and object iteration;yieldinsidetry/catch,for ... in iterator(...), closures and functions is rejected at compile time. PHP's\Generatoris final, so declare-> <\Iterator>,-> <\Traversable>or omit the return type #1849 - Added trait support:
trait Name { }and import inside classes/traits. Zephir traits compile to realZEND_ACC_TRAITclass entries, so PHP userland canusethem #504
- Multi-dimensional array assignments (
let a[i][j] = v) now skip a redundant final-offset hash lookup inzephir_array_update_multi_ex(three hash operations per write down to two), making tight-loop matrix builds ~15–20% faster (measured viatests/Benchmark/MultiDimArrayBench.php) #1884 - Object property reads and writes on
thiswith a compile-time-known name now reuse a per-method internedzend_stringfor the name and a per-request inline property cache slot (zephir_read_property_cached/zephir_update_property_zval_cached), instead of allocating azend_stringand re-resolving the property offset by hash lookup on every access. This takesthis->propreads from ~0.44× to ~1.35× of native PHP throughput — now faster than interpreted PHP (measured viatests/Benchmark/PropertyAccessBench.php) #1902
- Fixed arithmetic compound-assignment (
+=,-=,*=) on an object property overwriting the property instead of accumulating when the right-hand side is a variable (e.g.let this->total += delta;compiled tolet this->total = delta;, dropping the read). The current property value is now read, the operator applied, then written back — matching the already-correct literal-operand path. Arithmetic sibling of the concat-assign fix #2063; found while adding the property inline-cache #1902 - Pure-PHP parser parity: a closure-arrow (
x => expr) now requires a bare identifier on the left, matching the C parser grammaryield "k" => 2;andlet f = "x" => 2;are syntax errors again instead of being mis-parsed #1849 forloops over the../...range operators (for i in 0..n) now compile to an integer counting loop instead of materializing an intermediate array, matching the existingfor i in range(...)optimization; this also lets a typedintloop variable be used with.., which previously failed to compile #2433- A static property initialized with an array literal no longer breaks single-file (concatenated) builds: the
zephir_init_static_properties_<Class>()initializer is now forward-declared at file scope in the project.cinstead of the per-class header, keeping its declaration and definition in one translation unit so their linkage cannot mismatch (staticvs non-static) #2601
1.0.0 - 2026-07-01
- Implemented
.zept(Zephir Test) format and azephir test <path>command: a single file bundles the Zephir implementation (--FILE--, repeatable), the PHP usage (--USAGE--) and the expected output (--EXPECT--/--EXPECTF--). Each case is compiled into a throwaway extension (pure-PHP parser forced) and its output checked, so a.zeptdoubles as an end-to-end parser test. A dependency-free runner (Zephir\Zept\) backs both the CLI and thetests/Zephir/BlackBox/ZeptSuiteTest.phpbridge #1098 - Built-in pure-PHP Zephir parser, removing the hard dependency on the
ext-zephir_parserPECL C extension. The parser produces the identical intermediate representation (IR) the compiler already consumes — verified byte-for-byte (json_encodeequality) against the C extension over the fullstub/corpus, the extractedphp-zephir-parsertest snippets, and the entire Phalcon framework (930/930.zepfiles). Building the bundled stub extension with the PHP parser generates a byte-identical C tree and passes the Extension test suite identically to the C-extension build #2495
- The
ext-zephir_parserC extension is now optional: it is used as a fast path when loaded, otherwise the built-in PHP parser handles parsing. Set theZEPHIR_FORCE_PHP_PARSERenvironment variable to force the PHP backend even when the extension is present (useful for differential testing and deterministic builds).Zephir\Parser\Manager::isAvailable()is now alwaystrue#2495
- The
!(strict type) modifier on argument types (e.g.int! a) now emits a deprecation notice duringzephir generate. A future parser will no longer recognize it. Suppress with-Wdeprecated-strict-type#2274 RedisClusterprototype (inprototypes/redis.php), so Zephir code can resolve its methods and constants when ext-redis is not installed
0.23.0 - 2026-06-06
- Support for array class constants (e.g.
const BAR = [1, 2, 3];, including nested and keyed arrays). The value is materialized on the class entry as a persistent immutable array (readable from PHP), andself::CONSTresolves to it in Zephir code #2533 - Full union return type support, enforced by the engine just like a hand-written PHP union return type. Any combination of classes and/or scalar types is now emitted into the compiled extension's arginfo (via
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX/ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX), so-> <Model> | <Row> | null,-> int | string,-> <Foo> | int, etc. are reported by Reflection and enforced at runtime. Previously onlyint | false/T | nullcarried a return type and every other union silently emitted none #2428
- Cached method/static calls now reuse the resolved function handler instead of repeating the method-table lookup in
populate_fcic(), shaving ~6–10% off per-call dispatch in hot loops (measured viatests/Benchmark/CallDispatchBench.php) #1510 - BC: methods declared with a multi-type union return now carry an enforced return type in the compiled extension. PHP subclasses that override such a method must declare a compatible (equal or narrower) return type, where previously the missing return type made any override valid #2428
- Fixed
let self::prop = "";(assigning an empty string to a static property) failing to compile. The generatedZVAL_EMPTY_STRINGwas passed the bare variable name instead of its address #2409 - Fixed double-quoted string escapes not matching PHP:
\u{XXXX}Unicode codepoints are now UTF-8 encoded (previously emitted literally), and\xHHno longer absorbs following hex digits (e.g."\x41BC"is now"ABC"). Out-of-range codepoints (> U+10FFFF) and a\xwith no hex digit are emitted safely instead of producing malformed C #2030 - Fixed assigning a non-constant boolean expression to a dynamic property (e.g.
let this->{key} = value > 5;) failing to compile with a cryptic?error; it now branches at runtime like a regular property. The remaining?placeholders inBackend::updateArray()and PHP-constant resolution were replaced with descriptive messages #1790 - Fixed hexadecimal literals (e.g.
0xffffffff << 32,0xff + 1) raising "A non-numeric value encountered" during constant folding. Numeric literals are now decoded to real ints before folding in the bitwise and arithmetical operators #2014 - Fixed array writes to a property holding an
ArrayAccessobject converting it to a plain array.let this->prop[key] = value;now calls the object'soffsetSet(), and a chainedlet this->prop[a][b] = value;now mirrors native PHP exactly (fetchesoffsetGet()once and raises the "Indirect modification of overloaded element" notice) instead of replacing the object #2465 - Fixed integer arithmetic with a dynamic operand losing int64 precision (e.g.
1000000000000000000 + varrounded through adouble). The result ofzephir_get_numberval()is now cast to(zend_long)in integer contexts #2010 - Fixed
[ERROR] Unknown charwhen achar/ucharvariable is used as an array literal item (e.g.return [ch1, ch2];). Such items are now boxed as their byte (integer) value #1988 - Fixed a false
Unreachable codewarning on a guard reading a variable that holds a constant before a loop but is reassigned inside the loop body (e.g.let x = false; for ... { if x { ... } let x = true; }). The constant-folding unreachability check is now skipped inside loops #1170 - Subtraction with a
-glued to a digit (e.g.range(0, len-1),arr[0]-1) no longer raisesSyntax error; the parser now treats-after a value as a binary operator instead of the sign of a negative literal #2011 - Fixed
Undefined array key "variable"when assigning to a nested object property (e.g.let this->bar->data = value;). The inner object is now resolved into a temporary and the assignment is handled as a regular object-property write #2532 - Fixed the static type-inference pass leaking debug output (
StaticTypeInference=.../STI=...) to stdout during compilation when it met a variable type or expression node it did not enumerate (e.g. reassigning a var holding a(object)cast). Such cases now silently degrade the variable to dynamic #1877 - Fixed concat-assign (
let this->prop .= value) on object properties overwriting the property instead of appending to it; the current value is now read and concatenated #2063 - Fixed a false
Reached end of the method without returning a valid typeerror for a method ending in an exhaustiveswitch(one with adefaultclause that returns/throws on every path) #1706 - Fixed
char/ucharreturn values sign-extending when the byte exceeds 127 (e.g.0x8Areturned-118instead of138). Char returns are now cast tounsigned charto preserve byte semantics #1291 - Fixed external dependency classes (
external-dependenciesinconfig.json) not being found on case-sensitive filesystems. The.zeppath was lower-cased wholesale, so a PSR-4 class such asPhalcon\Support\Collectionlooked forsupport/collection.zepinstead ofSupport/Collection.zep. The path is now resolved using the namespace casing as written, falling back to the lower-cased path for backward compatibility #2499 - Fixed
[ERROR] Unknown type: ...when declaring a local with an expression default value (e.g.var x = i + 1;, concat, ternary, method calls). Declaration defaults now infer their type through the same path asletassignments #2394 - Fixed generated PHP stubs dropping all but the first class in a union return type (e.g.
-> <Model> | <Row> | nullproducedModel|nullinstead ofModel|Row|null) #2428 - Fixed capturing a scalar
string-typed variable in a closure viause()emittingZVAL_STRINGon azend_string *and failing to compile; it now boxes withZVAL_STRand the captured value is treated as a zval inside the closure body #2562 - Fixed default values not being readable through Reflection for parameters that have a class type, such as
<Foo> bar = null. Before thisgetDefaultValue()threw an error andisDefaultValueAvailable()returnedfalse. These parameters now useZEND_ARG_OBJ_TYPE_MASK, which keeps the default value, instead ofZEND_ARG_OBJ_INFO#2564 - Fixed class-constant parameter defaults (e.g.
string cipher = self::DEFAULT_CIPHER) not being readable through Reflection. Thestatic-constant-accessdefault was not folded, so the arg_info stored"null"andgetDefaultValue()returnednullinstead of the constant's value. The constant is now folded to its scalar literal for the arg_info, mirroring how the property declaration and method body already resolve it. Follow-up to #2566 #2564 - Fixed
instanceofnot narrowing the type inside the guarded block. Calling a method that exists only on the subtype, as inif (x instanceof Sub) { x->subMethod(); }, no longer fails generation with a "does not implement method" error. The narrowed type applies only inside theifblock #2565 zephir generatenow fails with a clear error when a concrete class does not implement an abstract method inherited from an abstract parent, instead of letting the engine raise "Cannot instantiate abstract class" only at runtime #1628- Fixed
Unknown type ...error when a property combines a{get}/{set}shortcut with a@vardocblock that includes the variable name (e.g.@var int $foo). The generated accessor now uses only the type, dropping the variable name and any description #2543 - Fixed a fatal error when a class constant is initialized from a predefined PHP constant (e.g.
const BAR = PHP_VERSION_ID;). Such constants are now folded to their literal value at compile time instead of crashing on the unavailable runtime resolution path #2542
0.22.0 - 2026-05-29
- Added support for variadic functions/methods using the
...operator (e.g.function f(int first, ...rest)) #2025 - Compiler now recognizes the parser-emitted
yieldAST node (bareyield;,yield expr;,yield key, value;) #1849 - Added PHPBench-based runtime benchmarks suites under
tests/Benchmark/#2541
for k, v in exprnow skips the unreachable branch when the iterand's dynamic type is known #1878
- Fixed dynamic init
new {className}()ignoring constructor visibility, allowing classes with aprotected/privateconstructor to be instantiated from any scope #882 - Fixed
unset(obj->{variable})(dynamic property name) andunset(obj->{"literal"})(string-literal brace syntax) throwingCompilerException: Cannot use expression type: property-dynamic-access in "unset".UnsetStatementnow handlesproperty-dynamic-accessandproperty-string-accessnodes, emitting the newzephir_unset_property_zval()kernel helper for variable keys #808 - Fixed
continueinsidefor ... inloops over PHPIterator/Traversableobjects producing an infinite loop #2546 - Fixed
elseifconditions that contain sub-expressions with side effects (such as array element accessmyvar[0]) being evaluated unconditionally before the outerif, causing spurious "Cannot use a scalar value as an array" notices when a preceding branch had already returned #1097 - Fixed cross-class chained
<static>(and<self>/<parent>) return-type resolution. The same-class case landed in #2537 by substituting the lexical class for the reserved keyword. The cross-class case —other->returnsStatic()->method()whereotheris a local variable typed as a different class — was still resolved against the call site's lexical class, so the chained method lookup ran on the wrong definition and the build aborted withClass '<EnclosingClass>' does not implement method: '<method>'.MethodCall.phpalready resolves the receiver's$classDefinitionearlier in the function (from$variableVariable->getClassTypes()); the substitution now uses that definition, which is identical to$compilationContext->classDefinitionfor thethisbranch and preserves existing behavior there. #2505
- Documented the workaround for
[ClassName, "protectedOrPrivateMethod"]arrays passed as callbacks to PHP higher-order functions (array_reduce,usort,preg_replace_callback, etc.) #2167
0.21.0 - 2026-05-20
- Add two templates to structure bug reports and feature requests. #2525
- Added
<self>method return-type annotation being emitted as a namespaced literal class name in arginfo #2505
- Fixed PHP-stub generator emitting implicit-nullable parameters (
Foo $x = null) that PHP 8.4 deprecates #2426 - Fixed false-positive
possible-wrong-parameterwarning when astring,bool,array, orcallableargument was passed to a method parameter typedmixed#2512 - Fixed
usestatements registering aliases for non-existent classes silently #2435 - Fixed
Unknown type: closure(and other AST-type-name) errors when avardeclaration was given #2522 - Fixed segfault when
for k, v in iterator(x)was given a non-Iterator operand (e.g.stdClass, plain array, scalar). #820 - Fixed
--vernumCLI option silently falling through to the help screen instead of printing the numeric version. #2454 - Fixed silent generation of uncompilable C when a local
varwas re-declared with the same name as a method parameter. #2009 - Fixed
stringlocals that were initialized to the empty string (string s = "";orlet s = "";) ending up asnullat runtime when subsequent code paths did not reassign them. #2393 - Fixed
new static()falling back to early binding. #2324 - Fixed
ParseException::__construct()triggering a fatal PHP 8.4 deprecation (Implicitly marking parameter $previous as nullable) when a.zepfile had a syntax error — the deprecation suppressed the actual parse-error message. Parameter is now declared asException | Throwable | null. - Fixed
isset()returningtruefor object properties and array offsets whose value isnull. Previously theisset()operator emittedzephir_isset_property*/zephir_array_isset*kernel helpers that only performed key/property existence checks — equivalent toproperty_exists()/array_key_exists()— soisset(obj->p)whereobj->p === null,isset(arr["k"])wherearr["k"] === null, andisset(obj->declaredButNeverAssigned)all returnedtrueinstead of PHP'sfalse. The codegen now emits newzephir_isset_property_value*/zephir_array_isset_value*helpers that also rejectIS_NULL; for objects this delegates to thehas_propertyhandler withZEND_PROPERTY_ISSET(same path the engine uses for theZEND_ISSET_ISEMPTY_PROP_OBJopcode), so__issetmagic and inaccessible/private property scoping behave correctly. The existing key-only helpers stay available for internal callers that genuinely want existence semantics (e.g.array_key_exists). #2385 - Forcing Exception on Failure of Compile Step
0.20.1 - 2026-05-15
- Migrated Black-box Testing from Sharness to PHPUnit. #2492
- Fixed method return-type enforcement at runtime for
return this->property: methods declared with a strict scalar return type (-> string,-> int,-> double,-> array) now throwTypeErrorwhen the property holds a mismatching value instead of silently returning it. PHP only verifies internal-function return types inZEND_DEBUG=1builds, so the generated C code now emits a runtime check via newRETURN_MEMBER_TYPED/RETURN_MM_MEMBER_TYPEDkernel macros. The error message matches PHP's userland format:Class::method(): Return value must be of type X, Y returned. Nullable return types (string | null) and union/mixedreturns are left unchecked, as before. #1991, #2196 - Fixed built-in array methods called on a
var-typed variable (e.g.let b = b->join("");wherebis declaredvar). Previously these were emitted asZEPHIR_CALL_METHOD(b, "join", …)and surfaced as aRuntimeException: Trying to call method join on a non-object(originally a segfault, reduced to an exception over time). When the method name is one of the array-specific built-in names that can't meaningfully be a real object method (join,reversed,rev,tojson,haskey,mergerecursive,replacerecursive,sortbykey,reversesort,reversesortbykey), the compiler now dispatches viaArrayType— lowering to the matching PHP function call (e.g.join(glue, array)), just like statically-typed array variables already did. Common Iterator/Countable-style method names (count,push,pop,shift,sort,next,current,end,key,reset,each) are deliberately excluded so object dispatch on those is preserved. #733, #2228 - Fixed
let this->prop = valueinside closures: the closure-binding detector from #2497 caught property reads but missed let-statement writes (different AST shape), so writes were rejected as "Property not defined on stub\NN__closure". #1873, #2203 - Reorganised
populate_fcic()to pin calling/called scope earlier for direct call paths (zephir_fcall_ceand closures). #2321 is NOT fixed by this change. The original symptom —preg_replace_callback(..., [this, 'privateMethod'], ...)failing with "cannot access private method" — remains; PHP's callable-argument validation walksprev_execute_datafor the nearestZEND_USER_CODEframe and Zephir methods areZEND_INTERNAL_FUNCTIONso they're skipped. Workaround: wrap the callback in a Zephir closure that capturesthis—function (m) { return this->privateMethod(m); }— closures aren't re-validated by PHP. #2321, #2325
0.20.0 - 2026-05-12
- Added support of PHP
8.5#2459, #2461 - Added closure
thisandusesupport: closures can now referencethisto call methods and access properties of the enclosing class #2497, #2503 - Added support for
charanducharliteral/variable values as method arguments to parameters typedchar/uchar#2469, #2507 - Added support for typed constants (PHP 8.3+) in generated stubs #2498
- Added PhpStan/Psalm tag pass-through whitelist for class-level docblocks in generated stubs #2501
- Added validation of
@phpstan-return,@phpstan-var,@phpstan-type,@phpstan-param,@phpstan-import-typeand Psalm equivalents (delegates parsing tophpstan/phpdoc-parser) #2502 - Added
ConstructorsCodeGenTestto verify generated C/H files against reference fixtures #2482
- Refactored string parameter handling to use native
zend_string *(with companionzval) where the parameter isn't mutated, reducing engine round-trips for string params #2462, #2484 - Refactored type optimizers and added more tests #2470
- Refactored header compilation logic and updated compatibility checks for PHP 8.5 #2489
- Bumped
phpstan/phpdoc-parserfrom1.33.0to2.3.2#2504 - Bumped
squizlabs/php_codesnifferfrom3.13.5to4.0.1#2473 - Bumped
phpunit/phpunitfrom9.6.32to9.6.33#2471 - Bumped
codecov/codecov-actionfrom3to6#2472, #2488 - Bumped
actions/checkoutto6,actions/cacheto5,actions/upload-artifactto7,actions/download-artifactto8#2474, #2475, #2476, #2477, #2480, #2481, #2464
- Fixed
-Wincompatible-pointer-typeswarnings on PHP 8.5+ forzend_parse_arg_array(Z_PARAM_ARRAY/Z_PARAM_ARRAY_OR_NULL) — promoted to error by GCC 14+ #2462, #2463, #2483, #2508 - Fixed
-Wdiscarded-qualifierswarnings introduced on PHP 8.5 whereEG(fake_scope)becameconst zend_class_entry *(kernel/object.c, kernel/require.c,ZEPHIR_BACKUP_SCOPE/ZEPHIR_RESTORE_SCOPEmacros) #2462 - Fixed memory leak in generated code where native
zend_string *parameters incremented refcount viaZVAL_STR_COPYwithout a matching decrement on the return path (~3.4 KB per call) #2500, #2506 - Fixed crash when passing a
char/ucharliteral or variable to a method parameter declared aschar/uchar(TypeError ingetResolvedParams) #2469, #2507 - Fixed stale
.depdependency files causing compilation failures when switching between PHP 8.x versions (now removed duringfullclean; build order corrected somake cleanruns beforephpize --clean) #2490, #2491 - Fixed missing default values in reflection metadata for method parameters with scalar types #2457
- Fixed various compiler warnings surfaced by recent GCC/Clang #2445
- Fixed
backtrace.csoPHP_VERSION_IDis visible (added missing PHP header include)
0.19.0 - 2025-05-13
- Refactor CUFA implementation #2444
0.18.0 - 2024-09-29
- Added support of PHP
8.3#2407 - Added support of multiple return types in stubs
- Changed
PHP_DEBUGconst usage toZEND_DEBUG_BUILD
- Changed minimal PHP version to
8.0#2407
0.17.0 - 2023-02-11
- Added support of PHP
8.2#2255
- Fixed backtrace on alpine #2397
0.16.3 - 2022-09-17
- Fixed segmentation fault on
mixedreturn type and PHP 7.4 #2387
0.16.2 - 2022-08-22
- Added support for
objectreturn type #2374
0.16.1 - 2022-08-21
- Changed usage of
utf8_decode()function in favour ofmb_convert_encoding()#2376
- Fixed generation of
ARG_INFOfor nullable object (?object) #2374
0.16.0 - 2022-03-20
- Added custom list of arg info definition (Phalcon only) #2341
- Added support for
int|falsereturn type (PHP >= 8.0 only) #2338 - Added support of PHP
8.1#2255
- Fixed left
nullwithstringcondition #2299 - Improved support of
mixedtype #2330 - Fixed Interfaces Breaking Child Projects Of Same Root Level Namespace #2334
0.15.2 - 2021-10-24
- Fixed output of
stringtype INI in globals #2312
0.15.1 - 2021-10-08
- Fixed support of
stringtype in struct globals #2308
0.15.0 - 2021-10-05
- Removed
.zepfrom stubs filenames #2273
0.14.0 - 2021-09-18
- Added support for
require_once#2253
- Bumped minimal version of Zephir Parser to
1.4.1. #2284
0.14.0-beta.3 - 2021-08-06
- Fixed class entry generation of external class #2261
0.14.0-beta.2 - 2021-08-06
- Fixed missing
config/directory inzephir.phar#2259
0.14.0-beta.1 - 2021-08-06
- Fixed nullable dynamic argument definition #2245
- Changed detection of external class entries #2213
0.13.5 - 2021-05-09
- Fixed
zephir buildcommand #2240 - Fixed
zephir generatewhen processing Closure #2241 - Fixed stubs generation with variable-length argument #2239
0.13.4 - 2021-04-26
0.13.3 - 2021-04-25
- Fixed nullable array #1094
- Fixed default value detection with Reflection (only PHP 8.0) #1134
- Updated supported list of class entries for PHP date extension #2226
- Fixed unset from class property #1259
- Added support syntax assign-bitwise operators #1103
0.13.2 - 2021-04-10
- Fixed default value of nullable string parameter #2180
- Fixed cast of
stringtointandfloat#828 - Fix
uintcast tounsigned intin function params #812 - Fixed
nullstrict check when variable isstringtype #2186
0.13.1 - 2021-03-31
- Added jobs
-j, --jobsoption forzephir compile#2174
- Fixed not used arginfo for interface static method without parameters (PHP
>= 8.0only) #2178 - Fixed
zephir installcommand #2175
0.13.0 - 2021-03-25
- Dropped support of PHP
< 7.4versions #2111 - Removed call of
generatecommand insidecompilecall #2150 - Removed call of
compilecommand insideinstallcall #2150
- Fixed parameters type detection in methods/functions (PHP
>= 8.0only) - Fixed not adding all build directories #2144
0.12.21 - 2021-03-05
- Fixed path separators in generated
config.m4file on Windows #2153
0.12.20 - 2020-12-16
- Added supports void type return value for stubs phalcon/ide-stubs#50 #1977
- Fixed missing kernel directory at build time ice/framework#271
- Fixed stubs generation for case with array declaration with square brackets in params
- Fixed parameters positioning for
implode()php function #2120
0.12.19 - 2020-05-13
- Fixed duplicate definition with GCC 10 ice/framework#266
- Fixed initialization of object properties with default values when the object is an instance of a child class #2089
- Improved stubs generation for methods which may return object or null #2092
0.12.18 - 2020-04-25
- In some cases for C "control characters" aren't properly escaped #2065
- Zephir ignored property visibility and has not thrown error when setting private/protected properties in scope that shouldn't intend for it #2078, phalcon/cphalcon#14810, phalcon/cphalcon#14766
0.12.17 - 2020-02-14
- On some platforms special alpha characters aren't correctly escaped. #2058
- Changed the internal DI environment mode when compile PHAR #2049
0.12.16 - 2020-01-16
- Do not dump config file if config was changed.
Usually we need dump configuration exactly once - at project initialization.
There are no needs to dump it for every config change. Also, this patch
removes
Config::$changedvariable that is no longer needed #2035 - Use a different path for the Kernel cache if possible. This patch fixes a cache collision issue. The issue is after creating the cache and filling it with a project-specific configuration, there is no way to invalidate it. Any next project will use the same Kernel cache and the same Kernel configuration (if any). #2036
- Fixed
-VCLI flag purpose. Initially it was designed to disable verbose mode on the fly, e.g. to override project configuration for a single Zephir pass. This behavior was returned back. - Fix increment array elements operation #2020
- Fixed compound addition and subtraction assignment operators for static properties #2038
- Improved type hint for arrays when generating stubs #2026
0.12.15 - 2019-12-12
- Removed
uinttypedef usage
0.12.14 - 2019-12-11
- Removed
zend_uinttypedef usage
0.12.13 - 2019-12-08
- Fixed PHP 7.4 support for macOS phalcon/cphalcon#14577
- Removed
uintandulongtypedefs usage
0.12.12 - 2019-11-25
- Option to set banner for stubs generator #1987
- Calling object methods from static context yields segmentation fault when
internal-call-transformationis set toTRUE#2000 - Certain method calls fail when called from static context when
internal-call-transformationis set toTRUE#2005 - Method context loses track of
thisafter calling static method wheninternal-call-transformationis set toTRUE#2007 - Fixed incorrect stubs generation for return type hint #1990
- Fixed incorrect stubs generation for classes in the same namespace #2016
0.12.11 - 2019-11-02
- Fixed arithmetical operations with
zvalswhich storesdoublenumbers - Fixed updating static variables in the loop which represents
doubleandintegerdata types #1494 - Fixed casting char into another of a different type #1988
- Fixed
internalmethods definition wheninternal-call-transformationis enabled #1956 - Fixed aliases using in the
usestatement when generating stubs #1986 - Fixed incorrect namespace on type hinted return when generating API docs #1229
0.12.10 - 2019-10-19
- Fixed incorrect behavior in
zephir_get_globalifzvalreference count <= 1 #1961
- Removed
--vernumoption from the help for regular commands - Removed
voidfrom the return type hint in the generated stubs #1977 - Remove no longer supported
TSRMLS_CCusage #1865
- Disabled PHP warnings for PHP >= 7.3.0 to be able correct work with lowest versions of dependencies zendframework/zend-code#160
- Introduced support of multi line
@parambody for generated stubs #1968
0.12.9 - 2019-10-14
- Added a single hyphen version of
dumpversionoption (just-dumpversion) - Added
--vernumoption to print compiler version as integer
- Create local
.zephironly when necessary - Fixed IDE stubs generation #1778
- Fixed segfault on cast
IS_UNDEFto array #1941 - Disables some regression changes introduced in the version
0.12.5#1941 (comment) - Fixed memory leak on update array #1937
- Fixed IDE stubs generation for classes that extends base classes #1907
- Proper escape slashes in strings #1495
- Print warning during the code generation if the
timecopextension was detected #1950 - Improved error handling to not print PHP stack traces if
ZEPHIR_DEBUGis not set
- Removed no longer used
zephir_dtormacro
0.12.8 - 2019-10-03
- Fixed
zephir_preg_matchto useZVAL_NULLinstead ofZEPHIR_NULL#1946 - Fixed
Extension\InternalClassesTesttest to be able run full test suite without Phalcon #1949
0.12.7 - 2019-10-03
- Fixed regression introduced in
0.12.5for those users who doesn't use bundledext/pcre/php_pcre.h#1944 #1940 - Fixed sitemap API generator #1940
0.12.6 - 2019-10-03
- Fixed regression introduced in
0.12.5for those users who doesn't use bundledext/json/php_json.h#1940
0.12.5 - 2019-10-02
- Update
zend_update_static_propertyto be compatible with PHP >= 7.3 #1904 - Improved error handling
- Fixed IDE stubs generation to properly generate return type hint for
var | null#1922 - Fixed updating Super Globals #1917
- Fixed casting variables to array #1923
- Fixed work with constant which are not present #1928
- Fixed access to Super Globals #1934, phalcon/cphalcon#14426
0.12.4 - 2019-09-22
- Fixed install template
0.12.3 - 2019-09-22
- Fixed concatenation support of strings with
doublenumbers #1893 - Fixed 'void' return type hint being ignored #1908
- Fixed updating array properties #1915
0.12.2 - 2019-08-05
- Introduced initial ability to generate
zend_module_deps#1900, phalcon/cphalcon#13702, phalcon/cphalcon#13794
- Write errors compiler to stderr if available
0.12.1 - 2019-07-30
- Added initial bash completion support (see
zephir-autocompletefile)
- Remove HAVE_SPL usage phalcon/cphalcon#14215
- Remove not used redundant command line options
- Cleaning up redundant CLI options
- Fixed segfault when auto-loading class with syntax error #1885
- Optimize memory usage #1882
- Fixed modifying array values in loops #1879
0.12.0 - 2019-06-20
- PHP 5.x is no longer supported
- The minimal Zephir Parser version is 1.3.0
- Fixed CLI runner for Windows #1857
- Fixed segfault with fetching and opcache #1855
- Extended classes can't access their private variables #1851
- Incorrect usage of
zend_declare_class_constant_exphalcon/cphalcon#14160, https://bugs.php.net/bug.php?id=78121 - Incorrect implementation of ArrayAccess methods #1871
- Fixed exception on call undefined method #1863
0.11.12 - 2019-03-24
- Compilation error for instanceof #1828
- Fixed
array_shiftbehavior to mimicry PHP's "change by reference" #1831 - Fixed reference counting while changing object's properties that are arrays #1833
0.11.11 - 2019-02-26
- Objects are not traversable with
foreach#1818 #1595 - Recursion for array_push on PHP 7 #1140
- Invalid array initialization #1159
0.11.10 - 2019-02-23
- Moved internal cache and logs to the user's home directory.
- On macOS Zephir will use
XDGif it is possible, otherwise$HOME/Library - On Windows Zephir will use
LOCALAPPDATAif it is possible, otherwise home dir as a base path - In any other cases, e.g. Linux, BSD and so on, Zephir will use
XDGif it is possible, otherwise$HOME/.localand$HOME/.cache
- On macOS Zephir will use
- Per project cache used for temporary operations was moved to
%CWD%/.zephir/%VERSION%where%CWD%is the current working directory and%VERSION%is the current Zephir version e.g.0.11.10-4a825b8
- Array of object as return type is reported to PHP as type, not array #1779
- Use namespace as a prefix for ini name #1604
- Fixed calling anonymous functions by resolving context #1751
- Fixed a bug when accessing super-global variables that do not exist (only for PHP >= 7.0 ) #1775
- Fixed incorrect behavior during work with ArrayAccess #1061, #1400
0.11.9 - 2019-01-15
- Fixed
zend_closuredeclaration to reflect PHP 7.3 changes
0.11.8 - 2018-12-01
- Fixed compilation error with inheritance of prototype interfaces #1758
- Fixed compilation error when a new file is added or removed to the project #1776
0.11.7 - 2018-11-27
- The cache directory, formerly known as
.temp, used for temporary operations was moved to the new.zephirdirectory. The algorithm for calculating cache path is as follows:%CWD%/.zephir/%HASH%/cache/IRwhere%CWD%is the current working directory and%HASH%means a hash calculated from the current Zephir version, environment and configuration - The compiler's messages was divided into streams. Thus, now it is possible to redirect compiler's
output as follows:
zephir generate 2> errors.log 1> /dev/null - Fixed type hints for scalar arguments for PHP < 7.2 #1658
- Coloring the compiler messages in the terminal is temporarily disabled
- Fixed incorrect behavior of
func_get_argandfunc_get_argsfunctions for PHP 7.3
0.11.6 - 2018-11-19
0.11.4 - 2018-11-18
- Introduced a brand new CLI interface
- The preferred method of installation is to use the Zephir PHAR which can be downloaded from the most recent Github Release
- Added
--no-devoption to force building the extension in production mode #1520 - Zephir development mode will be enabled silently if your PHP binary was compiled in a debug configuration #1520
- Added missed CLI option
--export-classesto flag whether classes must be exported. If export-classes is enabled all headers are copied toinclude/php/ext.
- Fixed regression introduced in the 0.10.12 related to
requirefile using protocols #1713
0.11.3 - 2018-11-13
- Remove legacy installers and provide a common way to install Zephir
#1714. Supported installation strategies are:
- Install as a global application (using
composer global require) - Install as a PHAR file. (this feature currently in the testing phase and not released officially)
- Install as a Git clone (using
git cloneandcomposer installinside cloned project) - Install as a project's dependency (using
composer require)
- Install as a global application (using
0.11.2 - 2018-11-11
- Introduced an ability to pack project into one
zephir.pharfile (for PHP 7.1 and later)
- Composer now is a mandatory dependency
- Improved Zephir's Compiler error reporting
- PHP 5.5 no longer supported
- Correct return types hint check
0.11.1 - 2018-10-19
- Initial support of PHP 7.3 (ported from the 0.10.x branch)
0.11.0 - 2018-08-05
- Add type hints for scalar arguments and return values in ZendEngine 3 1656
0.10.14 - 2018-11-20
- Fixed incorrect behavior of
func_get_argandfunc_get_argsfunctions for PHP 7.3 (backported from the upstream)
0.10.13 - 2018-11-18
- Fixed regression introduced in the 0.10.12 related to
requirefile using protocols #1713 (backported from the upstream) - Fixed incorrect behavior of
requirestatement for ZendEngine3 #1621 #1403 #1428 (backported from the upstream)
0.10.12 - 2018-10-19
- Initial support of PHP 7.3
0.10.11 - 2018-08-05
- Allow extension to be loaded prior to the tests
- Fixed Copy-On-Write violation for arrays zvals
- Fixed some testing settings 5deb64a
- Fixed casting resource to int (only ZendEngine 3) #1524