Releases: Ocramius/ProxyManager
2.0.4
2.0.3
2.0.3
Fixed
- Various test suite cleanups, mostly because of
new PHPUnit 5.4.0 deprecations being introduced
#318 - Removed
zendframework/zend-code:3.0.3
from installable dependencies, since
a critical bug was introduced in it #321
#323
#324. Please upgrade to
zendframework/zend-code:3.0.4
or newer.
Total issues resolved: 4
- 318: Cleanup: remove unused imports, deprecated method usage, static/non-static assertion mixup
- 321: Syntax error, unexpected '' (T_NS_SEPARATOR) when using Zend-Code 3.0.3
- 323: Excluding
zendframework/zend-code
3.0.3
from compatible dependencies - 324: Excluding
zendframework/zend-code
3.0.3
from compatible dependencies (2.0.x backport)
2.0.2
2.0.2
Fixed
- Various optimizations were performed in the
ocramius/package-versions
integration in order to prevent "class not found" fatals. #294 - Null objects produced via a given class name were not extending from the given class name, causing obvious LSP
compliance and type-compatibility issues. #300
#301 - Specific installation versions were removed from the README.md install instructions, since composer
is installing the latest available version by default. #305 - PHP 7.0.6 support was dropped. PHP 7.0.6 includes some nasty reflection bugs that caused
__isset
to be called when
ReflectionProperty#getValue()
is used (https://bugs.php.net/72174).
#306
#308 - PHP 7.0.7 contains additional limitations as to when
$this
can be used. Specifically,$this
cannot be used as a
parameter name for closures that have an already assigned$this
. Due to$this
being incorrectly used as parameter
name within this library, running ProxyManager on PHP 7.0.7 would have caused a fatal error.
#306
#308
#316 - PHP 7.1.0-DEV includes type-checks for incompatible arithmetic operations: some of those operations were erroneously
performed in the library internals. #308
Total issues resolved: 12
- 294: Fatal error: Class 'ProxyManager\Versions' not found
- 296: Forward port the changelog for 2.0.1 to master as well
- 300: Null objects do not extend their original class
- 301: Correcting null object inheritance - null objects were not extending from their original class
- 305: Update version on README installation example
- 306: PHP 7.0.6 is incompatible with ProxyManager 2.x
- 308: PHP 7.0.7 compatibility
- 310: Port 2.0.1 changelogs to master branch
- 313: Documentation fixlets
- 315: Update lazy-loading-value-holder.md
- 316: Symfony Lazy Services don't work with PHP 7.0.7
- 317: Hotfix: PHP 7.0.7 compatibility (backport for 2.0.2)
2.0.1
2.0.0
New features
PHP 7 support
ProxyManager will now correctly operate in PHP 7 environments.
PHP 7 Return type hints
ProxyManager will now correctly mimic signatures of methods with return type hints:
class SayHello
{
public function hello() : string
{
return 'hello!';
}
}
PHP 7 Scalar type hints
ProxyManager will now correctly mimic signatures of methods with scalar type hints
class SayHello
{
public function hello(string $name) : string
{
return 'hello, ' . $name;
}
}
PHP 5.6 Variadics support
ProxyManager will now correctly mimic behavior of methods with variadic parameters:
class SayHello
{
public function hello(string ...$names) : string
{
return 'hello, ' . implode(', ', $names);
}
}
By-ref variadic arguments are also supported:
class SayHello
{
public function hello(string ... & $names)
{
foreach ($names as & $name) {
$name = 'hello, ' . $name;
}
}
}
Constructors in proxies are not replaced anymore
In ProxyManager v1.x, the constructor of a proxy was completely replaced with a method
accepting proxy-specific parameters.
This is no longer true, and you will be able to use the constructor of your objects as
if the class wasn't proxied at all:
class SayHello
{
public function __construct()
{
echo 'Hello!';
}
}
/* @var $proxyGenerator \ProxyManager\ProxyGenerator\ProxyGeneratorInterface */
$proxyClass = $proxyGenerator->generateProxy(
new ReflectionClass(SayHello::class),
new ClassGenerator('ProxyClassName')
);
eval('<?php ' . $proxyClass->generate());
$proxyName = $proxyClass->getName();
$object = new ProxyClassName(); // echoes "Hello!"
var_dump($object); // a proxy object
If you still want to manually build a proxy (without factories), a
public static staticProxyConstructor
method is added to the generated proxy classes.
Friend classes support
You can now access state of "friend objects" at any time.
class EmailAddress
{
private $address;
public function __construct(string $address)
{
assertEmail($address);
$this->address = $address;
}
public function equalsTo(EmailAddress $other)
{
return $this->address === $other->address;
}
}
When using lazy-loading or access-interceptors, the equalsTo
method will
properly work, as even protected
and private
access are now correctly proxied.
Ghost objects now only lazy-load on state-access
Lazy loading ghost objects now trigger lazy-loading only when their state is accessed.
This also implies that lazy loading ghost objects cannot be used with interfaces anymore.
class AccessPolicy
{
private $policyName;
/**
* Calling this method WILL cause lazy-loading, when using a ghost object,
* as the method is accessing the object's state
*/
public function getPolicyName() : string
{
return $this->policyName;
}
/**
* Calling this method WILL NOT cause lazy-loading, when using a ghost object,
* as the method is not reading any from the object.
*/
public function allowAccess() : bool
{
return false;
}
}
Faster ghost object state initialization
Lazy loading ghost objects can now be initialized in a more efficient way, by avoiding
reflection or setters:
class Foo
{
private $a;
protected $b;
public $c;
}
$factory = new \ProxyManager\Factory\LazyLoadingGhostFactory();
$proxy = $factory-createProxy(
Foo::class,
function (
GhostObjectInterface $proxy,
string $method,
array $parameters,
& $initializer,
array $properties
) {
$initializer = null;
$properties["\0Foo\0a"] = 'abc';
$properties["\0*\0b"] = 'def';
$properties['c'] = 'ghi';
return true;
}
);
$reflectionA = new ReflectionProperty(Foo::class, 'a');
$reflectionA->setAccessible(true);
var_dump($reflectionA->getValue($proxy)); // dumps "abc"
$reflectionB = new ReflectionProperty(Foo::class, 'b');
$reflectionB->setAccessible(true);
var_dump($reflectionB->getValue($proxy)); // dumps "def"
var_dump($proxy->c); // dumps "ghi"
Skipping lazy-loaded properties in generated proxies
Lazy loading ghost objects can now skip lazy-loading for certain properties.
This is especially useful when you have properties that are always available,
such as identifiers of entities:
class User
{
private $id;
private $username;
public function getId() : int
{
return $this->id;
}
public function getUsername() : string
{
return $this->username;
}
}
/* @var $proxy User */
$proxy = (new \ProxyManager\Factory\LazyLoadingGhostFactory())->createProxy(
User::class,
function (
GhostObjectInterface $proxy,
string $method,
array $parameters,
& $initializer,
array $properties
) {
$initializer = null;
var_dump('Triggered lazy-loading!');
$properties["\0User\0username"] = 'Ocramius';
return true;
},
[
'skippedProperties' => [
"\0User\0id",
],
]
);
$idReflection = new \ReflectionProperty(User::class, 'id');
$idReflection->setAccessible(true);
$idReflection->setValue($proxy, 123);
var_dump($proxy->getId()); // 123
var_dump($proxy->getUsername()); // "Triggered lazy-loading!", then "Ocramius"
Proxies are now always generated on-the-fly by default
Proxies are now automatically generated any time you require them: no configuration
needed. If you want to gain better performance, you may still want to read
the tuning for production docs.
Proxy names are now hashed, simplified signature is attached to them
Proxy classes now have shorter names, as the parameters used to generate them are
hashed into their name. A signature is attached to proxy classes (as a private static
property) so that proxy classes aren't re-used across library updates.
Upgrading ProxyManager will now cause all proxies to be re-generated automatically,
while the old proxy files are going to be ignored.
BC Breaks - backwards-incompatible changes
- PHP
~7.0
is now required to use ProxyManager - HHVM compatibility is not guaranteed, as HHVM is not yet PHP 7 compliant
- All classes and interfaces now use strict scalar type hints.
If you extended or implemented anything from theProxyManager\
namespace, you probably need to change
that code to adapt it to the new signature. - All classes and interfaces now use return type declarations.
If you extended or implemented anything from theProxyManager\
namespace, you probably need to change
that code to adapt it to the new signature. - ProxyManager will no longer write proxies to disk by default:
theEvaluatingGeneratorStrategy
is used instead.
If you still want ProxyManager to write files to disk, please refer to the tuning for production docs - Ghost objects were entirely rewritten, for better support and improved performance. Lazy-loading is not
triggered by public API access, but by property access (private and public). While this is not really a BC
break, you are encouraged to check your applications if you rely on ghost objects. - If ProxyManager can't find a proxy, it will now automatically attempt to auto-generate it, regardless of
the settings passed to it. ProxyManager\Configuration#setAutoGenerateProxies()
was removed. Please look for calls to this method and
remove them.- Private properties are now also correctly handled by ProxyManager: accessing proxy state via friend classes
(protected or private scope) does not require any particular workarounds anymore. ProxyManager\Version::VERSION
was removed. Please useProxyManager\Version::getVersion()
instead.- PHP 4 style constructors are no longer supported
Changes (raw log)
Total issues resolved: 66
- 97: Private properties of superclasses are not considered when generating proxies
- 105: Make the evaluating generator strategy a default
- 115: RFC: Recited: Give me my constructor back
- 128: Removal of PHP 5.3 support
- 130: [WIP\ Master branch dev version / 2.0.x dependencies
- 152: Rewrite Ghost Objects to only rely on property lazy loading
- 159: Ideas/considerations for GhostObject Proxies lazy loading
- 167: Drop PHP 5.4 support
- 175: Avoid constructor override
- 177: Add variadics support
- 184: Split documentation homepage into a "features" page, remove duplicate content
- 186: Remove deprecated
ProxyManager\Configuration#setAutoGenerateProxies()
- [192: Lazy-loading of ghost objects only via properties access (no method ove...
2.0.0-BETA3
This is the third beta release of the 2.0.0 series.
Users are encouraged to try this new version, and to verify if there are any BC breaks other than the documented ones.
You can install this component by running:
composer require ocramius/proxy-manager:2.0.0-BETA3@BETA
New features
PHP 7 support
ProxyManager will now correctly operate in PHP 7 environments.
PHP 7 Return type hints
ProxyManager will now correctly mimic signatures of methods with return type hints:
class SayHello
{
public function hello() : string
{
return 'hello!';
}
}
PHP 7 Scalar type hints
ProxyManager will now correctly mimic signatures of methods with scalar type hints
class SayHello
{
public function hello(string $name) : string
{
return 'hello, ' . $name;
}
}
PHP 5.6 Variadics support
ProxyManager will now correctly mimic behavior of methods with variadic parameters:
class SayHello
{
public function hello(string ...$names) : string
{
return 'hello, ' . implode(', ', $names);
}
}
By-ref variadic arguments are also supported:
class SayHello
{
public function hello(string ... & $names)
{
foreach ($names as & $name) {
$name = 'hello, ' . $name;
}
}
}
Constructors in proxies are not replaced anymore
In ProxyManager v1.x, the constructor of a proxy was completely replaced with a method
accepting proxy-specific parameters.
This is no longer true, and you will be able to use the constructor of your objects as
if the class wasn't proxied at all:
class SayHello
{
public function __construct()
{
echo 'Hello!';
}
}
/* @var $proxyGenerator \ProxyManager\ProxyGenerator\ProxyGeneratorInterface */
$proxyClass = $proxyGenerator->generateProxy(
new ReflectionClass(SayHello::class),
new ClassGenerator('ProxyClassName')
);
eval('<?php ' . $proxyClass->generate());
$proxyName = $proxyClass->getName();
$object = new ProxyClassName(); // echoes "Hello!"
var_dump($object); // a proxy object
If you still want to manually build a proxy (without factories), a
public static staticProxyConstructor
method is added to the generated proxy classes.
Friend classes support
You can now access state of "friend objects" at any time.
class EmailAddress
{
private $address;
public function __construct(string $address)
{
assertEmail($address);
$this->address = $address;
}
public function equalsTo(EmailAddress $other)
{
return $this->address === $other->address;
}
}
When using lazy-loading or access-interceptors, the equalsTo
method will
properly work, as even protected
and private
access are now correctly proxied.
Ghost objects now only lazy-load on state-access
Lazy loading ghost objects now trigger lazy-loading only when their state is accessed.
This also implies that lazy loading ghost objects cannot be used with interfaces anymore.
class AccessPolicy
{
private $policyName;
/**
* Calling this method WILL cause lazy-loading, when using a ghost object,
* as the method is accessing the object's state
*/
public function getPolicyName() : string
{
return $this->policyName;
}
/**
* Calling this method WILL NOT cause lazy-loading, when using a ghost object,
* as the method is not reading any from the object.
*/
public function allowAccess() : bool
{
return false;
}
}
Faster ghost object state initialization
Lazy loading ghost objects can now be initialized in a more efficient way, by avoiding
reflection or setters:
class Foo
{
private $a;
protected $b;
public $c;
}
$factory = new \ProxyManager\Factory\LazyLoadingGhostFactory();
$proxy = $factory-createProxy(
Foo::class,
function (
GhostObjectInterface $proxy,
string $method,
array $parameters,
& $initializer,
array $properties
) {
$initializer = null;
$properties["\0Foo\0a"] = 'abc';
$properties["\0*\0b"] = 'def';
$properties['c'] = 'ghi';
return true;
}
);
$reflectionA = new ReflectionProperty(Foo::class, 'a');
$reflectionA->setAccessible(true);
var_dump($reflectionA->getValue($proxy)); // dumps "abc"
$reflectionB = new ReflectionProperty(Foo::class, 'b');
$reflectionB->setAccessible(true);
var_dump($reflectionB->getValue($proxy)); // dumps "def"
var_dump($proxy->c); // dumps "ghi"
Skipping lazy-loaded properties in generated proxies
Lazy loading ghost objects can now skip lazy-loading for certain properties.
This is especially useful when you have properties that are always available,
such as identifiers of entities:
class User
{
private $id;
private $username;
public function getId() : int
{
return $this->id;
}
public function getUsername() : string
{
return $this->username;
}
}
/* @var $proxy User */
$proxy = (new \ProxyManager\Factory\LazyLoadingGhostFactory())->createProxy(
User::class,
function (
GhostObjectInterface $proxy,
string $method,
array $parameters,
& $initializer,
array $properties
) {
$initializer = null;
var_dump('Triggered lazy-loading!');
$properties["\0User\0username"] = 'Ocramius';
return true;
},
[
'skippedProperties' => [
"\0User\0id",
],
]
);
$idReflection = new \ReflectionProperty(User::class, 'id');
$idReflection->setAccessible(true);
$idReflection->setValue($proxy, 123);
var_dump($proxy->getId()); // 123
var_dump($proxy->getUsername()); // "Triggered lazy-loading!", then "Ocramius"
Proxies are now always generated on-the-fly by default
Proxies are now automatically generated any time you require them: no configuration
needed. If you want to gain better performance, you may still want to read
the tuning for production docs.
Proxy names are now hashed, simplified signature is attached to them
Proxy classes now have shorter names, as the parameters used to generate them are
hashed into their name. A signature is attached to proxy classes (as a private static
property) so that proxy classes aren't re-used across library updates.
Upgrading ProxyManager will now cause all proxies to be re-generated automatically,
while the old proxy files are going to be ignored.
BC Breaks - backwards-incompatible changes
- PHP
~7.0
is now required to use ProxyManager - HHVM compatibility is not guaranteed, as HHVM is not yet PHP 7 compliant
- All classes and interfaces now use strict scalar type hints.
If you extended or implemented anything from theProxyManager\
namespace, you probably need to change
that code to adapt it to the new signature. - All classes and interfaces now use return type declarations.
If you extended or implemented anything from theProxyManager\
namespace, you probably need to change
that code to adapt it to the new signature. - ProxyManager will no longer write proxies to disk by default:
theEvaluatingGeneratorStrategy
is used instead.
If you still want ProxyManager to write files to disk, please refer to the tuning for production docs - Ghost objects were entirely rewritten, for better support and improved performance. Lazy-loading is not
triggered by public API access, but by property access (private and public). While this is not really a BC
break, you are encouraged to check your applications if you rely on ghost objects. - If ProxyManager can't find a proxy, it will now automatically attempt to auto-generate it, regardless of
the settings passed to it. ProxyManager\Configuration#setAutoGenerateProxies()
was removed. Please look for calls to this method and
remove them.- Private properties are now also correctly handled by ProxyManager: accessing proxy state via friend classes
(protected or private scope) does not require any particular workarounds anymore. ProxyManager\Version::VERSION
was removed. Please useProxyManager\Version::getVersion()
instead.- PHP 4 style constructors are no longer supported
Changes (raw log)
Total issues resolved: 65
- 97: Private properties of superclasses are not considered when generating proxies
- 105: Make the evaluating generator strategy a default
- 115: RFC: Recited: Give me my constructor back
- 128: Removal of PHP 5.3 support
- 130: [WIP\ Master branch dev version / 2.0.x dependencies
- 152: Rewrite Ghost Objects to only rely on property lazy loading
- 159: Ideas/considerations for GhostObject Proxies lazy loading
- 167: Drop PHP 5.4 support
- 175: Avoid constructor override
- [177: Add variadics support](https://github.com/Ocramius/ProxyManager/issues/...
2.0.0-BETA2
This is the second beta release of the 2.0.0 series.
Details on the new features will follow in further release notes.
For now, existing users are encouraged to try this new version, and to verify if there are any BC breaks other than the documented ones.
You can install this component by running:
composer require ocramius/proxy-manager:2.0.0@BETA
Total issues resolved: 59
- 97: Private properties of superclasses are not considered when generating proxies
- 105: Make the evaluating generator strategy a default
- 115: RFC: Recited: Give me my constructor back
- 128: Removal of PHP 5.3 support
- 130: [WIP\ Master branch dev version / 2.0.x dependencies
- 152: Rewrite Ghost Objects to only rely on property lazy loading
- 159: Ideas/considerations for GhostObject Proxies lazy loading
- 167: Drop PHP 5.4 support
- 175: Avoid constructor override
- 177: Add variadics support
- 184: Split documentation homepage into a "features" page, remove duplicate content
- 186: Remove deprecated
ProxyManager\Configuration#setAutoGenerateProxies()
- 192: Lazy-loading of ghost objects only via properties access (no method overrides)
- 200: Remove deprecated methods on ProxyManager\Configuration
- 203: Remove duplicated content on documentation #184
- 204: Cleanup: #167 - remove PHP 5.4 support
- 205: Skipping files/directories that are not needed in deployed versions of ProxyManager in the packaged version of the repo
- 208: Document new
GhostObject
behavior (property lazy-loading, by-ref initialization) - 209: Modify the strategy on Configuration#getGeneratorStrategy to use EvaluationGeneratorStrategy class as default
- 211: Move documentation to be generated by couscous
- 212: Allow skipping properties in
LazyLoadingGhost
for partial initialization - 214: Cleanup: unused classes removal (constructors, not needed as per #115 and #175)
- 215: Cleanup: unused imports
- 218: #97: handle private properties of superclasses
- 219: Cleanup: run codegen smoke-tests in same process
- 220: CS: imported symbols cleanups
- 221: Skip properties when use ghost objects
- 222: Hotfix: Ghost object generators cannot proxy interfaces, therefore should throw exceptions
- 224: Disable private/protected property checks during lazy loading initialization of GhostObjects
- 225: #224 - GhostObjects can simply ignore scope checks during lazy-loading (temporarily fixes #210)
- 232: Variadic function support
- 234: Fix html titles
- 237: remove unused title table at README.md ?
- 238: Fix title when rendering
- 239: Skip test inapplicable to php7
- 240: Support scalar type hints (PHP 7)
- 246: Don't suggest package that is already required.
- 247: Hotfix: PHP 7 warnings on binding internal classes
- 251: Hotfix - #249 file writer generator strategy rename failures (2.0.x rebase)
- 252: Moving to new travis build infrastructure
- 255: Fix: Use all the columns
- 256: Revert #254, add integration test for options in factory logic
- 261: Fix a typo in main.css stylesheet
- 263: Broken links in footer http://ocramius.github.io/ProxyManager/
- 264: Duplicate semicolons generated
- 265: Document limitation of pre-5.6 variadic usage
- 266: #265 - by-ref variadic support
- 267: #264 - duplicate semicolon removal
- 268: #263 - correcting links in the footer of the docs
- 271: Feature - #241 - support scalar type hints
- 273: The homepage of the doc is confusing
- 274: Add scalar and return type hints where applicable, use strict types
- 276: Test protected member access lazy loading (ghost objects)
- 277: Fix/#276 protected member access via friend objects
- 278: #274 - scalar type hints, return type hints, strict types
- 279: Feature - #274 void and missing return types
- 280: #273 - fix homepage docs link, fix presentation link
- 281: Docs - #208 document new ghost object behavior
- 282: Grammar improvements to lazy loading ghost object docs
2.0.0-BETA1
This is the first beta release of the 2.0.0 series.
Details on the new features will follow in further release notes.
For now, existing users are encouraged to try this new version, and to verify if there are any BC breaks other than the documented ones.
You can install this component by running:
composer require ocramius/proxy-manager:2.0.0@BETA
Total issues resolved: 59
- 97: Private properties of superclasses are not considered when generating proxies
- 105: Make the evaluating generator strategy a default
- 115: RFC: Recited: Give me my constructor back
- 128: Removal of PHP 5.3 support
- 130: [WIP\ Master branch dev version / 2.0.x dependencies
- 152: Rewrite Ghost Objects to only rely on property lazy loading
- 159: Ideas/considerations for GhostObject Proxies lazy loading
- 167: Drop PHP 5.4 support
- 175: Avoid constructor override
- 177: Add variadics support
- 184: Split documentation homepage into a "features" page, remove duplicate content
- 186: Remove deprecated
ProxyManager\Configuration#setAutoGenerateProxies()
- 192: Lazy-loading of ghost objects only via properties access (no method overrides)
- 200: Remove deprecated methods on ProxyManager\Configuration
- 203: Remove duplicated content on documentation #184
- 204: Cleanup: #167 - remove PHP 5.4 support
- 205: Skipping files/directories that are not needed in deployed versions of ProxyManager in the packaged version of the repo
- 208: Document new
GhostObject
behavior (property lazy-loading, by-ref initialization) - 209: Modify the strategy on Configuration#getGeneratorStrategy to use EvaluationGeneratorStrategy class as default
- 211: Move documentation to be generated by couscous
- 212: Allow skipping properties in
LazyLoadingGhost
for partial initialization - 214: Cleanup: unused classes removal (constructors, not needed as per #115 and #175)
- 215: Cleanup: unused imports
- 218: #97: handle private properties of superclasses
- 219: Cleanup: run codegen smoke-tests in same process
- 220: CS: imported symbols cleanups
- 221: Skip properties when use ghost objects
- 222: Hotfix: Ghost object generators cannot proxy interfaces, therefore should throw exceptions
- 224: Disable private/protected property checks during lazy loading initialization of GhostObjects
- 225: #224 - GhostObjects can simply ignore scope checks during lazy-loading (temporarily fixes #210)
- 232: Variadic function support
- 234: Fix html titles
- 237: remove unused title table at README.md ?
- 238: Fix title when rendering
- 239: Skip test inapplicable to php7
- 240: Support scalar type hints (PHP 7)
- 246: Don't suggest package that is already required.
- 247: Hotfix: PHP 7 warnings on binding internal classes
- 251: Hotfix - #249 file writer generator strategy rename failures (2.0.x rebase)
- 252: Moving to new travis build infrastructure
- 255: Fix: Use all the columns
- 256: Revert #254, add integration test for options in factory logic
- 261: Fix a typo in main.css stylesheet
- 263: Broken links in footer http://ocramius.github.io/ProxyManager/
- 264: Duplicate semicolons generated
- 265: Document limitation of pre-5.6 variadic usage
- 266: #265 - by-ref variadic support
- 267: #264 - duplicate semicolon removal
- 268: #263 - correcting links in the footer of the docs
- 271: Feature - #241 - support scalar type hints
- 273: The homepage of the doc is confusing
- 274: Add scalar and return type hints where applicable, use strict types
- 276: Test protected member access lazy loading (ghost objects)
- 277: Fix/#276 protected member access via friend objects
- 278: #274 - scalar type hints, return type hints, strict types
- 279: Feature - #274 void and missing return types
- 280: #273 - fix homepage docs link, fix presentation link
- 281: Docs - #208 document new ghost object behavior
- 282: Grammar improvements to lazy loading ghost object docs
1.0.2
1.0.1
Total issues resolved: 2
- 249: Weird problem with FileWriterGeneratorStrategy
- 250: Hotfix - #249 file writer generator strategy rename failures
Note: this release was incorrectly tagged, please use 1.0.2 instead.