Standby for Release
We are skipping the 4.173 release this week, and are revisiting our release process. We expect to share an update in the coming weeks.
Michael O'Farrell
Posted November 14, 2022
We are skipping the 4.173 release this week, and are revisiting our release process. We expect to share an update in the coming weeks.
Alexey Toptygin
Posted November 02, 2022
HHVM 4.172 is released! 4.169 - 4.171 remain supported, as do the 4.168 and 4.153 LTS releases.
require class <that class>
from being mocked.
(commit)--module or --cmodule options as of this release.
Please use their new names --dir and --cdir instead (new names added in
release 4.169). This change is intended to avoid confusion wht the ‘modules’
experimental feature.
(commit)dynamic and another type; e.g. ~int
for the union of dynamic and int) are enforced in argument and return type
positions. Previously they were enfoced the same as the dynamic type (i.e.
any value would be accepted) but after this release they are enforced as the
other type in the union would be (e.g. for ~int only integer values will
now be accepted).
(commit)
See also
(commit)
for related changes adding new ways to write aspirational, un-enforced types
via helpers in the HH\FIXME namespace.Bo Yang
Posted October 21, 2022
HHVM 4.153.3, 4.167.1, 4.168.1, 4.169.1, 4.170.1 and 4.171.0 are released! 4.167.1 is the last release in 4.167 branch, while 4.168 - 4.170 remain supported, as does the 4.153 LTS release.
Note that HHVM 4.153.2 is also released accidentally, but it does not include any meaningful change since 4.153.1.
These releases fixes an issue introduced in 4.153.0 (commit). When combining with another commit introduced in 4.168.0, it leads to a segmentation fault when building a bytecode repository for repo-authoritative mode in gcc built HHVM. Earlier releases are not affected.
--inputs from --ffile, which was dropped in HHVM
4.167.ReflectionClass::getModule() (commit).ReflectionModule::getDocComment() (commit).HH\classname_from_string_unsafe to convert a string into a lazy class (commit).HH\embed_type_decl now supports repo mode (commit).clearTerseFields functions in generated
code
(commit).
Regenerating Hack files from the thrift definition with the latest thrift
compiler
would provide the required clearTerseFields functions.hh_server flags are renamed:
Alexey Toptygin
Posted October 07, 2022
HHVM 4.170 is released! 4.167 - 4.169 remain supported, as does the 4.168 and 4.153 LTS releases.
type_structure(MyCoolType::class, 'TUhOh')
when type MyCoolType = shape(...) Previously this was not flagged by
the typechecker but would fatal at runtime.
(commit)Foo::class expressions emit ‘lazy’
class pointers) is now the only supported behavior.
(commit)foo*bar = value or *foobar* = value in HDF configs. Adding values to
a vector-typed config node such as MyVectorConfig.* = value remains
supported.
(commit)We are still working on a fix for https://github.com/facebook/hhvm/issues/9236 (inability to compile a repo in gcc builds of hhvm since release 4.168). If you rely on this functionality consider skipping this release or using nix packages built with clang. We will release updated versions of all supported releases once the fix is available.
Bo Yang
Posted September 20, 2022
HHVM 4.169 is released! 4.166 - 4.168 remain supported, as does the 4.153 LTS releases.
hackfmt now only allows up to 1 consecutive blank lines (previously 2).--module and --cmodule are being renamed to --dir
and --cdir to avoid confusion with the experimental ‘modules’ feature.
(This item was retroactively added to this announcement on 2022.11.02).$callback passed to fb_setprofile now receives all parameters,
including non-default and default parameters. Previously only non-default
parameters are passed to $callback.Alexey Toptygin
Posted September 09, 2022
HHVM 4.168 (LTS) is released! This release has long term support, so:
We had intended for this release to have Ubuntu 22.04 support, but we are releasing without that support for now. Due to library version compatibility issues, we need more time to get this support working, and we did not want to delay the release for other platforms. We intend to make a 4.168.1 release with 22.04 support as soon as we get builds working on 22.04.
Note that our experimental universal packages (also available for version 4.168) are not affected by this issue and should be usable on any version of Ubuntu.
Expected Awaitable<[unresolved]> But got int becomes Expected
Awaitable<_> But got int
(commit)Bo Yang
Posted August 30, 2022
We’re happy to announce the availability of universal deb packages of HHVM, which do not depend on system libraries and are expected to run on any version of Debian, Ubuntu or any other Linux distributions with apt package manager.
The universal deb packages is still considered experimental like nix packages. We encourage you to try it out and report any issues you encountered. We will appreciate your feedback because it will help us decide if we will entirely switch from distribution-specific packaging to universal packaging.
These instructions require root; use su - or sudo -i to get a root shell
first.
1
2
3
4
5
6
7
apt-get update &&
apt-get install --yes software-properties-common apt-transport-https &&
apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xB4112585D386EB94 &&
add-apt-repository 'deb https://dl.hhvm.com/universal release main' &&
apt-get update &&
apt-get install --yes hhvm &&
hhvm --version
1
2
3
4
5
6
7
apt-get update &&
apt-get install --yes software-properties-common apt-transport-https &&
apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xB4112585D386EB94 &&
add-apt-repository 'deb https://dl.hhvm.com/universal release-4.167 main' &&
apt-get update &&
apt-get install --yes hhvm &&
hhvm --version
Currently 4.167 is the only release version including universal deb packages.
For future releases, you will be able to specify the apt suite name as
release-x.yyy, where x is the major version and yyy is the minor version.
1
2
3
4
5
6
7
apt-get update &&
apt-get install --yes software-properties-common apt-transport-https &&
apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xB4112585D386EB94 &&
add-apt-repository 'deb https://dl.hhvm.com/universal nightly main' &&
apt-get update &&
apt-get install --yes hhvm &&
hhvm --version
Note that the universal deb packages are built with nix package manager and then get repacked into deb format. As a result, the universal deb packages will conflict with packages directly installed from the nix package manager. If you are a nix package manager user, you should directly use the nix packages announced in this post, instead of the universal deb packages in case of path conflicts.
Wilfred Hughes
Posted August 24, 2022
HHVM 4.167 is released! 4.164 - 4.166 remain supported, as do the 4.128 and 4.153 LTS releases.
ext_json, ext_folly_variant,
ext_thrift, ext_zlib, ext_server, ext_enum) have more
extensive typing in their .hhi files, so the type checker can check
code using them..hackpartial settings in .hhconfig have been removed,
specifically allowed_fixme_codes_partial, codes_not_raised_partial
and strict_codes.hh_client now supports a --is-subtype to see if types are
compatible, using JSON from --type-at-pos
(commit).<<__Memoize>> and <<__MemoizeLSB>> on a method
is now a type error.hhvm command.
--ffile--target-tBo Yang
Posted August 10, 2022
HHVM 4.166 is released! 4.163 - 4.165 remain supported, as do the 4.128 and 4.153 LTS releases.
This release does not compile on Ubuntu 21.04 and 21.10. Both versions have reached End of Life earlier this year according to this post and this post. We are aware that we have not provided deb packages for Ubuntu 22.04 LTS. For now, Ubuntu 22.04 users could try our experimental HHVM binary built with Nix, which should be able to run on any Linux distribution.
class C { public dynamic $d
= 3 upcast dynamic; }%'(char) in sprintf.<<__Docs("http://example.com")>> to type, newtype,
enums and enum classes, which shows the docs URL in the IDE’s hover information<<__Memoize(#SoftMakeICInaccessible)>><<__Memoize(#MakeICInaccessible)>><<__PolicyShardedMemoize>><<__PolicyShardedMemoizeLSB>>null default parameter with non-nullable type hint result in errorlambdaType(...).__unwrap() method instead of direct invoking.Wilfred Hughes
Posted August 02, 2022
HHVM 4.165 is released! 4.162 - 4.164 remain supported, as do the 4.128 and 4.153 LTS releases.
This release does not compile on Ubuntu 18.04. Ubuntu 18.04 is outside our support lifecycle and this is the first HHVM version that depends on newer C++ features.
hh now computes smaller fanouts in some circumstances (such as
enum
constraints),
making incremental typecheckers faster.Bo Yang
Posted July 12, 2022
We’re happy to announce that the Nix packages of HHVM are now available, as is the public CI status on GitHub Actions for it, and the Visual Studio Code workspace with HHVM dependencies from Nix. The Nix packages can be run on macOS and Linux of any distributions.
Currently, HHVM’s Nix packages are not officially supported, yet. They are provided as is and haven’t been extensively battle-tested. Since we have dropped macOS Homebrew support, it is likely that we will also stop building HHVM with Nix on macOS in the future, too.
For NixOS users, add the following settings to /etc/nixos/configuration.nix to
configure the binary cache for HHVM:
1
2
3
4
5
6
7
nix.settings.substituters = [ "s3://hhvm-nix-cache?region=us-west-2&endpoint=hhvm-nix-cache.s3-accelerate.amazonaws.com" ];
nix.settings.trusted-substituters = [ "s3://hhvm-nix-cache?region=us-west-2&endpoint=hhvm-nix-cache.s3-accelerate.amazonaws.com" ];
nix.settings.trusted-public-keys = [ "hhvm-nix-cache-1:MvKxscw16fAq6835oG8sbRgTGITb+1xGfYNhs+ee4yo=" ];
nix.settings.experimental-features = [ "nix-command" "flakes" ];
environment.systemPackages = [
pkgs.git # Required to support git+https protocol
];
In addition, if you want to build HHVM from source, add the following setting to disable sandboxing because HHVM cannot be built in Nix’s sandboxing build environment.
1
nix.settings.sandbox = false;
Then execute the following shell command to apply the configuration to the system:
1
nixos-rebuild switch
Then add HHVM to system packages,
1
2
3
4
environment.systemPackages = [
(builtins.getFlake "git+https://github.com/facebook/hhvm.git?submodules=1&shallow=1&ref=refs/tags/nightly-2022.07.08").packages.x86_64-linux.default
pkgs.git
];
and apply the configuration, again:
1
nixos-rebuild switch
Now hhvm is available.
1
hhvm --version
1
2
3
HipHop VM 4.164.0-dev (rel) (non-lowptr)
Compiler: 1657256394_118415120
Repo schema: 9845ff37f3bb751abbb48e4c823aa5641d5cb453
The above configuration has been tested on NixOS unstable and 22.11. The configuration for older NixOS might be different.
For Linux users other than NixOS, the HHVM Nix package can be installed with the following command if you have a multi-user installation of Nix:
1
2
3
4
5
6
7
8
9
10
11
12
(
sudo tee -a /etc/nix/nix.conf <<EOF
extra-experimental-features = nix-command flakes
extra-substituters = s3://hhvm-nix-cache?region=us-west-2&endpoint=hhvm-nix-cache.s3-accelerate.amazonaws.com
extra-trusted-substituters = s3://hhvm-nix-cache?region=us-west-2&endpoint=hhvm-nix-cache.s3-accelerate.amazonaws.com
extra-trusted-public-keys = hhvm-nix-cache-1:MvKxscw16fAq6835oG8sbRgTGITb+1xGfYNhs+ee4yo=
sandbox = false
EOF
) &&
sudo systemctl restart nix-daemon &&
nix profile install 'git+https://github.com/facebook/hhvm.git?submodules=1&shallow=1&ref=refs/tags/nightly-2022.07.08' &&
hhvm --version
Or if you have a single-user installation of Nix:
1
2
3
4
5
6
7
8
9
10
11
(
cat >> ~/.config/nix/nix.conf <<EOF
extra-experimental-features = nix-command flakes
extra-substituters = s3://hhvm-nix-cache?region=us-west-2&endpoint=hhvm-nix-cache.s3-accelerate.amazonaws.com
extra-trusted-substituters = s3://hhvm-nix-cache?region=us-west-2&endpoint=hhvm-nix-cache.s3-accelerate.amazonaws.com
extra-trusted-public-keys = hhvm-nix-cache-1:MvKxscw16fAq6835oG8sbRgTGITb+1xGfYNhs+ee4yo=
sandbox = false
EOF
) &&
nix profile install 'git+https://github.com/facebook/hhvm.git?submodules=1&shallow=1&ref=refs/tags/nightly-2022.07.08' &&
hhvm --version
The above configuration is tested on Nix 2.9.1. The configuration for older Nix might be different.
For macOS users, the HHVM Nix package can be installed with the following command if you have a multi-user installation of Nix:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
(
sudo tee -a /etc/nix/nix.conf <<EOF
extra-experimental-features = nix-command flakes
extra-substituters = s3://hhvm-nix-cache?region=us-west-2&endpoint=hhvm-nix-cache.s3-accelerate.amazonaws.com
extra-trusted-substituters = s3://hhvm-nix-cache?region=us-west-2&endpoint=hhvm-nix-cache.s3-accelerate.amazonaws.com
extra-trusted-public-keys = hhvm-nix-cache-1:MvKxscw16fAq6835oG8sbRgTGITb+1xGfYNhs+ee4yo=
sandbox = false
EOF
) &&
sudo launchctl remove org.nixos.nix-daemon &&
sudo launchctl load /Library/LaunchDaemons/org.nixos.nix-daemon.plist &&
sleep 3 &&
nix profile install 'git+https://github.com/facebook/hhvm.git?submodules=1&shallow=1&ref=refs/tags/nightly-2022.07.08' &&
hhvm --version
The above configuration is tested on Nix 2.9.1. The configuration for older Nix might be different.
The HHVM version to install is specified in the optional ref parameter in the
URL, which can be any git branch or tag. For example:
nix profile install
'git+https://github.com/facebook/hhvm.git?submodules=1&shallow=1'nix profile install
'git+https://github.com/facebook/hhvm.git?submodules=1&shallow=1&ref=refs/tags/nightly-2022.07.08'nix profile install
'git+https://github.com/facebook/hhvm.git?submodules=1&shallow=1&ref=refs/tags/HHVM-4.164.0'nix profile install
'git+https://github.com/facebook/hhvm.git?submodules=1&shallow=1&ref=refs/heads/HHVM-4.164'Since HHVM is built with Nix for new HHVM versions only, the ref parameter must
point to a child commit of
21870f6097ac7dea56ea57cc9113bcfd0d1a03d0.
Also note that the binary cache for a git commit would take hours of time to be available. If you are trying to install a recent commit, of which the binary cache is not available yet, Nix will build it from source for you automatically, otherwise Nix will just download the prebuilt binary.
We provide a Visual Studio Code workspace to develop HHVM. To set up the VS Code based HHVM development environment on any Linux or macOS machines:
git clone
https://github.com/facebook/hhvm.git --depth 1 --recurse-submodules hhvm.code-workspace from Visual Studio CodeSee this instructional video for more detail.
Alternatively, we also provide a development container with Nix pre-installed, which can be either used in a local Docker engine or in GitHub Codespaces.
See this instructional video for more detail.
To start a clean build HHVM from source:
git clone
https://github.com/facebook/hhvm.git --depth 1 --recurse-submodulesnix-buildTo incrementally edit the source and build HHVM:
git clone
https://github.com/facebook/hhvm.git --depth 1 --recurse-submodulesnix-shell to
enter a development shell. All the HHVM dependencies and development tools
will be available in $PATH and other environment
variables.cmake -C "$CMAKE_INIT_CACHE" -Bbuild
to configure HHVM.cd build && make to build HHVM.make to compile the affected files
only.Feel free to directly edit files in the HHVM repository on GitHub website and create a pull request for ad-hoc changes. We have introduced GitHub Actions to build and test your pull requests with Nix. Just take the advantage from the CI signal and have fun!
Wilfred Hughes
Posted July 08, 2022
HHVM 4.164 is released! 4.161 - 4.163 remain supported, as do the 4.128 and 4.153 LTS releases.
Bo Yang
Posted June 22, 2022
HHVM 4.163 is released! 4.160 - 4.162 remain supported, as do the 4.128 and 4.153 LTS releases.
HH\str_bitwise_xor to perform bitwise xor operator on strings1
2
3
4
5
6
7
interface I1 {
const type T = int;
}
interface I2 {
abstract const type T = float;
}
class C implements I1, I2 {}
Alexey Toptygin
Posted June 17, 2022
We are continuing support for it on LTS releases (4.128 and 4.153) until they reach EOL, but we are stopping nightly builds of HHVM on MacOS homebrew, will no longer be publishing MacOS homebrew packages for new releases, and will not be testing new versions of HHVM on MacOS going forward.
We are dropping support for two reasons. First, Homebrew has proven difficult to support. Dependency versions change out from under us which require retroactive fixes and back-porting retroactive fixes to LTS releases. Second, due to the current state of HHVM ARM support we are not able to provide a good experience on M1 Macs.
We recommend users on Intel macs switch to using one of our docker images. We are unable to support M1 users due to the different architecture and limitations of Rosetta. Therefore, we must recommend use of an Intel linux host instead.
Bo Yang
Posted June 09, 2022
HHVM 4.162 is released! 4.159 - 4.161 remain supported, as do the 4.128 and 4.153 LTS releases.
parent::__constructimplements and extends\Error as the $previous argument to the \Error constructor does not violate an internal typed property anymore. The argument to the constructor has/had the ?\Throwable type, but the $throwable->previous property had the ?\Exception type. Depending on the value of hhvm.check_prop_type_hints key in your configuration, this violation used to trigger a warning (the default), throw an \Error, or do nothing.Exception, Error, and Throwable methods and propertiesAlexey Toptygin
Posted June 01, 2022
HHVM 4.161 is released! 4.157 - 4.160 remain supported, as do the 4.128 and 4.153 LTS releases.
require class C
constraint to access the protected members of the parents of C// as part of the
docblock if there are completely empty lines between that comment line and the
definition being documented. This fixes some cases where file-level comments
were being spuriously considered part of the docblock for the first thing
defined in the file.apc_fetch_with_pure_wakeup, apc_store_with_pure_sleep, and
apc_add_with_pure_sleep APIs were published. These allow interacting with APC
while enforcing that the __sleep and __wakeup magic methods won’t observe
global state or produce side-effects.Alexey Toptygin
Posted May 12, 2022
HHVM 4.160 is released! 4.155 - 4.159 remain supported, as do the 4.128 and 4.153 LTS releases.
_$shape['optional_field'] into
Shapes::idx($shape, 'optional_field')<<__SafeGlobalVariable>>
has been renamed to <<__SafeForGlobalWriteCheck>>Alexey Toptygin
Posted May 05, 2022
As noted in the HHVM 4.153 release post, we are moving to releases every other week. The plan detailed in that post had us moving to releasing every 2 weeks starting after HHVM 4.156, but for administrative reasons that was delayed. As a result, this is the first week with no release, and this post is just a reminder of why. The next release (HHVM 4.160) is planned for next week.
Bo Yang
Posted April 26, 2022
HHVM 4.159 is released! 4.154 - 4.158 remain supported, as do the 4.128 and 4.153 LTS releases.
<<__SafeGlobalVariable>> to mark global variables as safe,
ensuring no errors/warnings would be raised from writing to this global
variable, when --enable-global-write-check is passed to hh_server. Note
that this attribute will be renamed to <<__SafeForGlobalWriteCheck>> in the
next release.// FALLTHROUGH).Bo Yang
Posted April 20, 2022
HHVM 4.158 is released! This release marks the end of support of 4.151; 4.153 - 4.157 remain supported, as does the 4.128 LTS release.
switch statementsHH_FIXME error code of direct writes to static variables. Now:
elseif keywordAlexey Toptygin
Posted April 14, 2022
HHVM 4.157 is released! This release marks the end of support of 4.150; 4.151 - 4.156 remain supported, as does the 4.128 LTS release.
__FILE__ and __DIR__ magic constants in traitsFred Emmott
Posted April 08, 2022
HHVM 4.156 is released! This release marks the end of support of 4.149; 4.150 - 4.155 remain supported, as does the 4.128 LTS release.
HH\FIXME_UNSAFE_CAST<mixed, T>($expr)
if the type of $expr is non-denotable and expression-dependent, e.g. if
IDE hover information or hh_client --type-at-pos shows a type like
<expr#1>::THH\serialize_with_options now supports a disallowObjects option, which
disallows serialization of objects except for legacy Hack Collections.$x = 1_234_567_890; sets $x to the integer 1234567890.use clauseBo Yang
Posted March 31, 2022
HHVM 4.155 is released! This release marks the end of support of 4.148; 4.149 - 4.154 remain supported, as does the 4.128 LTS release.
HHVM_COMPILER_TIMESTAMP constant to hhi for type checker, which contains the timestamp to build hhvm.create_opaque_value and unwrap_opaque_valueHH\Lib\Math\to_basehash_*function
foo(int):int in a super class can be overridden as function foo<T>(T):T in a subclass.--single options in hh_client invocations.array_fill (See CVE-2022-27809).defaults capability.int when
one of the operands is an unsolved type.Eval.EnableZendIniCompat.--force--gen-stats--sync-dir--target--program--args--include-path--branch--revision--config-dir--output-dir argument:interface
A<T> { function f<T1>(T $a): T1; }, if A is implemented in a class
introducing type parameter name clash as class B<T1> extends A<T1> { function
f<T1>(T1 $a): T1 { return $a; } }, when upcasting B to A, /*A<int>*/ $a = new
B<int>();, it would allow for arbitrary type convention like
Str\length($a->f(1));.Bo Yang
Posted March 29, 2022
A security update has been released for all supported HHVM versions. Please update to one of the following versions to get the update:
This security update addresses:
array_fill leads to uninitialized variable referenceFred Emmott
Posted March 24, 2022
HHVM 4.154 is released! This release marks the end of support of 4.147; 4.148 - 4.153 remain supported, as does the 4.128 LTS release.
void/Awaitable<void> return type for functions that do not return a valueSrcKey structshphpd_break() and hphp_debug_break() can now be used in pure functionsstream_get_meta_data() no longer crashes debug builds of HHVM when called on a closed fileHH\Asio\curl_exec no longer has an unneeded exponential backoff--hphp command (used for creating hhvm.hhbc for repo auth mode) interprets paths differently. On previous versions of hhvm --module . would include the current working directory in the repo. You must now explicitly provide all directories and files with Hack code using multiple flags, for example --module src --module vendor --ffile public/index.hack.Fred Emmott
Posted March 17, 2022
HHVM 4.153 is released! This release has long term support, so:
A final release of 4.102 - 4.102.7 - has been made to fix compatibility issues on MacOS.
We moved from monthly to weekly releases in 2019 due to the large rate of breaking changes, and the difficulty in keeping up with them; we believe that the severity of the breaking changes has decreased over time, and that the improved tooling and increased soundness of the language has changed this situation over the last few years.
We aim for 4.156 to be the last weekly release, and will then be moving to a two-week release schedule; we hope that this is a stepping stone on the way to a monthly release cycle, with an eventual goal of it being practical for the community to primarily target our LTS releases. We actively welcome feedback, and are open to reverting back to weekly releases if it is best for the commuinty.
We hope that this move will reduce work for community maintainers, and make standard approaches such as semantic versioning more practical.
\HH\Lib\OS\posix_spawnp and \HH\Lib\OS\posix_spawn, which supports a
subset functionality of the corresponding POSIX C API.getopt_with_optind native function to support simple subparsers.nonnull, the body is now typechecked as
if the untyped parameters were mixed instead of nonnull, which is
consistent with passing an untyped lambda as mixed or dynamic (where
parameters are assumed to be mixed or dynamic, respectively). Previously,
passing an untyped lambda as nonnull would always raise error 4224: “Cannot
determine types of lambda parameters in strict mode”.async from
interface methods. async interface methods and abstract methods are already
an error, as it is an implementation detail - the Awaitable<T> return type
specifies how it is called.newinout parameters can now be dynamic.pcntl_waitpid() and pcntl_wait() now work correctly in server modes -
proxygen, fastcgi, and CLI-serverFile\leaky_temporary_file() which requires manual closing
and deletion. File\temporary_file() remains strongly encouraged where
possible.resources can now be passed as dynamic. resource remains strongly
discouraged in cases where alternatives exist.($this->f)() now requires readonly check if the return type of f is
readonly.Set keys; (Set {})->add($non_arraykey) now properly
raises a type error.<<__ProvenanceSkipFrame>> has been removed from the HSL; this was an
unsupported annotation that was previously intended for PHP array to
vec/dict/keyset migration.unset statement parameters can no longer contain function calls.Bo Yang
Posted March 02, 2022
HHVM 4.151 is released! This release marks the end of support of 4.145; 4.146 - 4.150 remain supported, as do the 4.102 and 4.128 LTS releases.
hphpd_break and hphp_debug_break are now marked as pure.HHVM_COMPILER_TIMESTAMP) and read-only ini setting
(ini_get('hphp.compiler_timestamp')) that contain the timestamp to build
hhvm (which is itself part of the HHVM_COMPILER_ID and hphp.compiler_id
constant and ini setting).abstract enum class is not considered an experimental feature any more.dict or a keyset is now always inferred as a subtype of
arraykey even when used with dynamic. For example, previously the key type
could be inferred as types like int|dynamic and now it would be
int|(dynamic&arraykey) in that case.Fred Emmott
Posted February 24, 2022
HHVM 4.150 is released! This release marks the end of support of 4.144; 4.145 - 4.149 remain supported, as do the 4.102 and 4.128 LTS releases.
ENT_HTML5 constant is now recognized by the typecheckergetSslCertCn(), getSslCertSan(), getSslCertExtensions(), and
isSslCertValidationEnforced() to AsyncMysqlResult and
AsyncMysqlConnection$server_cert_values parameter to AsyncMysqlClient::connect(), which
contains comma separated values that are matched against the existing
$cserver_cert_extensions parameter when verifying the certificate.class_implements(), class_parents(), and class_uses() are now marked
as puremixed but returns without a value,
LSP-based IDEs such as VSCode will now suggest void or Awaitable<void>
return typesHH\Readonly\Shapes now includes typechecker definitionsAsyncMysqlClient::adoptConnection() has been removed.meth_caller() on methods that return a
readonly object; previously, this would be a runtime error. This is due to
technical limitations of the current implementation.write_globals capability, a more specific error is raised based on the write
or passing of the return value (if mutable), instead of always when the
function is called. This may change necessary fixme codes from 4461 (“a
memoized function is called”) to 4459 (“A global variable is written”).James Wu
Posted February 22, 2022
As of HHVM version 4.139, we’ve released a new keyword called readonly in Hack. readonly is a new feature in Hack for restricting the mutability of object properties. It’s designed for use cases that require performant, runtime-enforced mutability control.
readonly has two main principles: readonlyness and deepness.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Bar {
public function __construct(
public Foo $foo,
){}
}
class Foo {
public function __construct(
public int $prop,
) {}
}
function test(readonly Foo $foo, readonly Bar $bar) : void {
$foo->prop = 5; // error, $foo is readonly
// Deepness: $x is also readonly
$x = $bar->foo;
$x->prop = 3; // error, $x is readonly
}
The readonly keyword can be used in many places in Hack.
readonly keyword.$this as readonly. Readonly values can only call readonly methods.You can see some examples of the readonly keyword in this code snippet:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Bar {
public int $prop = 0;
}
class Foo {
public function __construct(public Bar $bar, public readonly Bar $ro_bar) {}
// This method promises not to modify $this
public readonly function getBar(): readonly Bar {
// note that $this is readonly, so $this->prop is readonly, which is why
// this method must return readonly
return $this->bar;
}
public static function takesReadonlyExample(readonly Foo $x): void {
$x->bar = new Bar(); // error, $x is readonly here!
}
public static function readonlyClosureExample(): void {
$x = new Bar();
$readonly_f = readonly (): void ==> {
$x->prop = 5; // error, $x is captured as readonly since $readonly_f is a readonly function
};
$x->prop = 4; // $x is still mutable out here, so this is okay!
}
public function readonlyPropExample(Foo $foo): void {
$x = readonly new Bar();
$foo->bar = $x; // error, $x is readonly but bar is a regular property
$foo->ro_bar = $x; // ok!
}
}
Some function calls and property accesses require explicitly annotating the result of the call as readonly:
readonly keyword.readonly keyword.1
2
3
4
5
6
function testExplicitReadonly(readonly Foo $foo): void {
// vvvvvvvv This keyword is required here since getBar returns readonly
$bar = readonly $foo->getBar();
// vvvvvvvv This keyword is required here since $ro_bar is a readonly property
$ro_bar_prop = readonly $foo->ro_bar;
}
For a full guide and specification to using readonly, you can check our full documentation on the feature.
Bo Yang
Posted February 15, 2022
HHVM 4.149 is released! This release marks the end of support of 4.143; 4.144 - 4.148 remain supported, as do the 4.102 and 4.128 LTS releases.
__clone is now able to write to its own properties even when the capability set is specified as pure.class_*dyncall_*_forceReflectionProperty::{get,set}ValueReflection{Method,Property}::setAccessiblethrift_protocol_set_compact_versionmb_*$LANG is not found.Fred Emmott
Posted February 09, 2022
HHVM 4.148 is released! This release marks the end of support of 4.140; 4.143 - 4.147 remain supported, as do the 4.102 and 4.128 LTS releases.
HH\Readonly\Shapes class, partially mirroring the Shapes classHH\Lib\Str\length() now takes advantage of JIT optimizations that were
previously exclusive to \strlen()Bo Yang
Posted February 02, 2022
HHVM 4.147 is released! This release marks the end of support of 4.139; 4.140, and 4.143 - 4.146 remain supported, as do the 4.102 and 4.128 LTS releases. 4.141 and 4.142 were cancelled due to the holiday season.
thrift_protocol_set_compact_version, DateTime and mbstring functions.abstract keyword in an IDE.HH\FIXME\UNSAFE_CAST is now considered readonly if the input is readonly.case_sensitive_inheritance option is enabled)Fred Emmott
Posted January 25, 2022
HHVM 4.146 is released! This release marks the end of support of 4.138; 4.139, 4.140, and 4.143 - 4.145 remain supported, as do the 4.102 and 4.128 LTS releases. 4.141 and 4.142 were cancelled due to the holiday season.
T::foo();.CoeffectViolationException instead of a
BadMethodCallException; both extend LogicException.$this; previously, any attempts to use it would be treated as references to
the current object instance, not the parameter.ob_get_contents(), ob_get_length(), ob_get_level(), ob_get_status,
ob_list_handlers(), hphp_get_stats(), hphp_get_status(),
hphp_get_io_status(), hphp_get_timers(), hphp_instruction_counter(),
and hphp_get_hardware_counters() are now marked as [read_globals], so can
no longer be called from ‘pure’ functions.Bo Yang
Posted January 21, 2022
HHVM 4.145 is released! This release marks the end of support of 4.137; 4.138, 4.139, 4.140, 4.143, 4.144 remain supported, as do the 4.102 and 4.128 LTS releases. 4.141 and 4.142 were cancelled due to the holiday season.
function foo(dynamic $d): void { throw $d; }gethostname is now a pure function.?mixed and similar if they’re in a type hint position, including f<?mixed>() or new C<?mixed>().(foo($x))[3] = 'a' or (bar($y))[] = 45.curl_multi_exec now requires int as the second parameter.Bo Yang
Posted January 20, 2022
HHAST is a toolkit for for analyzing the structure of Hack files. It includes a linting and migration framework to find and automatically fix problems in your code. The lint errors and migration suggestions can be accessed from Hack API, command line interface or IDEs.
HHAST also ships with many built-in lint rules and migration rules. However, the HHAST built-in lint rules have limited access to the type checker, therefore, it is difficult to create a lint rule that needs to determine questions like “is this type a subtype of that type?” or “is this expression compatible with that function signature?”.
Recently, we released HHAST v4.139.0. The new version brings a proxy to run the linter from the Hack compiler written in OCaml, which includes more powerful lint rules that need the access to the type checker 1. Note that type checker based lint rules cannot be user-defined, as they must be written in OCaml, built in to the HHVM repository.
Firstly, follow the User Documentation to set up the linters for IDEs and command line tools.
The lint rules from the Hack compiler are not enabled by default, to enable them, put the following settings into your hhast-lint.json:
1
2
3
"extraLinters": [
"Facebook\\HHAST\\HHClientLinter"
],
HHClientLinter is the special linter as a proxy to run linters from the Hack compiler. Similar to the Hack typing errors, these lint rules report lint errors with 4-digit numeric codes. To avoid conflicts, the 5xxx range is reserved for Hack compiler lint rules.
HHClientLinter for particular error codesHHClientLinter can be configured to not report particular error codes by adding the following settings into your hhast-lint.json
1
2
3
4
5
"linterConfigs": {
"Facebook\\HHAST\\HHClientLinter": {
"ignore": [5624, 5639]
}
}
or if you are interested in only particular error codes:
1
2
3
4
5
"linterConfigs": {
"Facebook\\HHAST\\HHClientLinter": {
"ignore_except": [5624, 5639]
}
}
The definition of error codes can be found at lints_codes.ml.
Each lint error can be suppressed separately with the help of HHAST_IGNORE_ERROR markers.
For example, suppose you are generating a file including some unnecessary null checks, which triggers the error code 5611, putting the HHAST_IGNORE_ERROR[5611] marker at the previous line of each lint error position could prevent HHAST from reporting it.
1
2
3
4
5
6
7
8
9
10
11
class Diagnosis {
public function __construct(shape('file' => string, 'position' => ?int, 'reason' => string) $data) {}
public function hasFile(): bool {
// HHAST_IGNORE_ERROR[5611]
return $this->data['file'] is nonnull;
}
public function getFile(): string {
return $this->data['file'];
}
}
HHAST_IGNORE_ALL is also supported for suppressing an error code in the whole file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// HHAST_IGNORE_ALL[5611] because this file is generated.
// It is expected to include some correct but unnecessary null checks.
class Diagnosis {
public function __construct(shape('file' => string, 'position' => ?int, 'reason' => string) $data) {}
public function hasFile(): bool {
return $this->data['file'] is nonnull;
}
public function getFile(): string {
return $this->data['file'];
}
public function hasPosition(): bool {
return $this->data['position'] is nonnull;
}
public function getPosition(): ?int {
return $this->data['position'];
}
public function hasReason(): bool {
return $this->data['reason'] is nonnull;
}
public function getReason(): string {
return $this->data['reason'];
}
}
HHAST_IGNORE_ALL is not encouraged because, unlike HHAST_IGNORE_ERROR, HHAST_IGNORE_ALL would silently skip newly introduced errors and you would miss the opportunity to review them.
HHAST v4.139.0 requires HHVM 4.126 or newer version. ↩
Bo Yang
Posted January 14, 2022
HHVM 4.144 is released! This release marks the end of support of 4.136; 4.137, 4.138, 4.139, 4.140, 4.143 remain supported, as do the 4.102 and 4.128 LTS releases. 4.141 and 4.142 were cancelled due to the holiday season.
hh_client --config type_printer_fuel=N option.classname<E> where E is an enum now supports dynamic.read_globals context without an enclosing readonly modifier.Fred Emmott
Posted January 06, 2022
HHVM 4.143 is released! This release marks the end of support of 4.135; 4.136–4.140 remain supported, as do the 4.102 and 4.128 LTS releases. 4.141 and 4.142 were cancelled due to the holiday season.
Additional patch releases have been made for 4.102, 4.128, and 4.135-4.140,
which change the typechecker to ignore any files in vendor/bin/; this is
required for compatibility with Composer 2.2.
readonly, extends, async, await, and
concurrent keywords.fb_intercept2() now supports functions that return readonly.<<__ConsistentConstruct>> but does not define
a constructor, all subclass constructors must now be pure ([]).
Alternatively, define a constructor on the interface or class to specify
different capabilities. In previous versions, this can be enabled with
the pure_default_consistent_constructors flag in .hhconfig.DateTimeInterface::getTimestamp() is now pure; any custom implementations
will need to also be pure.Fred Emmott
Posted December 17, 2021
HHVM 4.139.1 and HHVM 4.140.1 are released! These releases add support for a new
environment variable, HHVM_DISABLE_PERSONALITY, which disables use of the
personality() syscall on Linux.
Like HHVM_DISABLE_NUMA, this is required in some restricted environments, such
as Docker containers, and is now set in our Docker images for these
versions.
Bo Yang
Posted December 16, 2021
HHVM 4.140 is released! This release marks the end of support for 4.134; HHVM 4.135–4.139 remain supported, as do the 4.102 and 4.128 LTS releases.
v4.140 is the last release in 2021. Happy Holidays!
readonly data types.\preg_replace_callback() and \preg_replace_callback_with_error(). See this commit for the new signature.JitAHotSize and JitAProfSize runtime options are removedUNSAFE_CAST in lvalues and await operands. The following code does not type-check any more:
HH\FIXME\UNSAFE_CAST<mixed, dict<int, string>>($m)[0] = "lvalue";await HH\FIXME\UNSAFE_CAST<Awaitable<mixed>, Awaitable<int>>(foo());clone of a readonly object is also readonly.\preg_replace_callback() and \preg_replace_callback_with_error() now take a (function(darray<arraykey, string>)[_]: string) as the second parameter in the typechecker, instead of an untyped value.Fred Emmott
Posted December 09, 2021
HHVM 4.139 is released! This release marks the end of support for 4.133; HHVM 4.134–4.138 remain supported, as do the 4.102 and 4.128 LTS releases.
We expect to release 4.140 next week, but there will be no 4.141 release (week of the 20th), or 4.142 (week of the 27th). We plan to resume our usual schedule with 4.143 in the week of the 3rd of January, however we consider this release ‘at-risk’, depending on changes during the preceeding weeks.
readonly data types.async stub methods if the return type is Awaitable.json_decode() is now faster, and consumes less memory.globals or read_globals capabilties.globals capabilty.json_decode() is now stricter about the input it accepts (per JSON/ECMA-404):
\f is no longer considered a whitespace character.\r is now considered a whitespace character.Fred Emmott
Posted November 30, 2021
HHVM 4.138 is released! This release marks the end of support for 4.131; HHVM 4.133–4.137 remain supported (4.132 was cancelled), as do the 4.102 and 4.128 LTS releases.
This release primarily contains changes that are not easily observable, such as reliability improvements and preparation work for future changes.
/A modifier with non-zero offsets (regression fix)Fred Emmott
Posted November 23, 2021
HHVM 4.137 is released! HHVM 4.131–4.136 remain supported, as do the 4.102 and 4.128 LTS releases. HHVM 4.131 remains supported as the 4.132 release was cancelled.
hh_client --lint no longer suggests that reified generic parameters should be marked as covariant or contravariant, as this is not supported for reified generic.self with static when calling an abstract static method.is/as checks.Bo Yang
Posted November 19, 2021
HHVM 4.136 is released! HHVM 4.131–4.135 remain supported, as do the 4.102 and 4.128 LTS releases.
readonly feature is no longer considered unstable.
readonly modifier is now also visible to the reflection API via the isReadonly() or returnsReadonly() functions.controlled and no longer require the defaults capabilities.noreturn type now can be upcasted to dynamic.private final modifier are not supported any more. Use private instead.partial typing mode is removed. This includes both support for <?hh // partial in .php files, and for .hackpartial files.<<__ConsistentConstruct>> but does not declare an explicit constructor.Fred Emmott
Posted November 08, 2021
HHVM 4.135 is released! HHVM 4.130–4.134 remain supported, as do the 4.102 and 4.128 LTS releases.
This release primarily contains stability and performance improvements, and work towards future features that are not yet supported.
Fred Emmott
Posted November 01, 2021
HHVM 4.134 is released! HHVM 4.129–4.133 remain supported, as do the 4.102 and 4.128 LTS releases.
ext_curl will now cache TLS certificates between requests if HHVM is built against Curl v7.46.0 or newer.HH\Lib\Ref::get() and ::set($value) - direct property access is still supported.HH\Lib\Async\Poll::waitUntilEmptyAsync() for convenience and clarity when only the side effects of the
Awaitables are needed, such as when running an event loop.Fred Emmott
Posted October 26, 2021
HHVM 4.133 is released! HHVM 4.128–4.131 remain supported, as do the 4.102 and 4.128 LTS releases. HHVM 4.132 was skipped due to issues with the nightly builds.
dynamic values can now be used as container keys. The containers will then
be inferred to be keyed by arraykeys, so can not be used as
T<int, _> or T<string, _>.Str\format() accidentally using the request locale.hackfmt adding unwanted blank lines to the top of files.//
comments instead..php, .hack, .hackpartial, or .hhi extension will now
be consistently parsed as if they were .hack files.
.hck and .hh, as <?hh tokens
are banned in .hack files.parent::__construct() from a trait, unless the
parent has <<__ConsistentConstruct>>.parent::__construct()..php files remain deprecated, and support may be removed in a future
release; .hack is strongly recommended instead.hackpartial and .php files with <?hh // partial remain deprecated, and
support will likely be removed in a future release. .hack is strongly
recommended instead.Fred Emmott
Posted October 12, 2021
HHVM 4.131 is released! HHVM 4.126–4.130 remain supported, as do the 4.102 and 4.128 LTS releases.
AsyncMysqlConnectionPool::connectAndQuery().ReflectionTypeConstant::getTypeStructure() incorrectly referring to
the declaring class for inherited type constants, instead of the current class.
This could lead to bugs if the type constant referred to this.Str\replace functions introduced in 4.130Fred Emmott
Posted October 05, 2021
HHVM 4.130 is released! HHVM 4.124–4.129 remain supported, as do the 4.102 and 4.128 LTS releases.
Vulnerabilities have been found bypassing the intent of the
hhvm.server.whitelist_exec, hhvm.server.whitelist_exec_warning_only, and
hhvm.server.allowed_exec_cmds options when subprocesses are executed via
system() (and potentially similar APIs such as shell_exec() and proc_open())
with user-controlled input. Given that these builtins all execute subprocesses via
a shell, there is not a viable path to implement these in a trustable way, so
these options will be removed without replacement in a future release.
We recommend:
escapeshellarg() function may be useful here, but assumes a sh-style shell.inout parameters.hhvm.debugger.enable_debugger=1, even if using a different
debugger such as Visual Studio Code. We expect to remove this requirement in a future release.Locale\bytes() as a preferred alias for Locale\c(); we expect to remove Locale\c() in a future release.hh_client --lint can now suggest variance; for example: Lint[5639] This generic parameter could be marked covariant. Consider prefixing the generic parameter with + [1]
infer_variance.php:1:19
[1] 1 | interface IGetter<T> {
2 | public function get(): T;
3 | }
invariant() as inout.self and parent as types now results in a runtime error; this previously
raised typechecker errors. They remain valid for use in other contexts, e.g.
self::foo() and parent::__construct().array_map() is no longer special-cased in the typechecker; it now expects
a single callback, a single KeyedContainer, and returns a KeyedContainer.
It no longer accepts a variable number of parameters, and no longer preserves
the concrete type of the input.Str\ functions no longer respect the current thread locale; functions
that were locale-sensitive now have a _l() variant that takes an explicit
locale.
Str\format('%0.2f', 1.23) will now reliably return 1.23,
instead of sometimes returning 1,23 - if the previous behavior is desired,
Str\format_l(Locale\get_native(), '%0.2f', 1.23) can be used instead.Str\ functions could not be marked as pure, and because most users
were surprised that functions like Str\format(), sprintf() etc were
locale-aware._l functions support UTF-8, depending on the CTYPE in the locale; this
may lead to behavior differences. Please ensure that LC_CTYPE is set
correctly for the behavior you desire using Locale\modified().Str\split() now consistently throws if a negative limit was provided.
Str\split() would only throw for negative limits if the
delimiter was empty.Str\split('a!b!c', '!') returned vec['a', 'b', 'c']Str\split('a!b!c', '!', 2) returned vec['a', 'b!c']Str\split('a!b!c', '!', -1) instead returned vec['a', 'b']Legacy_FIXME\split_with_possibly_negative_limit() as a migration aid
with the old behavior.Str\replace_every() and related functions now consistently raises exceptions
for empty search strings, and for inputs that are not strings. Previous
behavior varied depending on the specific function and inputs.
Legacy_FIXME\coerce_possibly_invalid_str_replace_pairs() as a
migration aid.Str\ functions now raise InvalidArgumentException instead of invariant
violations for invalid arguments.hhvm.warn_on_implicit_coercion_of_enum_value flag is set to true, the
runtime will raise a warning. This affects is and as operators, and
EnumName::isValid().Fred Emmott
Posted September 28, 2021
HHVM 4.129 is released! This release marks the end of support for 4.123; HHVM 4.124–4.128 remain supported, as do the 4.102 and 4.128 LTS releases.
hackfmt --in-place (or -i) no longer writes to files that do not have
formatting changes.hackfmt --check-formatting which, given a list of files, prints
which files would be modified by hackfmt --in-place.hackfmt now correctly handles multi-line string literals.DateTimeZone::listIdentifiers() returning an empty set.UTC timezone not being recognized.isset() no longer permits inout arguments.RuntimeException and LogicException
now extend the new ExceptionWithPureGetMessage class; all descendents that
override getMessage() must mark it as pure, e.g. getMessage()[].Fred Emmott
Posted September 21, 2021
HHVM 4.128 is released! This release has long term support, so:
hackfmt -i (or --in-place) now accepts multiple filenames in one invocation.newctx now requires an as constraint.Fred Emmott
Posted September 16, 2021
HHVM 4.127 is released! This release marks the end of support for 4.121; HHVM 4.122–4.126 remain supported, as do the 4.80 and 4.102 LTS releases.
Str\foo_l() functions taking a Locale\Locale() object, and supporting
UTF8 (via Locale\create('en_US.UTF-8'), for example). We recommend only
using these functions when locale or multibyte-character awareness is
explicitly required, as:
_l functions are more performantStr\ends_with_l() call returns true when a string ends with the same
characters, but in a different byte sequence, potentially of a different
length.__FILE__ in trait methods.crypto_core_ristretto255_from_hash() and sodium_crypto_scalarmult_ristretto255() when
supported by system libsodium.sodium_crypto_secretstream family of functions.hackfmt.version = 0 in your .hhconfig..hhconfig flag disallow_partially_abstract_typeconst_definitions is
now true by default, and will be removed in a future release. This bans
declarations of the form const type T as Y = Z.foo()::$static_prop = 1 is now a runtime error, instead of only a
typechecker error.Fred Emmott
Posted September 07, 2021
HHVM 4.126 is released! This release marks the end of support for 4.120; HHVM 4.121–4.123 remain supported, as do the 4.80 and 4.102 LTS releases.
HHVM 4.125 was cancelled due to issues with the release candidate builds.
hh_client --lint FILE is now supported, including several type-aware linters. There is not currently any
configuration or suppression available; please join us in Slack to discuss
potential integration approaches.is/as checks will now invoke the autoloader if required instead of failing.HH\Lib\Locale namespace, providing:
Locale\create(string $locale)[]: Locale\LocaleLocale\modified(Locale\Locale $base, Locale\Category $cat, string $new): LocaleLocale\c()[]: Locale\Locale (likely to be renamed to Locale\bytes())Locale\get_native(): Locale\LocaleLocale\set_native(Locale\Locale $locale): voidLocale\from_environment(): Locale\LocaleThe new Locale\ functions are intended to be a replacement for the
setlocale() built-in, and to interoperate with future changes to the Str\
namespace.
We discourage changing the native locale in most cases (either with setlocale()
or with the new Locale\set_native()) as it can have unexpected results, such as
changing the output of Str\format(), or translating exception messages raised
by some builtins which should usually end up in logs that are read by
developers/administrators instead of users. We have included it to provide a
migration path for existing users of setlocale(), and because it is desirable
in some cases, especially CLI tools.
Str\ HSL functions will start throwing InvalidArgumentException instead of
InvariantException when invalid offsets or lengths are passed. We strongly
recommend against catching either of these exceptions.hhvm.throw_on_iteration_over_objects
INI setting. Set to 1 for a notice to be raised, or 2 for an error.Fred Emmott
Posted August 25, 2021
HHVM 4.124 is released! This release marks the end of support for 4.118; HHVM 4.120–4.123 remain supported (4.119 was skipped), as do the 4.80 and 4.102 LTS releases.
This release primarily contains improvements to implementation details, and preparatory work for future features/changes.
Str\ HSL functions will start throwing InvalidArgumentException instead of
InvariantException when invalid offsets or lengths are passed. We strongly
recommend against catching either of these exceptions.Fred Emmott
Posted August 17, 2021
HHVM 4.123 is released! This release marks the end of support for 4.117; HHVM 4.118–4.122 remain supported, as do the 4.80 and 4.102 LTS releases.
meth_caller() must now be constantsFred Emmott
Posted August 11, 2021
HHVM 4.122 is released! This release marks the end of support for 4.116; HHVM 4.117–4.121 remain supported, as do the 4.80 and 4.102 LTS releases.
== no longer converts types or warns by default; false is now returned.
For example, var_dump(1 == '1') prints bool(false).<) now throw in cases where they would previously
coerce types, such as 1 < '2'.hh_single_compile is no longer included in our packages. HackC is now
embedded in HHVM as a library. If you want to view the generated bytecode
(e.g. for debugging), use hhvm -d hhvm.dump_hhas=1 foo.hack.gettype() will no longer ever return array - vec, dict, or keyset
will be returned instead. If you need to distinguish
between arrays marked as legacy and other arrays, use
HH\\is_array_marked_legacy($x).curl_copy_handle and CurlPool due to thread safety issues. If
similar behavior is required, we recommend using CurlShareHandle instead.Fred Emmott
Posted August 02, 2021
HHVM 4.121 is released! This release marks the end of support for 4.115; HHVM 4.116–4.120 remain supported, as do the 4.80 and 4.102 LTS releases.
hhvm.notice_on_coerce_for_str_concat2 option to catch a
coercion case that is not handled by hhvm.notice_on_coerce_for_str_concat.
For both of these, a value of 0 means silent coercion, 1 raises a notice,
and 2 is an error.hhvm.notice_on_coerce_for_math and hhvm.notice_on_coerce_for_inc_dec INI
settings.hhvm.notice_on_coerce_for_cmp and
hhvm.notice_on_coerce_for_eq INI settings.hhvm.notice_on_coerce_for_bit_op INI setting.See 4.120’s announcement
for Legacy_FIXME functions to aid in type coercion migration.
Fred Emmott
Posted July 27, 2021
HHVM 4.120 is released! This release marks the end of support for 4.113 and 4.114; HHVM 4.115–4.118 remain supported, as do the 4.80 and 4.102 LTS releases. HHVM 4.119 was skipped due to personal circumstances of the team.
stringstream_select() and pagelet_server_task_result() will no longer be
inlined, so will appear correctly in profilers like Xenon.HH\\Lib\\Legacy_FIXME namespace, containing several functions emulating
PHP behavior that we intend to remove from the core language. New code should
never use these functions, and projects should aim to remove them over time.
Currently, these include:
Legacy_FIXME\\increment(mixed) and decrement(mixed): reimplements the
current coercion behavior of ++ and -- on null and string inputs;
the coerced value is returned, not mutated in place.Legacy_FIXME\\cast_for_arithmetic(mixed): match PHP’s implicit coercion
for math operations on null, bools, strings (int-like, float-like,
and neither), and resources.lt(mixed, mixed), lte(mixed, mixed), gt(mixed, mixed),
gte(mixed, mixed), cmp(mixed, mixed), eq(mixed, mixed(),
neq(mixed, mixed)optional_arraykey_to_int_cast_for_switch(?arraykey $value)[]: intoptional_num_to_int_cast_for_switch(?num $value)[]: intint_cast_for_switch(mixed $value, ?arraykey $first_truthy); the second
parameter is required when switching on an enum.string_cast_for_basic_switch(mixed $value, ?arraykey $first_case)These last few functions are intended to be used by replacing switch($foo)
with switch(Legacy_FIXME\\string_cast_for_basic_switch($foo)), for example.
X<bool> is invalid if X is defined as X<T as arraykey>Foo::bar<> could previously have been coerced to vec['Foo', 'bar'].
Exceptions are now raised for these conversions. On previous versions, this
can be configured with the hhvm.is_compatible_cls_meth_type,
hhvm.raise_cls_meth_conversion_warning,
hhvm.raise_cls_meth_comparison_warning,
and hhvm.is_compatible_cls_meth_type INI settings.++ and -- now raise notices when the types are coerced. Ideally, avoid
the coercion, otherwise migrate to the new Legacy_FIXME\\increment() and
Legacy_FIXME\\decrement() functions.fb_intercept() has been removed; use fb_intercept2()fb_intercept2() as it would not
reliably trigger, could recurse, and could crash HHVM.hphp_debugger_attached() always returns false in repo-authoritative mode, as
it could have performance implications, and is not reliable when attached in
repo-authoritative mode.Legacy_FIXME functions in a future release.Fred Emmott
Posted July 20, 2021
A security update has been released for all supported HHVM versions. Please update to one of the following versions to get the update:
4.80.6 and 4.102.3 are also released for Debian 10 Buster and Ubuntu 18.04 Bionic, updating build system compatibility with those platforms.
This security update addresses:
IOBuf classFred Emmott
Posted July 16, 2021
HHVM 4.118.1 is released! This release fixes an issue introduced in 4.118.0, leading to a segmentation fault when building a bytecode repository for repo-authoritative mode in some environments. Earlier releases are not affected.
Fred Emmott
Posted July 14, 2021
HHVM 4.118 is released! This release marks the end of support for 4.112; HHVM 4.113–4.117 remain supported, as do the 4.80 and 4.102 LTS releases.
ext_facts; when using the watchman-based autoloader, this
provides information about the declarations in the current repository.Stringish is now sealed to StringishObject and can not be directly
extended. Any class implementing __toString(): string automatically
implements the StringishObject interface.Ján
Posted July 07, 2021
HHVM 4.117 is released! This release marks the end of support for 4.111; HHVM 4.112–4.116 remain supported, as do the 4.80 and 4.102 LTS releases.
HH\FIXME\UNSAFE_CAST
can now be used as a slightly safer alternative to HH_FIXME comments.Stringish interface no longer declares a __toString() method. This
method is now declared only on the StringishObject interface (added in
HHVM 4.115).
__toString() on Stringish was misleading, since
string is a subtype of Stringish but trying to call any method on a
string value results in a runtime error.hhvm.raise_array_serialization_noticeshhvm.hack_arr_compat_intish_cast_noticeshhvm.hack_arr_compat_noticeshhvm.array_provenance== and !=, as well as
switch statements, will no longer treat values of different types as equal.
hhvm.notice_on_coerce_for_eq now supports a new value, 3.
This enables the new behavior, i.e. comparing values of different types will
return false. We recommend setting this option to 1 (raise notices) or
2 (throw exceptions) first to catch any comparisons that would be
affected.Ján
Posted June 28, 2021
HHVM 4.116 is released! This release marks the end of support for 4.110; HHVM 4.111–4.115 remain supported, as do the 4.80 and 4.102 LTS releases.
is and as operators with varray and
darray types. These types are equivalent to vec and dict since
HHVM 4.103.int or float now throws an exception
(previously it would raise a notice).is_array($value) check, the typechecker now more precisely refines
the type of $value. This may reveal some previously hidden errors.
.hhconfig option is_array=true can be
used to enable this behavior. This option was removed in HHVM 4.116.hhvm.hack_arr_compat_check_comparehhvm.hack_arr_compat_fb_serialize_hack_arrays_noticeshhvm.hack_arr_compat_is_vec_dict_noticeshhvm.hack_arr_compat_compact_serialize_noticeshhvm.hack_arr_compat_cast_marked_array_noticeshhvm.hack_arr_is_shape_tuple_noticeshhvm.hack_arr_dv_arrs== and != will no longer
treat values of different types as equal (similarly to their strict variants
=== and !==).
switch statements where the type of the switch
expression is different from any of the case expressions.hhvm.notice_on_coerce_for_eq=1 can
be used to raise a notice whenever values of different types are compared
using these operators (set to 2 to throw an exception).Ján
Posted June 21, 2021
HHVM 4.115 is released! This release marks the end of support for 4.109; HHVM 4.110–4.114 remain supported, as do the 4.80 and 4.102 LTS releases.
StringishObject, was added. It is a subtype of
Stringish
that does not include strings, only objects with a __toString() method.
Stringish, it is therefore always safe to call __toString() after
a ($value is StringishObject) check.Stringish, classes don’t have to explicitly specify that they
implement StringishObject. It is automatically added to all classes that
have a __toString() method.hhvm.repo.central.path and hhvm.repo.local.path were
replaced with a single option, hhvm.repo.path
(see documentation).
yield statements). This may reveal some previously hidden
errors.hhvm.trait_constant_interface_behavior=1 can be used to
enable the future behavior now.<<__Sealed(...)>> attribute
are actually existing subclasses/implementations of the annotated
class/interface.
.hhconfig option enable_sealed_subclasses=true
which can be used to enable the future behavior now.Ján
Posted June 14, 2021
HHVM 4.114 is released! This release marks the end of support for 4.108; HHVM 4.109–4.113 remain supported, as do the 4.80 and 4.102 LTS releases.
dynamic-typed
arguments to some
Hack Standard Library
functions.!) operator is used
on some comparisons of array-typed values
(e.g. !(vec[2,3,4] == vec[1,2,3])).<<__Sealed(...)>> attribute
are actually existing subclasses/implementations of the annotated
class/interface.
.hhconfig option to enable this behavior should become available in the
next release.Ján
Posted June 08, 2021
HHVM 4.113 is released! This release marks the end of support for 4.107; HHVM 4.108–4.112 remain supported, as do the 4.80 and 4.102 LTS releases.
arraykey and num-typed values. This may
reveal some previously undetected errors.hhvm.server.allow_duplicate_cookies was removed.If you are interested in HHVM, you’re welcome to join our Slack group.
This replaces our IRC channel, which has been inactive for a long time.
Ján
Posted June 02, 2021
HHVM 4.112 is released! This release marks the end of support for 4.106; HHVM 4.107–4.111 remain supported, as do the 4.80 and 4.102 LTS releases.
ReflectionTypeConstant::getTypeStructure() was added
(it had already been available in HHVM, but previously not recognized by the
typechecker).this (e.g. this::T) can now be used as reified generic
type parameters. Note that the type this itself is still not allowed as a
reified generic type parameter.echo and print are
used with arguments that are not int or string.newtype X<T as arraykey> = T;).
This may reveal some previously undetected errors.Ján
Posted May 25, 2021
HHVM 4.111 is released! This release marks the end of support for 4.105; HHVM 4.106–4.110 remain supported, as do the 4.80 and 4.102 LTS releases.
enable_abstract_context_constants = true).?-> operator is used on an
object of a non-nullable type (these calls are safe, even if unnecessary).Map is used with a key of an
invalid type (e.g. dynamic, null) that would previously only cause runtime
errors.$this->someMethod($this->uninitializedVar)Ján
Posted May 17, 2021
HHVM 4.110 is released! This release marks the end of support for 4.104; HHVM 4.105–4.109 remain supported, as do the 4.80 and 4.102 LTS releases.
setlocale() when called
with the special values "" or "0"
(#8834).
preg_last_error(), json_last_error(), and
json_last_error_msg() have been deleted. They have been deprecated since
HHVM 4.106. Instead, use
these alternatives:
<<__EntryPoint>> function has any
generic type parameters.keyset, dict, Set, or Map initializer has generic type
parameter(s), the typechecker now raises an error if the key type is not
arraykey or its subtype (int or string).
For example, $foo = keyset<bool>[]; is an error.keyset ($keyset[] = 'foo';), the typechecker now
correctly enforces that the appended value is an int or string.Map using an index
that is not an int or string. This had already been an error for other
collection types.Fred Emmott
Posted May 11, 2021
HHVM 4.109 is released! This release marks the end of support for 4.103; HHVM 4.104–4.108 remain supported, as do the 4.80 and 4.102 LTS releases.
exit()ext_facts, ext_watchman and the watchman-based native autoloader are now
included in builds by default, building and statically linking
libwatchmanclient if a dynamic version is not available in the build system.HH\enable_function_coverage() and HH\collect_function_coverage();
these are intended for calculating unit test coverage only, and only function
if repo-authoritative mode is not enabled, and the
hhvm.enable_func_coverage ini setting is 1.hhvm --check-repo; this can be used to verify that a
repo-authoritative repo was built with a compatible HHVM and with compatible
options. It may be useful as a debugging tool for CI/CD pipelines, but it is
not a necessary step.hhvm.notice_on_coerce_for_cmp option, raising notices for cases
where invalid comparisons are made between different types. This option does
not control cases where there were already dedicated options, such as implicit
__toString() calls.setlocale(), leading to observerable
changes; this affects both Hack code, and C/C++ extension code in HHVM, as
HHVM replaces the libc setlocale() with a request-aware version.
"C" by
setlocale(); previously, HHVM reported the empty string, leading to
differing behavior:
uselocale() would detect the "C" localesetlocale() would sometimes detect it as C,
sometimes manually infer it from the environment, or use it as some other
special locale, eg an invalid locale, or the ‘root’ locale in ICU.LC_ALL=en_US.UTF-8 is set,
setlocale(LC_ALL, '') will set the locale to en_US.UTF-8, and this will
be indicated when retrieving the locale via setlocale(). Previously:
uselocale() would use the locale from the environmentsetlocale() would not be able to distinguish this
state from the initial state"C" differs to
PHP, which defaults to using the environment locale.Built-in autoloading is now available, but depends on the Watchman daemon being installed on your system.
Both per-repository and per-process (or global) settings are required;
first, a
Watchman query
must be specified in REPO_ROOT/.hhvmconfig.hdf, e.g.:
Autoload {
Query = {"expression": ["allof", ["type", "f"], ["suffix", ["anyof", "hack", "php"]], ["not",["anyof",["dirname",".hg"],["dirname",".git"],["dirname",".svn"]]]]}
}
Additionally, the following options need to be specified on the command line or in a configuration file:
hhvm.autoload.enabled=truehhvm.autoload.db.path=foo/autoload-%{euid}-%{schema}.db%{euid} and %{schema} are template placeholders:
%{schema} is replaced with a hash which changes if your HHVM version, parser flags, or .hhvmconfig.hdf file changes. Changes to any of these factors might change the way autoloading works, and changing the hash ensures we’ll store autoloading data in a different DB.%{euid} is replaced with the effective UNIX user ID that HHVM’s running as. Different users on a host might be running HHVM. Including the UNIX EUID ensures that each UNIX user has a personal DB they can write to, avoiding permissions errors.Correct configuration can be verified by:
HH\Facts\enabled()class_exists() or function_exists() in your entrypoint
on a definition that requires autoloadingWhen using the built-in autoloader, it is not necessary to initialize
separate autoloaders such as the hhvm-autoload tool; for example,
it is not necessary to require('vendor/autoload.hack') or to call
Facebook\AutoloadMap\initialize().
We expect future versions of HHVM to:
Ján
Posted May 04, 2021
HHVM 4.108 is released! HHVM 4.103–4.107 remain supported, as do the 4.80 and 4.102 LTS releases.
as/super) on abstract
context constants
are now supported.meth_caller()
with a private or protected method (even within the same class hierarchy),
but these runtime errors are not detected by the Hack typechecker. A new
.hhconfig option, meth_caller_only_public_visibility = true, can be used
to raise Hack errors in these cases. However, the plan is to support private
and protected methods in meth_caller() in the future, at which point this
.hhconfig option will become unnecessary.Str\ namespace in the (now built-in) Hack Standard Library
will no longer respect the system/request locale. Instead, they will default
to using the
POSIX (also known as C) locale.
Fred Emmott
Posted April 29, 2021
HHVM 4.107 is released! This release marks the end of support for 4.101; HHVM 4.102–4.106 remain supported, as does the 4.80 LTS release.
disallow_partially_abstract_typeconst_definitions flag to be on by default
in a future release. This is different to the previous
disable_partially_abstact_typeconstants option, which disables the ability
to override them.expected T as string instead of just expected Tis nonnull the same as !== null; both already
had special cases in type refinement, but some were exclusive to !== null.php_version(), PHP_VERSION, PHP_VERSION_ID, PHP_MAJOR_VERSION and
related constants/functions will be removed, as they are misleading. If you
need to detect if specific PHP5-compatible behaviors are enabled, use
ini_get('hhvm.php7.foo'). The PHP5-compatible behaviors remain unsupported
and are disabled by default.# comments will be used; use // or /* comments instead. #! will still
be ignored if it is the first line of a file, i.e. a ‘shebang’ line, such as
#!/usr/bin/env hhvm. We expect to re-use the # token for new syntax in
a future release.David Snider
Posted April 22, 2021
tl/dr: we’re doubling down on removing surprising implicit (and some explicit) coercions from the language. So far we
Implicit coercions can be unintuitive in edge cases, and these edge cases can be surprisingly common - making them the second most confusing language feature, behind arrays. Even those working on the language often make mistakes, and they are frequently a source of subtle bugs.
For those who don’t know, an implicit coercion is when a value of type A gets converted to type B as part of computing the result of an operation. Probably the most common example is how 0 == false results in true courtesy of 0 being converted to false prior to the comparison, but things go straight downhill from there (hint: try comparing '0' with false and then '0' with null). We’ve determined that the time has finally come to tackle this once and for all.
Well, we’ve actually already started doing something about it! Very shortly, attempting to convert an object into a number will universally throw an exception. On top of this almost finished step, we have a few portions in flight, as well as a few more not started but still very much planned.
For the following, the possible stages are
These stages are ordered such that by a certain stage, all previous stages are implied.
. , .=) interpolationCurrent Behaviour: int, null, bool, float, and resource will implicitly coerce to string
1
'' . true; // '1'
Future Behaviour: only int will implicitly coerce. The rest will trigger exceptions Example:
1
2
'' . true; // `InvalidOperationException`
'one: ' . 1; // 'one: 1'
Status of rollout: Soft Runtime Enforcement
&, |, ^, ~, <<, >>) and assignment equivalentsCurrent Behaviour:
&, |, ^: null, bool, float, vec, dict, keyset, and resource will implicitly coerce to int. strings will implicitly coerce as well unless both operands are strings.
1
2
3
null & vec[]; // 0
keyset[1] & true; // 1
'abcd' & 'efgh'; // 'abc`'
~: floats will implicitly coerce to int
1
~1.2; // -2
<<, >>: null, bool, float, string, vec, dict, keyset, and resource will implicitly coerce to int
1
keyset[1] << true; // 2
Future Behaviour:
&, |, ^: no operations will coerce. Attempting to operate on a non-int (unless both operands are strings) will trigger an exception.
1
2
3
null & vec[]; // InvalidOperationException
keyset[1] & true; // InvalidOperationException
'abcd' & 'efgh'; // 'abc`' - https://3v4l.org/CTH2o
~: no operations will coerce. Attempting to operate on a non-int or string will trigger an exception.
1
~1.2; // InvalidOperationException
<<, >>: no operations will coerce. Attempting to operate on a non-int will trigger an exception.
1
keyset[1] << true; // InvalidOperationException
Status of rollout: Soft Runtime Enforcement
Current Behaviour: Incrementing null, decrementing an empty string, and inc/dec a “numeric” string will implicitly coerce to int.
1
2
3
4
5
6
$x = null; ++$x; // 1
$x = ''; --$x; // -1
$x = ''; ++$x; // '1'
$x = '1.123'; ++$x; // 2.123
$x = '1bananas'; ++$x; // '1bananat'
$x = 'abcd'; ++$x; // 'abce'
Future Behaviour: No operations will coerce. Additionally banning incrementing an empty string for consistency. The only valid values for inc/dec are ints, floats, and non-numeric strings. Note that while inc/dec a non-numeric string is still “legal,” it’s not necessarily a great idea.
1
2
3
4
5
6
$x = null; ++$x; // InvalidOperationException
$x = ''; --$x; // InvalidOperationException
$x = ''; ++$x; // InvalidOperationException
$x = '1.123'; ++$x; // InvalidOperationException
$x = '1bananas'; ++$x; // '1bananat'
$x = 'abcd'; ++$x; // 'abce'
Status of rollout: Soft Runtime Enforcement
+, -, *, /, %, **) and assignment equivalentsCurrent Behaviour: null, bool, string, and resource will coerce to int / float depending on the other operand (defaulting to int for two non-num operands)
1
null + true; // 1
Future Behaviour:
Operating on anything other than ints and floats will trigger an exception, with floats additionally being banned for use with %. It’s worth noting that we specifically decided to allow implicit coercions between ints and floats in this context.
1
null + true; // InvalidOperationException
Status of rollout: Soft Runtime Enforcement
< ,<=, > , >=, <=>)Current Behaviour: Attempting to list all the situations in which coercions happen and between which types would result in this post being twice as long. That should give you an idea of how much work this step will be.
1
2
3
4
5
null >= false; // true
false < new Foo(); // true
false < Foo::class; // true
true < Foo::class; // false
true > Foo::class; // false
Future Behaviour: Comparing values of two different types will throw an exception. A notable exception to this will be comparing ints and floats. In that case, comparison works as you’d expect, with the usual caveats about comparisons involving two approximately equal floats (including an approximately equal int and float).
1
2
3
4
5
null >= false; // InvalidOperationException
false < new Foo(); // InvalidOperationException
false < Foo::class; // InvalidOperationException
true < Foo::class; // InvalidOperationException
true > Foo::class; // InvalidOperationException
Status of rollout: Enforced By Type Checker
==, !=)Current Behaviour: All the same combinations of types trigger coercions as with the comparison operators, but with even more situations resulting in coercions.
1
2
3
4
null == false; // true
false == new Foo(); // false
false == Foo::class; // false
true == Foo::class; // true
Future Behaviour: There will be two steps to this, going through both Hard Runtime Enforcement and then New Behaviour. First, comparing values of two different types will throw an exception. Then, comparing values of two different types will simply be false.
1
2
3
4
null == false; // InvalidOperationException then false
false == new Foo(); // InvalidOperationException then false
false == Foo::class; // InvalidOperationException then false
true == Foo::class; // InvalidOperationException then false
Status of rollout: No Progress
This is may be a surprise to you, but switch statements utilize == under the hood and so result in all the same coercions. As such, refer to that section for current and future behaviour.
In addition to the above major operational line items, we continue to discover a long tail of more minor coercions that will necessarily be tackled by this work, including things such as indexing into strings with other strings.
After this change, == and === will be very similar semantically, with the only major remaining differences appearing when operating on arrays and objects. This could make it confusing which one should be used. As a follow up, we will evaluate potentially removing one of the operators.
Additionally, there are a handful of above operations that don’t trigger coercions but we consider dubious nonetheless. Examples of this include bitwise operations and inc/dec on strings. As a followup, we will consider what to do about these operations.
Ján
Posted April 20, 2021
HHVM 4.106 is released! This release marks the end of support for 4.100; HHVM 4.101–4.105 remain supported, as does the 4.80 LTS release.
json_last_error(), json_last_error_msg(), and
preg_last_error() are now deprecated and will be removed in a future
release. Instead, use these alternatives:
json_last_error(),
json_last_error_msg(), and preg_last_error() will be removed in a future
release.2 + '3') is changing from 4110 to 4429. This doesn’t introduce any
new errors, but may require HH_FIXMEs to be updated.
.hhconfig option math_new_code = true to enable the future
behavior now.Ján
Posted April 19, 2021
A security update has been released for all supported HHVM versions. Please update to one of the following versions to make sure you’re secure:
This security update addresses the following vulnerabilities:
mailparse_rfc822_parse_addresses()AsyncMysqlClient methods: connect(), connectAndQuery(), connectWithOpts()AsyncMysqlConnectionPool::connectWithOpts()mysql_connect_with_ssl()IntlCalendar methods: after(), before(), equals(), isEquivalentTo()IntlTimeZone::hasSameRules()XMLReader::expand()DOMDocument, DOMNode, DOMImplementation, DOMXPath methodsFred Emmott
Posted April 14, 2021
HHVM 4.105 is released! This release marks the end of support for 4.99; HHVM 4.100–4.104 remain supported, as does the 4.80 LTS release.
enum class featureClosure$func#num() instead of
__invoke()hh_server’s compression model can be changed to ZSTD by setting the
sharedmem_compression .hhconfig option to a ZSTD compression level; 3
is ZSTD’s default. This is essentially CPU vs memory tradeoff - large
projects may wish to experiment with this option.<<__ConstFun>> attribute.json_last_error(),
json_last_error_msg(), and preg_last_error()_with_error suffixed variants of all json/preg functions have been added and
should be used instead for error checking. e.g. json_encode() has
json_encode_with_error() and preg_match() has preg_match_with_error()Ján
Posted April 05, 2021
HHVM 4.104 is released! This release marks the end of support for 4.56 (LTS) and 4.98; HHVM 4.99–4.103 remain supported, as does the 4.80 LTS release.
Note that HHVM 4.104 is not a long-term support (LTS) release as originally scheduled. Instead, HHVM 4.102 was promoted to a LTS release.
Fred Emmott
Posted March 31, 2021
HHVM 4.103 is released! This release marks the end of support for 4.97; HHVM 4.98–4.101 remain supported, as do the 4.56, 4.80, and 4.102 LTS releases.
mixed or dynamic; for example, it is now possible to pass
() ==> { echo "hello"; } as a (function(): mixed)HH\EnumClassAttribute interface, allowing definition of user
attributes for enum classes.varray is now an alias for vecdarray is now an alias for dictdicts at runtime; this generally remains
considered an implementation detail, but will be helpful when handling
untyped data such as decoded JSON.vecs at runtime; this is also an considered
an implementation detail.apc_prime.so support has been removed; this was an undocumented feature that
would allow providing a C++ library to pre-fill APC on HHVM startup.hh_single_compile, however the parser and emitter are also
embedded, and we expect to remove the dependency on hh_single_compile and
potentially remove the executable in the future. The embedded compiler can be
tested with the hhvm.hack_compiler_use_compiler_pool=false INI setting.Ján
Posted March 29, 2021
HHVM 4.102 is the last release where varray and darray are treated as
distinct types from vec and dict. From HHVM 4.103 on, varray becomes an
alias for vec, and darray an alias for dict (in HHVM 4.101 and 4.102, the
INI option hhvm.hack_arr_dv_arrs=1 can be used to enable the new behavior).
To give users more time to migrate, we are promoting HHVM 4.102 to a long-term support (LTS) release. Similarly to other LTS releases, it will be supported until superseded by two regularly scheduled LTS releases. We expect these releases to be HHVM 4.128 and 4.152, in which case, 4.102 will be supported for ~ 50 weeks.
This replaces the regularly scheduled LTS release, HHVM 4.104, which will likely
be a standard release (supported for 6 weeks). However, we might add one more
unscheduled LTS release between HHVM 4.102 and 4.128 if it makes the migration
from varray/darray to vec/dict easier.
Ján
Posted March 23, 2021
HHVM 4.102 is released! This release marks the end of support for 4.96; HHVM 4.97–4.101 remain supported, as do the 4.56 and 4.80 LTS releases.
<<__Override>> is now correctly enforced on methods declared
on interfaces (previously it was only enforced on methods declared in
classes and traits). The typechecker will raise an error if the attribute is
used on an interface method that was not declared on
any of your interface’s parent interfaces.protected method declared
in a trait is called from an invalid context. Previously, there was a bug
where the typechecker would allow calling the protected method from any
class that used the same trait, even if it wasn’t a child or parent of the
target class. Such calls would cause a runtime error but previously wouldn’t
be caught by the typechecker.+, -, *, /, %, **) with values of non-numeric types (all types
except int and float) will cause an exception to be thrown at runtime. All
of these cases already raise typechecker errors.
+=, **=, etc.).hhvm.notice_on_coerce_for_math=2 can be used to enable
the future behavior now (set to 1 to raise a notice instead of throwing
an exception).$i++, --$i). The INI option
hhvm.notice_on_coerce_for_inc_dec can be used to enable the future
behavior for these (set to 1 for notice, 2 for exception).Fred Emmott
Posted March 16, 2021
HHVM 4.101 is released! This release marks the end of support for 4.95; HHVM 4.96–4.100 remain supported, as do the 4.56 and 4.80 LTS releases.
$0splice0switch($x) is exhaustive for enum classes,
not just for normal enums; the runtime continues to require that either a
case matches, or there is a default case.array_slice() no longer converts int-like string keys to intsvarray an alias for
vec, and darray an alias for dict; varray and darray will no longer
be distinct types to Hack arrays. This will also affect the runtime
implementation of shapes and tuples, which are currently implemented with
darrays and varrays respectively. You can test this behavior now with the
hhvm.hack_arr_dv_arrs=1 ini setting.Ján
Posted March 09, 2021
HHVM 4.100 is released! This release marks the end of support for 4.94; HHVM 4.95–4.99 remain supported, as do the 4.56 and 4.80 LTS releases.
switch statements
are exhaustive (this has been enforced at runtime since HHVM 4.80), i.e. that
at least one branch of the switch statement is guaranteed to be executed
(or an exception is thrown).
switch statement, allowing some
previously rejected programs to pass.<<__Pure>> and all related attributes
(__AtMostRxAsArgs, __AtMostRxAsFunc, __Cipp, __CippGlobal,
__CippLocal, __MaybeMutable, __Mutable, __MutableReturn, __NonRx,
__OnlyRxIfImpl, __OwnedMutable, __ReturnsVoidToRx)
were removed. They have been replaced by
contexts and capabilities.is and as operators
are used with the type
nothing
($x is nothing, $x as nothing).&, |, ^: both operands must be int or both string~ (unary): operand must not be double<<, >>: both operands must be int&=, <<=, etc.).hhvm.notice_on_coerce_for_bit_op=2 can be used to enable
the future behavior now (set to 1 to raise a notice instead of throwing
an exception).Ján
Posted March 02, 2021
HHVM 4.99 is released! This release marks the end of support for 4.93; HHVM 4.94–4.98 remain supported, as do the 4.56 and 4.80 LTS releases.
Exception, Error, Throwable no longer have their
methods marked as <<__Pure>>. This means that exceptions can no longer be
thrown from other <<__Pure>> functions.
meth_caller to change from
__SystemLib\MethCallerHelper to a native
function reference
type. This shouldn’t affect normal usage, but may affect edge cases like
serialization. Notably, the new values cannot be stored in APC.
hhvm.emit_meth_caller_func_pointers=true can be used to
switch to the new format now.hhvm.forbid_meth_caller_apc_serialize=1 can be
used to raise a warning when values in the old format are stored in APC,
without switching to the new format. Setting it to 2 will throw an
exception instead of the warning.<<__Pure>> will be removed in a future release. It
has been replaced by
contexts and capabilities.Ján
Posted February 25, 2021
A security update has been released for all supported HHVM versions. Please update to one of the following versions to make sure you’re secure:
This security update addresses the following vulnerabilities:
exif_read_data()substr_compare()crypt()preg_quote()exif_read_data()Ján
Posted February 22, 2021
HHVM 4.98 is released! This release marks the end of support for 4.92; HHVM 4.93–4.97 remain supported, as do the 4.56 and 4.80 LTS releases.
inst_meth to be removed in a future release
(anonymous functions
or meth_caller
can be used instead).
.hhconfig flag disallow_inst_meth=true and the INI option
hhvm.hack.lang.disallow_inst_meth=true can be used to enforce the future
behavior now.'hello '.$name) and interpolation
("hello $name") to become restricted to string and int values in the
future.
hhvm.notice_on_coerce_for_str_concat which can be used to raise a notice
(if set to 1) or throw an InvalidOperationException (if set to 2) when
concatenating/interpolating other types, in addition to the typechecker flag
added in last week’s release.Ján
Posted February 16, 2021
HHVM 4.97 is released! This release marks the end of support for 4.91; HHVM 4.92–4.96 remain supported, as do the 4.56 and 4.80 LTS releases.
ReflectionFunction::getCoeffects and ReflectionMethod::getCoeffects).hackfmt formatting of function calls that have is/as
expressions as arguments.<<__Rx>> and related built-in attributes (__RxShallow, __RxLocal) were
removed. Use
contexts and capabilities
instead.ReflectionClass::isFinal
will return false if the ReflectionClass represents an enum). This is due
to upcoming features,
enum classes and
enum inclusion.
<<__Sealed>>
can be used to add restrictions to specific enums.meth_caller
with a method that has any
inout parameters.
It had already been a runtime error, but previously wouldn’t be caught by the
typechecker.'hello '.$name) and interpolation
("hello $name") to become restricted to string and int values in the
future. These two types were chosen because they’re the only types with an
unambiguous string representation (compared to e.g. a bool value which
could be represented as “0”, “false”, or currently “”; similarly for null;
and float values can have arbitrary precision as well as special cases like
NaN).
.hhconfig option enable_strict_string_concat_interp=true can be used
to enable the future behavior now.Ján
Posted February 10, 2021
HHVM 4.96 is released! This release marks the end of support for 4.88; HHVM 4.91–4.95 remain supported, as do the 4.56 and 4.80 LTS releases.
(Note: HHVM 4.89 and 4.90 were skipped.)
mixed or dynamic
(examples).assert and assert_options were removed. Using them
had already been a typechecker error, but previously wouldn’t fail at runtime.+, *, etc.) on an array now throws an
InvalidOperationException (which can be caught) instead of a fatal error.hhvm.forbid_dynamic_calls_to_meth_caller was renamed to
hhvm.dynamic_meth_caller_level.
1) or
throw (2) when dynamic_meth_caller is called on a static method or a
method not marked as <<__DynamicallyCallable>>.meth_caller with arguments that are not string/::class literals will
become a fatal error at runtime (it is already a typechecker error).
hhvm.hack.lang.disallow_dynamic_meth_caller_args.dynamic_meth_caller can be used with non-literal arguments, but it can
only invoke methods annotated with <<__DynamicallyCallable>> (currently
might not be enforced based on the value of
hhvm.dynamic_meth_caller_level, as described above).Ján
Posted February 01, 2021
HHVM 4.95 is released! This release marks the end of support for 4.87; HHVM 4.88–4.94 remain supported, as do the 4.56 and 4.80 LTS releases.
(Note: HHVM 4.89 and 4.90 were skipped.)
proxy_ssl_cert_path, proxy_ssl_key_path, proxy_ssl_ca_bundle).debug_backtrace() now returns arguments (the 'args'
key in the returned array) in a vec (previously varray).DateTime
methods (matching what these methods already returned). This may reveal
previously hidden typechecker errors.dynamic_meth_caller(string $cls_name, string $meth_name)
that should be used to call instance (non-static) methods dynamically.Fred Emmott
Posted January 25, 2021
HHVM 4.94 is released! This release marks the end of support for 4.86; HHVM 4.87–4.93 remain supported, as do the 4.56 and 4.80 LTS releases.
Additionally, 4.88.1, 4.91.1, 4.92.1, and 4.93.1 have been released, fixing a segmentation fault on machines with less than 8GB of RAM.
(Note: HHVM 4.89 and 4.90 were skipped.)
debug_zval_dump() incorrectly reporting a refcount of 1 for
uncounted or static values; these are now explicitly marked as uncounted or
static.meth_caller().print_r, var_dump, and = in hphpd.Ján
Posted January 19, 2021
HHVM 4.93 is released! This release marks the end of support for 4.84; HHVM 4.86–4.92 remain supported, as do the 4.56 and 4.80 LTS releases.
(Note: HHVM 4.85, 4.89 and 4.90 were skipped.)
hhconfig flags enable_coeffects_syntax, call_coeffects, local_coeffects, and the INI option hhvm.hack.lang.enable_coeffects can be
used to enabled this feature in recent HHVM versions, or to disable this
feature in HHVM 4.93.UndefinedPropertyException at runtime (previously only a notice). It had
already been a typechecker error.Fred Emmott
Posted January 12, 2021
HHVM 4.92 is released! This release marks the end of support for 4.83; HHVM 4.84–4.91 remain supported, as do the 4.56 and 4.80 LTS releases.
(Note: HHVM 4.85, 4.89 and 4.90 were skipped.)
require extends, it
is now able to call its’ own private methods on instances of B.nonnull was technically accurate (as
mixed is ?nonnull), some users misinterpreted the error as meaning that
null was expected, or still consider mixed values to be mixed after a
null check.APCIterator class has been removed from the runtime, as it has generally
not been kept up to date or correct, and was not exposed to the typechecker.apc_cache_info() now correctly returns an uncounted_entries key instead of
uncounted_entires.dynamic values requires that all values are coercible to
dynamic, and the return type will be dynamic.async without an
Awaitable return type; previously this was separately checked by the type
checker and the bytecode emitter, and the typechecker did not detect invalid
async lambdas.Ján
Posted January 05, 2021
HHVM 4.91 is released! This release marks the end of support for 4.82; HHVM 4.83–4.88 remain supported, as do the 4.56 and 4.80 LTS releases.
(Note: HHVM 4.85, 4.89 and 4.90 were skipped.)
getNames() is called on an enum with duplicate
values.hackfmt now ignores non-Hack files instead of printing unhelpful error
messages.curl_setopt() now allows passing in keys and certificates as strings if HHVM
is built with libcurl >= 7.71.0. New options:
ReflectionClass methods.number_format and json_decode could allocate large
amounts of memory before checking the configured request memory limit.string to int would behave inconsistently for
strings containing the minimum int value with trailing whitespace
("-9223372036854775808 ").hhvm.forbid_division_by_zero was removed. Division by zero
now always raises an exception (this had already been the default behavior).hhvm.error_handling.no_infinite_recursion_detection was
removed. Comparing objects with cyclical references now always raises an
error (this had already been the default behavior).Fred Emmott
Posted December 15, 2020
HHVM 4.88 is released! HHVM 4.82–4.87 remain supported, as do the 4.56 and 4.80 LTS releases.
We intend to skip 4.89 and 4.90 due to the holiday season; support for 4.82 and 4.83 will be extended until the release of 4.91 and 4.92 respectively.
try/catch around require() (e.g. to attempt
to find an autoloader), HH\could_include() is a useful replacement.Ján
Posted December 07, 2020
HHVM 4.87 is released! HHVM 4.81–4.86 remain supported, as do the 4.56 and 4.80 LTS releases.
apc_add and apc_store now take a 4th, optional
argument. If this argument is provided, then the value stored in APC will be
evicted if it’s not accessed for the specified number of seconds (even if the
TTL specified in the previous argument hasn’t been reached yet)..hhconfig option disallow_goto was removed—it is no longer
possible to enable goto statements. It had been true by default in all
recent HHVM versions.arraykey value (not int or string)
now causes an InvalidArgumentException to be thrown at runtime. String
indexes like '42' stay supported for historical reasons, but generally
shouldn’t be used. Using any non-int value, including strings, had
already been a typechecker error.ArrayIterator and all the collections’ iterators (VectorIterator,
MapIterator, etc.) are deprecated. Most use cases can be replaced by
foreach loops, which HHVM can also optimize in the JIT. For the remaining
cases, the
current implementation
can be replicated in pure Hack code.
Ján
Posted November 30, 2020
HHVM 4.86 is released! This release marks the end of support for 4.79; HHVM 4.80–4.84 remain supported (4.85 was skipped), as does the 4.56 LTS release.
\preg_last_error may now return a new value,
\PREG_BAD_REGEX_ERROR. Various \preg_... functions use this error code
when called with an invalid regular expression (previously, they would return
false without setting an error code).async function is declared with a non-Awaitable return type, the
typechecker now raises an error at the position of the return type
(previously, it would raise an error at the position of the function name).
This doesn’t introduce any new errors but may require some HH_FIXMEs to be
moved.<<__DynamicallyCallable>> attribute.\HH\dynamic_fun($function_name) or
\HH\dynamic_class_meth($class_name, $method_name) (a way to dynamically
call non-static methods is in the works).hhvm.forbid_dynamic_calls_to_func,
hhvm.forbid_dynamic_calls_to_cls_meth and/or
hhvm.forbid_dynamic_calls_to_inst_meth to:
0 – Do nothing1 – Warn if target is not annotated2 – Throw exception if target is not annotated; warn if dynamic
callsite is using a raw string or array3 – Throw exceptionFred Emmott
Posted November 17, 2020
HHVM 4.84 is released! This release marks the end of support for 4.78; HHVM 4.79–4.82 remain supported, as does the 4.56 LTS release. This primarily contains internal improvements for performance, maintainability, and preparation for future work.
We will not be releasing 4.85 next week due to US holidays; we expect the next release to be 4.86, during the week of 2020-11-30.
class B<T> extends A<T> when A’s
T parameter is reified, but B’s is not.arraykey will throw an
InvalidArgumentException; currently, it emits a
String offset cast occurred notice.Ján
Posted November 12, 2020
A security update has been released for all supported HHVM versions. Please update to one of the following versions to make sure you’re secure:
This security update addresses the following vulnerabilities:
dump-static-strings
(CVE-2019-3555)
and dump-pcre-cache
(CVE-2019-3556)
admin endpoints can write to any file the webserver has access tocrypt()light-process.cpp not dropping privileges correctlygdImageCreate()XMLReader::expand()ldap_escape()
(CVE-2020-1916)Ján
Posted November 10, 2020
HHVM 4.83 is released! This release marks the end of support for 4.77; HHVM 4.78–4.82 remain supported, as does the 4.56 LTS release.
\HH\LambdaAttribute.hhvm.hack.lang.enable_first_class_function_pointers was removed.
The new
function reference
syntax is now always enabled.hhvm.emit_cls_meth_pointers is now enabled by default. It causes
the built-in function class_meth() to return values in the same format as
the new function reference syntax, which should make migrating easier.
hhvm.is_compatible_cls_meth_type = 1 can be used to
allow both formats to be considered valid.fun() and class_meth() will be removed in a future
release. Use the new
function reference
syntax instead.
hhvm.hack.lang.disallow_fun_and_cls_meth_pseudo_funcs = 1
and .hhconfig option disallow_fun_and_cls_meth_pseudo_funcs = true can
be used to disable these functions in the current HHVM release.Fred Emmott
Posted November 03, 2020
HHVM 4.82 is released! This release marks the end of support for 4.76; HHVM 4.77–4.81 remain supported, as does the 4.56 LTS release.
AsyncMysqlQueryResults has the new method
dictRowsTyped(): vec<dict<string, arraykey>>.array_fill_keys() will now throw an InvalidArgumentException if the first
argument is not a Container; in previous versions,
HHVM would return false. With this change, array_fill_keys() now only
returns darrays.Ján
Posted October 27, 2020
HHVM 4.81 is released! This release marks the end of support for 4.75; HHVM 4.76–4.80 remain supported, as does the 4.56 LTS release.
AnyArray was added, representing the parent type of all
containers that are values (vec, dict, keyset, varray, darray;
does not include containers with reference semantics like Vector). It is
a subtype of KeyedContainer.hhvm.hack_arr_dv_arr_var_dump was removed. var_dump will
now always output varray or darray instead of array.var_dump, var_export will also start distinguishing between
varray and darray.
hhvm.hack_arr_dv_arr_var_export=1 to enable this
behavior now.# comments will be removed in a future release.
Use // or /* instead.
Fred Emmott
Posted October 21, 2020
HHVM 4.80 is released! This release has long term support, so:
mixed; prior versions can
refer to the null or nonnull subtypes of mixed, which are more specific,
but can be confusing.touch; in prior versions,
this leads to immediately exiting earlier, however the metadata should be
updated to reflect the new modification time.__LSB or __MemoizeLSB attributes
are used in a final class. If this is raised, fix by removing the __LSB
attribute, and replacing __MemoizeLSB with __Memoize.for loop conditions no longer permit comma-separated expressions. In prior
versions, the behavior could be surprising - for example, in
for(;foo(), bar();) {}, the return value of foo() is ignored. Commas are
still permitted in other positions other positions, e.g.
for ($i = 0, $j = 0; some_func($i, $j); ++$i, $++j).1 (warn) to 2 (error), and we then expect to remove the options entirely.
Attempting to recover from these errors may lead to additional irrecoverable
errors.
hhvm.enforce_generics_ubhhvm.check_prop_type_hintsJán
Posted October 13, 2020
HHVM 4.79 is released! This release marks the end of support for 4.73; HHVM 4.74–4.78 remain supported, as do the 4.32 and 4.56 LTS releases.
fun('foo') becomes foo<>class_meth(Foo::class, 'bar') becomes Foo::bar<>$obj->Foo() instead of $obj->foo()). The typechecker had already been
raising errors in all such cases. In the future, we expect these notices to
become runtime errors.
hhvm.raise_on_case_insensitive_lookup_v2=falsenew self(...) or new parent(...) is
used inside a class with
reified
generic type parameters.dynamic-typed
value where an
enforceable
reified generic type is expected.fun and class_meth will be removed in a future HHVM
release, in favor of the new function reference syntax.Fred Emmott
Posted October 06, 2020
HHVM 4.78 is released! This release marks the end of support for 4.72; HHVM 4.73–4.77 remain supported, as do the 4.32 and 4.56 LTS releases.
(class|function|interface|trait)_exists functions are now more optimized
in repo-authoritative mode. This takes advantage of the fact that all HHBBC
definitions are now unique and persistent.(string) casts.var_dump() now distinguishes between varrays and darrays by default,
instead of reporting both as array.is shape(...) requires a darray, and is tuple(...) requires a varray;
is checks with reified generics are now consistent with this when the
generic is a shape or tuple. Previously, reified generics were more
permissive.require() and related functions no longer support URIs,
e.g. file://foo.hack.array has been removed from the parser. It is now
parsed as a name token, like user-defined types.array_fill_keys() will require that $keys is a
Container<Tk as arraykey>; this will allow specifying a
darray<Tk, Tv> return type. Currently, it will return null if $keys
is not a Container.Ján
Posted September 28, 2020
HHVM 4.77 is released! This release marks the end of support for 4.71; HHVM 4.72–4.76 remain supported, as do the 4.32 and 4.56 LTS releases.
xbox_task_*
functions). Removed built-in functions:
xbox_send_messagexbox_post_messagexbox_get_thread_timeoutxbox_set_thread_timeoutxbox_schedule_thread_resetxbox_get_thread_timeshape key if its type is an opaque
type alias (a newtype not from the same file). This makes it more consistent
with how opaque type aliases can be used in other contexts.Ján
Posted September 23, 2020
HHVM 4.76 is released! This release marks the end of support for 4.69; HHVM 4.71–4.75 remain supported (4.70 was skipped), as do the 4.32 and 4.56 LTS releases.
try/catch/finally blocks
(examples). This allows some programs to typecheck
that previously would have failed.$GLOBALS was removed. Global variables can still be accessed using the
following functions:
$this. In almost all cases, it had already been banned by both the
typechecker and the runtime, but there were some remaining edge cases:
catch (Exception $this)inout $this as an argumentunset($this)?enum {...} is no longer a valid XHP attribute type. Use enum {...}
instead, which is equivalent (XHP attributes are nullable unless declared as
@required).$$ (special variable inside a
pipe expression)
as an inout argument now raises a fatal error at runtime. It had already
been a typechecker error.Ján
Posted September 14, 2020
HHVM 4.75 is released! This release marks the end of support for 4.68; HHVM 4.69–4.74 remain supported, as do the 4.32 and 4.56 LTS releases.
FORCE_ERROR_COLOR can be used to force hh_client
to output color escape sequences even if the output is not a terminal, e.g. to
save the output into a file that can be printed to a compatible terminal
later.is_array() is now equivalent to HH\is_any_array() (previously equivalent
to HH\is_php_array()). We expect this to be the last step before
is_array() is removed completely (it had already been removed
from the typechecker since HHVM 4.71, but for now is still available at
runtime), so please migrate to HH\is_any_array() (preserving the new
behavior), HH\is_php_array() (preserving the old behavior), or another of
the alternatives listed in
HHVM 4.71
release notes.call_user_func() and call_user_func_array() were
deprecated. Using them raises a typechecker error, but for now still works at
runtime (we expect runtime support to also be removed soon).
$callable() instead, where $callable is an
anonymous function, or the return value from
fun(),
class_meth(),
inst_meth() or
meth_caller().
All of these are understood by the typechecker, so the change may reveal
previously hidden errors.string as $callable raises a typechecker error, but for now
still works at runtime. However, we expect it to stop working soon, as the
native “function pointer” types returned by the functions above will become
the only valid representations of functions and methods.hhvm.emit_func_pointers has been removed, fun() now always
returns a native “function pointer” type instead of a string.
hhvm.emit_cls_meth_pointers and other related flags are also expected to
be removed soon.string key (instead of int) to
index into a varray changed from OutOfBoundsException to
InvalidArgumentException.
hhvm.hack_arr_compat_notices INI option can
be used to raise a notice (in addition to the OutOfBoundsException) in
these cases.> and >= operators on varrays to be consistent
with vecs. This only affects rare cases such as comparing arrays of objects
or NAN values.
is_array() will be removed completely.strings or tuples to represent functions and methods will
be removed in a future release. They are being replaced by a native “function
pointer” type.
fun() or another option listed above guarantees that the return
value will be compatible with the specific HHVM version being used, no
matter which type it uses to represent functions.Fred Emmott
Posted September 08, 2020
HHVM 4.74 is released! This release marks the end of support for 4.67; HHVM 4.68–4.73 remain supported, as do the 4.32 and 4.56 LTS releases.
where constraints are well-formed;
method generic constraints (e.g. public function foo<T as Bar>()) were
already verified in this way.Ján
Posted September 02, 2020
HHVM 4.73 is released! This release marks the end of support for 4.66; HHVM 4.67–4.72 remain supported, as do the 4.32 and 4.56 LTS releases.
hh_client
error formatter.class :foo to xhp class foo.xhp class foo now
declares a class named foo, not xhp_foo. This can cause new naming
conflicts, and can also cause issues anywhere the old mangled class names
are passed around as strings.- is no longer allowed inside XHP class names.: is now a namespace separator, class foo:bar declares a class
named bar in the foo sub-namespace of the current namespace
(namespace\foo\bar).category %foo, %bar syntax is no longer supported.children (...) syntax is not supported by xhp-lib v4, we recommend
disabling it in the typechecker by adding
disable_xhp_children_declarations=true to .hhconfig.current(), key(), reset() and end() were
removed. This continues the
previously announced
removal of arrays’ built-in “internal iterators”.\HH\global_keys() now raises a typechecker
error. It had already been removed from the runtime, but was incorrectly still
accepted by the typechecker.abstract final class is now
a typechecker error. It had already been a runtime error.hhvm.dynamic_invoke_functions has been removed. This option
allowed specifying a list of functions that could be used with fb_intercept
or fb_rename_function in repo-authoritative mode. It’s no longer possible to
control this per-function, but it can still be controlled globally using
hhvm.jit_enable_rename_function.hhvm.use_repo_autoload_map has been removed (preserving
default true). The built-in autoload map is now always used in
repo-authoritative mode.Fred Emmott
Posted September 02, 2020
Today we are releasing significant changes to XHP - in Hack, HHVM, and in the class/function library; XHP now fully supports namespaces - both using XHP from other namespaces, and defining XHP components in namespaces.
XHP v4 includes several changes to:
We expect future development of XHP to be focused on making XHP more consistent with the rest of Hack, especially from a type system perspective.
xhp class foo {} instead of class :foo: token acts as a namespace separator; foo:bar is
equivalent to foo\bar (and namespace\foo\bar), and :foo:bar is
equivalent to \foo\bar.renderAsync() replaces asyncRender() and render()1
2
3
4
5
6
7
8
class :foo:bar extends :x:element {
category %flow;
children (:div, :code*);
protected function render(): void {
return <x:frag>{$this->getChildren());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
namespace foo;
use namespace Facebook\XHP\Core as x;
use namespace Facebook\XHP\ChildValidation as XHPChild;
use type Facebook\XHP\HTML\{div, code};
xhp class bar extends x\element
implements \Facebook\XHP\HTML\Category\Flow {
use XHPChild\Validation;
protected static function getChildrenDeclaration(): XHPChild\Constraint {
return XHPChild\any_of(
XHPChild\of_type<div>(),
XHPChild\at_least_one_of(XHPChild\of_type<code>()),
);
}
protected async function renderAsync(): Awaitable<XHPRoot> {
return <x:frag>{$this->getChildren()}</x:frag>;
// alternatively:
return
<:Facebook:XHP:Core:frag>
{$this->getChildren()}
</:Facebook:XHP:Core:frag>;
}
}
Automated migrations for all language changes, and for most classes and functions renamed in xhp-lib v4, are available in HHAST 4.64.6 or newer (some also available in older HHAST versions).
hhast-migrate --add-xhp-children-declaration-method adds
the ChildValidation trait and getChildrenDeclaration() method based on
existing children declarations.hhast-migrate --remove-xhp-child-declarations (run after the above
migration) will remove the now redundant children declarations.hhast-migrate --demangle-xhp-class-names replaces - in XHP class names
with _hhast-migrate --xhp-class-modifier migrates class :foo:bar
to xhp class foo:barhhast-migrate --xhp-lib-v3-to-v4 migrates most class and function names
changed in xhp-lib v4, adds the necessary use clauses (this includes all
HTML tags)In rare cases, these migrations can result in typechecker errors (e.g. naming
conflicts due to the removal of XHP class name mangling) or hhast-lint errors
(e.g. redundant use clauses) which need to be fixed manually.
Additional changes that may require manual migration:
xhp class foo:bar:baz { ... } to the equivalent
namespace foo\bar; xhp class baz { ... } based on your preferred style.category declarations with interfaces (new or existing; common ones
can be found in the Facebook\XHP\HTML\Category namespace).$xhp->toString() need to be updated to $xhp->toStringAsync().$xhp->getChildren(...), $xhp->getFirstChild(...) and other
methods that had their argument removed need to be updated to
$xhp->getChildrenOfType<...>(), $xhp->getFirstChildOfType<...>(), etc.forceAttribute) are not
handled by the automated migrations, we recommend replacing them with
equivalent or similar non-deprecated features.A more formal description of these changes is also available.
Previously, XHP classes were declared with a leading colon, e.g.
class :foo:bar {}
XHP classes are now declared with the following syntax:
namespace foo;
xhp class bar {}
This new syntax avoids ambiguities that would otherwise be introduced by the addition of namespace support.
xhp class foo:bar {} is also permitted - it is intended to be used:
Previously, XHP class names were ‘mangled’ into a form that meets the usual restrictions for Hack class names; for example, class :foo:bar-baz {} actually defined the class xhp_foo__bar_baz.
XHP class names are no longer mangled: xhp class foo defines the class foo, and xhp class foo:bar defines the class foo\bar; this may cause problems if you are storing or otherwise interacting with classname<T> of XHP classes, or storing serialized instances of XHP classes.
This also means that XHP class names must now be valid Hack XHP class names; the most significant effect is that the - character is no longer permitted in XHP class names.
Colons are now a namespace separator (largely equivalent to \), but are only permitted in some contexts:
xhp class foo:bar, <foo:bar>function foo(:bar:baz $_) is permitted, but function foo(bar:baz $_) is not permitted\ is not permitted in XHP constructor calls (e.g. <foo\bar> is an error), or XHP class declaration names (e.g. xhp class foo\bar). It is permitted in parent class references, e.g. xhp class foo extends bar\baz {}.
Like \, : can be used to indicate that a name is fully qualified; for example, foo\bar and foo:bar both refer to namespace\foo\bar (unless there is a relevant use statement), and \foo\bar and :foo:bar both always refer to \foo\bar. Similarly, <foo:bar /> is a reference to namespace\foo\bar, and <:foo:bar /> is now permitted as a reference to \foo\bar.
There are several situations where both \ and : are permitted; we recommend that codebases decide on a consistent style; for example, code bases may wish to ban:
: for anything that is not an XHP class\ in XHP-specific contextsnamespace foo { xhp class bar {} }, but ban xhp class foo:bar {})The category %foo, %bar syntax is no longer supported - we recommend using interfaces instead.
They were largely equivalent to interfaces, but without typechecker support; this both increased complexity, and users reasonably assume there was typechecker support.
The children (...) syntax is no longer supported; XHP-Lib v4 supports a variant of the approach introduced in v3.1, however functions have been renamed to lower_camel_case for consistency with other common Hack libraries.
There is now a clean separation between core APIs and HTML-specific APIs; we hope this will lead to more diverse uses of XHP in the future.
Core XHP classes and functions are now in the Facebook\XHP\Core namespace; child validation has been moved to Facebook\XHP\ChildValidation, and is no longer considered a core feature.
This also includes core elements and base classes; in particular:
:x:composable-element is now Facebook\XHP\Core\node:x:element is now Facebook\XHP\Core\element, and :x:frag is now Facebook\XHP\Core\fragThese are now all in the Facebook\XHP\HTML namespace; they can be used:
<:facebook:xhp:html:div>use type, e.g. use type Facebook\XHP\HTML\{code, div}; $_ = <div />use namespace, e.g. use namespace Facebook\XHP\HTML as h; $_ = <h:div />Additionally:
Facebook\XHP\HTML\Category namespaceHasXHPAttributeClobbering_DEPRECATED has been removed; use attribute splat insteadUnsafeAttributeValue has been renamed to UnsafeAttributeValue_DEPRECATED as it bypassing the type system by design, and will need to be removed in a future releaseforceAttribute() has been renamed to forceAttribute_DEPRECATED() as it bypassing the type system by design, and will need to be removed in a future releaseasyncRender() has been renamed to renderAsync(), for consistency with other popular Hack projects and the HSLrender() has been removed; always use renderAsync() instead.XHPRoot interface and :xhp classes have been removed as unnecessary; use Facebook\XHP\Core\Node or XHPChild instead.getFirstChild() and related functions; added getFirstChildOfType<T as XHPChild>() with improved typechecker support. An interface can be specified to replace previous category specifications.It has been a very long path to get here, and much more involved than we expected. I’d like to thank our friends at Slack - especially Johan Oskarsson - who made this possible, and also Lexidor Digital whose contributions to type safety are greatly appreciated.
Fred Emmott
Posted August 26, 2020
HHVM 4.72 is released! This release marks the end of support for 4.65; HHVM 4.66–4.71 remain supported, as do the 4.32 and 4.56 LTS releases.
varray and darray runtime errors (e.g. out of bounds access) now
have clearer error messages, and are consistent with the equivalent vec/
dict error messages.hhvm.hack_arr_compat_notices is enabled, a notice is now raised when
a varray is indexed by a string.?int $myPropertyName) instead of the
placeholder ?YourTypeHere.<<__Override>> attributes were not checked on abstract classes; this bug
has now been fixed, so type errors will now be raised if a method on an
abstract class is marked with this attribute, but it is in fact not overriding
a parent definition.class_meth(), fun(), meth_caller()
etc to create a reference to functions or methods with reified generics, as
any call to such a reference is an error.class_meth(__CLASS__) in non-final classes is now a typechecker error. This
can be resolved by:
static::class or self::class.Unstable features are likely to be completely rewritten, restricted to builtins, or removed entirely, and any issues will generally be considered very low priority.
Experimental features can be enabled by:
allow_unstable_features=true to /etc/hh.conf or
/usr/local/etc/hh.conf (location may vary depending on your platform and
package source).hhvm.hack.lang.allow_unstable_features=true to your HHVM
configurationFor example:
1
2
3
4
5
6
7
8
9
<<file:__EnableUnstableFeatures('union_intersection_type_hints')>>
function use_unstable_feature((int | bool) $x): int {
if ($x is bool) {
return $x ? 1 : 0;
} else {
return $x as int;
}
}
Experimental features should not be used in production code.
Ján
Posted August 18, 2020
HHVM 4.71 is released! This release marks the end of support for 4.64; HHVM 4.65–4.69 remain supported, as do the 4.32 and 4.56 LTS releases.
hh_client has been significantly improved, with better
color highlighting, error messages shown in a better order, smarter handling
of overlapping positions, added surrounding lines of code, and other
improvements.
hh_client --error-format ... can be used to switch between the different
output formats.is_array() was removed from the typechecker and will
soon be removed completely. Instead, use one of the following:
HH\is_php_array() accepts only legacy arrays (varray, darray). This is
equivalent to is_array(), so it guarantees no change in behavior, but
makes it harder to migrate from legacy arrays to Hack arrays in the future.HH\is_any_array() accepts legacy array types (varray, darray) as well as
Hack arrays (vec, dict, keyset). This makes any future migration from legacy
arrays to Hack arrays safer, but it is not equivalent to is_array(), so
the change may need some manual review and testing.HH\is_vec_or_varray() and HH\is_dict_or_darray() allow you to test for
vec/dict-like behavior, while still making it safe to migrate from legacy
arrays to Hack arrays in the future.$var is Container<_> or
$var is KeyedContainer<_, _>..php extension starting
with <?php instead of <?hh). The typechecker ignores them (making it
possible for Hack and PHP code to live in the same repository), while the
runtime and some other commands (e.g. hh_parse) will raise errors when
trying to process them.
<?hh // struct)
even when the --disable-modes flag is used.class A<T> {}, function test(A ...$a): void {}). This may reveal previously undetected errors.isset would return an incorrect value when used with dict
or keyset elements (isset($dict['key'])).is_array() function will also be removed from the runtime (currently, it
has only been removed from the typechecker).Ján
Posted August 13, 2020
We have decided to skip this week’s regular release, HHVM 4.70.
There’s been a regression that prevented us from publishing the release earlier this week, which we are still working on fixing. Instead of shipping the release only a few days before the next one, we decided to skip it.
Support for HHVM 4.64 will be extended until the release of HHVM 4.71, scheduled for next week.
Fred Emmott
Posted August 05, 2020
HHVM 4.69 is released! This release marks the end of support for 4.62; HHVM 4.64–4.68 remain supported, as do the 4.32 and 4.56 LTS releases.
class Foo implements IBar<string>, IBar<int> {}, only IBar<string> would
be properly enforced.hhvm.check_return_type_hints runtime option has been removed.IntlIterator.fun() now returns a distinct type, not a string; this will not pass string
typehints. For now, string variables are still invocable, but this will change,
and is highly discouraged.Ján
Posted July 30, 2020
HHVM 4.68 is released! This release marks the end of support for 4.61; HHVM 4.62–4.67 remain supported, as do the 4.32 and 4.56 LTS releases.
array type has been completely removed from HHVM. All arrays are now
either varray or darray, which are treated as separate incompatible types
by both the typechecker and the runtime.
array
values that are neither varray or darray from Hack code, but some
built-in functions could still return them. These have all been migrated to
return varray or darray now.varray_or_darray with either one or two generic parameters can be
used to migrate code that needs to accept/return both types of arrays.
However, using Container or KeyedContainer is usually preferable for
any code that is intended to work with multiple array-like types.array type annotations to varray_or_darray is guaranteed to be
safe in HHVM 4.68. In previous HHVM versions, it is safer to use
<<__Soft>> varray_or_darray, as it is possible to have array values that
are neither varray nor darray, depending on the exact INI options.array type annotations to varray and darray (or even vec
and dict) might be preferable, but it may cause runtime errors, possibly
undetected by the typechecker (for values coming from untyped code including
some built-ins). You can use <<__Soft>> to turn these errors into
warnings.array type annotations are available in
HHAST v4.64.4.each, next, prev were removed. Any other
built-ins that use arrays’ “internal iterator” (current, key, reset,
end) will also be removed soon.
ArrayIterator other than current, key, next,
rewind, validAppendIteratorCachingIteratorCallbackFilterIteratorLimitIteratorMultipleIteratorParentIteratorRecursiveArrayIteratorRecursiveCachingIteratorRecursiveCallbackFilterIteratorRecursiveTreeIteratorSplFixedArraySplObjectStorage+ or += operators now throws an
exception. It had already been a typechecker error.
hhvm.hack_arr_compat_notices=true and
hhvm.hack_arr_compat_check_array_plus=true to raise a notice.HH_FIXMEs to be moved.meth_caller with a trait now raises a typechecker error. Runtime
behavior hasn’t changed, HHVM currently allows constructing such meth_caller
but throws an exception when the method call is invoked.switch statements where none
of the cases matched the provided value. In the future, this will be changed
to throw an exception.
default branch should be added to any switch statements that
intentionally don’t cover all possible cases.hhvm.throw_on_non_exhaustive_switch=0 to temporarily
disable this warning, or hhvm.throw_on_non_exhaustive_switch=2 to enable
the future behavior now (throw an exception).hhvm.php7.engine_exceptions is set
to false. If this option is true (default), return type violations throw
a TypeError which can be caught, but it is never possible to continue
execution in the same scope.hhvm.check_return_type_hints
can be used to temporarily reduce this to a recoverable error or a warning,
but this option will be removed in the future.hhvm.check_prop_type_hints
can be used to temporarily disable the warning or to enable the future
behavior now.TFoo as FooBaseClass), when used
as function parameter or return types, will now raise a warning if the upper
bound is violated. This had already been a typechecker error, but previously
ignored at runtime.
TFoo is an instance of some subclass of FooBaseClass, but
can’t enforce that it matches the exact type of TFoo in the given context,
as generic types are erased at runtime.hhvm.enforce_generics_ub=0 to temporarily disable this
warning, or hhvm.enforce_generics_ub=2 to enable the future behavior now
(throw an exception).hhvm.forbid_thrift_integer_values_out_of_range (used by the
Thrift extension) has been removed.each, next, prev) or will be removed soon
(current, key, reset, end).
foreach loops,
and would be much faster to boot. For cases that can’t be converted this
way, you can use Vec\keys($array) to get an array of keys and
vec($array) to get an array of values and use a for loop over indices
for these two arrays.hhvm.throw_on_non_exhaustive_switchhhvm.check_return_type_hintshhvm.check_prop_type_hintshhvm.enforce_generics_ubFred Emmott
Posted July 20, 2020
HHVM 4.67 is released! This release marks the end of support for 4.60; HHVM 4.61–4.66 remain supported, as do the 4.32 and 4.56 LTS releases.
varray or darray as appropriate,
instead of just array.(array) casts are now disabled in the runtime.Ján
Posted July 13, 2020
HHVM 4.66 is released! This release marks the end of support for 4.59; HHVM 4.60–4.65 remain supported, as do the 4.32 and 4.56 LTS releases.
HH\is_any_array() now refines the type of its argument to KeyedContainer.
This doesn’t change what programs are accepted by the typechecker, but
results in clearer error messages for those that aren’t.vec, dict, keyset, varray, darray) to string
now throws an exception at runtime. It had already been a typechecker error.hhvm.hack_arr_compat_notices=1 and
hhvm.hack_arr_compat_check_array_key_cast=1.strtr(), when called with a darray that contains
int-like keys, to silently ignore them (strtr('123', darray['2' => 'x'])
now correctly returns '1x3'). The behavior is now consistent with dict,
which wasn’t affected by this bug.<<__EntryPoint>>
functions in a file. It had already been a runtime error.trait Foo<Ta, Tb as Ta> with use Foo<string, int>). This may reveal
previously undetected errors.array(...)) are going away. In a
previous release, we eliminated the Hack syntax for these arrays, but some
builtins (e.g. array_intersect_key() and many other array builtins) could
still produce them. We will change these builtins to return darray instead.
<, <=, >, >=);
darrays throw on comparison.hhvm.hack_arr_compat_notices and
hhvm.hack_arr_compat_check_compare and look for the following two
notices:
ReflectionFunction or ReflectionMethod may currently throw. In the
future, it will only raise a warning (making reflection safer to use).
hhvm.fix_default_arg_reflection=2 to enable the future
behavior now.class_meth with an abstract function will be a runtime
error. Currently, this is only a runtime error if the method is actually
called.
hhvm.emit_cls_meth_pointers=1 and
hhvm.is_compatible_cls_meth_type=1 to enable this behavior now.var_dump() will start differentiating between varrays and
darrays.
hhvm.hack_arr_dv_arr_var_dump=1 to enable this
behavior now.Fred Emmott
Posted July 06, 2020
HHVM 4.65 is released! This release marks the end of support for 4.58; HHVM 4.59–4.64 remain supported, as do the 4.32 and 4.56 LTS releases.
is and as checks for reified enums now only check the underlying type,
not the values; this makes them consistent with parameter and return type
enforcement._with_error() variants of preg functions, e.g.
preg_grep_with_error(), preg_match_with_error(),
preg_replace_with_error(), to avoid the need for preg_last_error() calls
and the global state that entails.HH\is_vec_or_varray() and HH\is_dict_or_darray() functions.extend each other - for
example, a class can not extend an interface, but it can implement one.array() literals are no longer supported by the parser; [] literals were
already banned. Replace with darray[] or varray[]. On older versions of
HHVM, hhast-migrate --php-arrays can be used to automate this.HH\global_get('GLOBALS')
now returns null. Fetch specific known keys instead.
$GLOBALS['foo'] (i.e. with a key) is still supported, however migrating to
HH\global_get('foo') is encouraged.__Memoize; this
was previously a runtime error.yield from has been removed; the
release notes for 4.64
contain suggestions for migrating.(array) casts will be a parse error; they are currently a typechecker error.
A runtime error can be enabled now with the new
hhvm.hack.lang.disable_array_cast INI setting.Ján
Posted June 30, 2020
A security update has been released for all supported HHVM versions. Please update to one of the following versions to make sure you’re secure:
This security update addresses the following vulnerabilities:
hhvm.admin_server.password could be revealed by functions like
ini_get(), ini_get_all(), phpinfo()fb_unserialize(), fb_compact_unserialize()unserialize() if type code ‘S’ is used
maliciouslyunserialize() when unserializing an object with
dynamic propertiesJán
Posted June 30, 2020
HHVM 4.64 is released! This release marks the end of support for 4.57; HHVM 4.58–4.62 remain supported (4.63 was skipped), as do the 4.32 and 4.56 LTS releases.
hhvm.hack_arr_compat_specialization was removed and its
behavior is now enabled by default.
This change disables the implicit interoperability between varrays and
darrays. Instead, array (soon to be removed), varray and darray are
now treated as types in their own right. Specifically:
varray where a darray is expected (at parameter and return value
typehints) throws, and vice versa. The same goes for property typehints,
if they are checked at runtime.varrays now maintain a “vec-like” layout, with integer keys from 0 to
(size - 1). Attempting to set a string key in a varray throws, as does
attempting to unset any element other than the last one.varrays and darrays,
respectively. As a
result, darray is tuple(...) returns false and darray as tuple(...)
throws. The same goes for varray is shape(...) and
varray as shape(...).varray and a darray using == or === always returns
false.darray with a varray, or two darrays using >, <, <=,
>=, <>, <=> results in an exception. Two varrays can still be
compared.varray, darray and array. For
example, a child class will not be able to redeclare a property with type
varray<Tv> if the parent class’ property is typed darray<Tk, Tv>.hhvm.hack_arr_compat_type_hint_noticeshhvm.hack_arr_compat_check_varray_promotehhvm.hack_arr_compat_check_implicit_varray_appendhhvm.hack_arr_compat_dv_cmp_noticesHH\global_keys() was removed. Other methods of enumerating all
global variables, such as HH\global_get('GLOBALS') or $GLOBALS['GLOBALS'],
are also expected to stop working soon.array(...) literals to be completely removed in the next release.
All code will need to be migrated to varray[...] and darray[...], or
preferably vec[...] and dict[...] (if it can be done safely).
hhast-migrate --php-arraysHH\global_get('GLOBALS') or $GLOBALS['GLOBALS'], are expected to stop
working in a future release.yield from syntax in a future release. In most
cases, it can be replaced by other syntax.yield fromHere’s a list of replacements to use based on the complexity of the use case:
If only the values, or only (key, value) pairs, are used, replace yield from
with foreach...yield:
1
2
3
4
5
6
7
8
9
10
11
12
13
function only_values_old($gen) {
yield from $gen;
}
function only_values_new($gen) {
foreach ($gen as $v) { yield $v; }
}
function keys_values_old($gen) {
yield from $gen;
}
function keys_values_new($gen) {
foreach ($gen as $k => $v) { yield $k => $v; }
}
Use getReturn to evaluate the result of the yield from expression:
1
2
3
4
5
6
7
8
9
function return_old($gen) {
$x = yield from $gen;
var_dump($x);
}
function return_new($gen) {
foreach ($gen as $v) { yield $v; }
$x = $gen->getReturn();
var_dump($x);
}
Use send to pass values back into the inner generator (if callers of the
yield from outer generator do so). This use case is quite rare.
1
2
3
4
5
6
7
8
function send_old($gen) {
yield from $gen;
}
function send_new($gen) {
for ($gen->next(); $gen->valid(); $gen->send($s)) {
$s = yield $gen->key() => $gen->current();
}
}
There’s one behavior of yield from syntax that can’t be captured easily by
rewrites like the above: if the same generator is aliased by a yield from and
elsewhere, next() on that generator will advance the yield from. Such code
will need a rewrite to make state explicit.
Ján
Posted June 24, 2020
We have decided to skip this week’s regular release, HHVM 4.63.
There have been some bugs that prevented us from publishing the release earlier this week. Instead of shipping the release only a few days before the next one, we decided to skip it.
Support for HHVM 4.57 will be extended until the release of HHVM 4.64, scheduled for next week.
We expect next week’s HHVM 4.64 to contain some significant changes affecting legacy (PHP-style) arrays.
array(...) literals to be completely removed in the next release.
All code will need to be migrated to varray[...] and darray[...], or
preferably vec[...] and dict[...] (if it can be done safely).
hhast-migrate --php-arrayshhvm.hack_arr_compat_specialization will be removed and its
behavior will be enabled by default. We highly recommend enabling this flag in
your current HHVM release before upgrading to HHVM 4.64.
This change disables the implicit interoperability between varrays and
darrays. Instead, varray and darray will be treated
as types in their own right. Specifically:
varray where a darray is expected (at parameter and return value
typehints) will throw, and vice versa. The same goes for property typehints,
if they are checked at runtime.varrays will now maintain a “vec-like” layout, with integer keys from 0 to
(size - 1). Attempting to set a string key in a varray will throw, as will
attempting to unset any element other than the last one.varrays and darrays,
respectively. As a
result, darray is tuple(...) will return false and darray as tuple(...)
will throw. The same goes for varray is shape(...) and
varray as shape(...).varray and a darray using == or === will always return
false.varrays to darrays relationally with <, <=,
>, or >= will result in an exception.Fred Emmott
Posted June 16, 2020
HHVM 4.62 is released! HHVM 4.57–4.61 remain supported, as do the 4.32 and 4.56 LTS releases.
json_encode_with_error() and json_decode_with_error(), which take
a new inout ?(int, string) $error parameter as their second argument,
instead of mutating global state (which would be retrievable via
json_last_error()).inout errors.FIXME codes must now be whitelisted in the top-level project’s
.hhconfig - adding a FIXME for a code that is not in the whitelist is in
itself an error. The relevant configuration options are:
allowed_fixme_codes_partial=1234,5678: FIXME codes that are permitted in
.hackpartial files.allowed_fixme_codes_strict=1234,5678: FIXME codes that are permitted in
all other files, including .hack files and .php files starting with
<?hh - including <?hh // partial. We still recommend moving to .hack
and .hackpartial files, and expect support for // partial to be removed
in a future release.allowed_decl_fixme_codes=1234,5678: FIXME codes that are permitted in
declaration contexts, such as function type signatures. Any codes here must
also be listed in the _strict or _partial options to be permitted in
those files; this is to allow banning a code from strict files, while still
permitting it in decl contexts in partial files.For example, the HSL is configured with:
1
2
allowed_decl_fixme_codes=2053,4045
allowed_fixme_codes_strict=2011,2049,2050,2053,4027,4045,4106,4108,4110,4128,4135,4188,4200,4240,4248,4297,4323
A script is available to generate these configuration options; this script requires jq version 1.6 or newer.
This change is intended to allow projects to control what kinds of unsafe operations they are comfortable permitting, and to avoid accidentally regressions and introducing new forms.
Empty strict/partial whitelists are likely not a practical goal for the majority
of projects at this time, however, there is significant benefit in entirely
eliminating fixmes in declaration contexts, so we recommend that all projects
attempt to have an empty allowed_decl_fixme_codes whitelist.
Ján
Posted June 08, 2020
HHVM 4.61 is released! This release marks the end of support for 4.55; HHVM 4.56–4.60 remain supported, as does the 4.32 LTS release.
array_unshift on a keyset could cause the keyset
to contain multiple identical values.HH_IGNORE_ERROR may be removed in the future, making HH_FIXME
the only way to silence typechecker errors.
disable_hh_ignore_error=true to your .hhconfig to get this
behavior now.Fred Emmott
Posted June 01, 2020
HHVM 4.60 is released! This release marks the end of support for 4.54; HHVM 4.55–4.59 remain supported, as does the 4.32 LTS release.
hh_parse --pretty-print-jsonShapes::idx() now permits null as the first argument, for consistency
with idx().function test<reifiy T as arraykey>() : void { T::foo(); }Removed Exception::setPreviousChain(); using this was already a type error
as it was not in the HHI files.Ján
Posted May 26, 2020
HHVM 4.59 is released! This release marks the end of support for 4.53; HHVM 4.54–4.58 remain supported, as does the 4.32 LTS release.
hh_client to more accurately describe the status of the
server in various cases.<<Attr('arg1', 'arg2')>>) are not literal values. These had already been
runtime errors.
.hhconfig option stronger_shape_idx_return has been removed. This was
an experimental option that was never enabled by default, so this change
should not affect most users.where constraint on a constructor isn’t satisfied at the point of using
new, the typechecker would previously raise an error pointing to the
constructor definition. Instead, it now points to the use (the new
construct).
HH_FIXMEs to be moved.Fred Emmott
Posted May 19, 2020
HHVM 4.58 is released! This release marks the end of support for 4.52; HHVM 4.53–4.57 remain supported, as does the 4.32 LTS release.
.hackpartial files, to replace <?hh // partial; like .hack files,
these must not contain a header line. See ‘future changes’ for upcoming
breaking changes related to partial files.proc_open when using
LightProcess, especially when STDIN was not specified, or other low-numbers
FDs were specified.@ (e.g. @int $foo) has been disabled;
use <<__Soft>> int $foo instead.$f = static function() { return 1;}) has been disabled
as they were never safely typechecked.goto is now a parse error; it has never been supported in Hack code.$foo[] += $bar is now a typechecker error.<<__EntryPoint>> functions to take arguments.__Override on a standalone function (i.e. not a
method).<?hh // partial will be removed; use .hackpartial files
instead..hackpartial files. We strongly recommend
migrating any remaining partial code in 2020.Ján
Posted May 11, 2020
HHVM 4.57 is released! This release marks the end of support for 4.51; HHVM 4.52–4.56 remain supported, as does the 4.32 LTS release.
Shapes::idx()
now accepts a nullable first argument (consistently with
idx()).__call
is now a parser error. It had already been a typechecker error, but now it is
also a fatal error at runtime.FormatString in the root namespace
(\FormatString). Use
\HH\Lib\Str\SprintfFormat
(compatible with \HH\Lib\Str\format()) or \HH\FormatString (compatible
with sprintf()) instead.dynamic
value could cause the typechecker to report an error with primary position in
a different file. This doesn’t introduce any new errors but may require some
HH_FIXMEs to be moved.fun(),
class_meth(),
or
inst_meth())
may change.
HH_FIXME to squelch the typechecker error.hhvm.enable_func_string_interop=0 can be used to test the
new behavior now.Fred Emmott
Posted May 04, 2020
HHVM 4.56 is released! This release has long term support, so:
Additionally, 4.56 is the last release with support for several older Linux distributions and MacOS versions. In particular, we expect this to be the last release with support for Ubuntu 16.04 (Xenial), Debian 8 (Jessie), and Debian 9 (Stretch). See ‘Future Changes’ below for details.
apc_fetch() expiration is now deferred until the end of the first request
that sees an expired result; this request will return false, but any
concurrent requests will see the old value until the first request has
finished. This change aims to reduce ‘thundering herd’ problems when many
requests simultaneously attempt to refresh a hot key.\HH\INCORRECT_TYPE<T> has been removed from the HHI definitions.__get, __set, __isset, and __unset has been removed from
HHVM and the parser. Builtin classes that used these with fixed property names
have a new native implementation.As announced in November, we are changing our distribution support lifecycle, starting with nightly builds and the next release:
As long as dependencies are available from official upstream repositories, we
plan to package x.y.z releases for any Linux distributions where we packaged
x.y.0; we also aim to do this for MacOS as long as the versions are available
from our build infrastructure provider.
Concretely, this means that we no longer commit to supporting:
We will generally keep building packages for distributions we no longer support as long as they keep working and they do not hold back development. That said, starting with 4.57, we are immediately ending support for distributions that include GCC6 or below:
Other unsupported distributions may be removed from future releases without further notice.
Ján
Posted April 30, 2020
A security update has been released for all supported HHVM versions. Please update to one of the following versions to make sure you’re secure:
This security update addresses the following vulnerabilities:
The following were originally reported as PHP vulnerabilities, but HHVM is also affected:
exif_read_data()socket_sendto()sodium_crypto_generichash_init()
leaks data from uninitialized memoryJán
Posted April 29, 2020
HHVM 4.55 is released! This release marks the end of support for 4.49; HHVM 4.50–4.54 remain supported, as do the 4.8 and 4.32 LTS releases.
vec, dict, keyset) to true, false, and null
with the “fuzzy” equality operators (==, !=) now considers non-empty Hack arrays == true, and empty Hack arrays == false and == null.
hhvm.hack_arr_empty_based_bool_eq_cmp=true can be used to enable this
behavior.nothing. As before, any number/types of arguments are allowed (due to nothing being Hack’s bottom
type), but previously ignored nonsensical arguments like 1 + 'foo' are now rejected.%s placeholder in printf() now expects an ?arraykey argument instead
of mixed.
Str\format() is unchanged, it has always expected a string argument..hhconfig options now treat the value 2 (as well as any other
value except 1/true/yes/on) as false. Previously, the behavior was
not consistent across all boolean options, sometimes all positive numbers
were treated as true.
2 as a valid
value, but later became boolean options (a somewhat common pattern).Fred Emmott
Posted April 21, 2020
HHVM 4.54 is released! This release marks the end of support for 4.48; HHVM 4.49–4.53 remain supported, as do the 4.8 and 4.32 LTS releases.
inout parameters on async functions now only raise a parse error, instead
of a parse error and a NastCheck error.concurrent
blocksignored_fixme_codes (errors that can not be suppresed) hack option is
no longer respected for HHI files; this allows projects to use a stricter
list than is compatible with builtins.hhvm.check_cli_client_commands=2 INI setting to raise an error instead:
these warnings indicate a bug in HHVM, and can not be safely recovered from.
If you see this warning, please file a bug report. It can also be set to 0
to disable the warnings. Any value other than 2 leads to undefined behavior
in this error case.idx() and array access on empty containers.arraykeys; this
behavior can be enabled on old releases with the
disallow_invalid_arraykey=true .hhconfig setting.hhvm.check_cli_client_commands INI setting will default to 2 (error)
in a future release.Ján
Posted April 13, 2020
HHVM 4.53 is released! This release marks the end of support for 4.47; HHVM 4.48–4.52 remain supported, as do the 4.8 and 4.32 LTS releases.
?> can no longer be used to terminate // comments (?> for all other
purposes was removed in HHVM 4.52)Fred Emmott
Posted April 07, 2020
HHVM 4.52 is released! This release marks the end of support for 4.46; HHVM 4.47–4.51 remain supported, as do the 4.8 and 4.32 LTS releases.
HHVM 4.52.1 fixes a regression introduced in 4.52.0, which made the typechecker report Hack parse errors in PHP code, instead of ignoring actual PHP source files.
ext_soap if a SoapServer’s handler class does not exist.?> and <?= are no longer recognized by the parser; this has replaced
dedicated errors with parse errors.use the same trait twice in the same class; using
the same trait in related classes (e.g. subclasses and parents) is still
permitted.__toString will be
removed shortly; this includes (string) $obj, print($obj),
sprintf('%s', $obj) among others. The
hhvm.notice_on_implicit_invoke_to_string INI setting can be used to find
calls that will break.Ján
Posted March 31, 2020
HHVM 4.51 is released! This release marks the end of support for 4.45; HHVM 4.46–4.50 remain supported, as do the 4.8 and 4.32 LTS releases.
getEnumUnderlyingType() was added to ReflectionClass. It
returns the underlying type of the enum’s values (usually HH\int or
HH\string, but can also be the name of another enum, type alias, or
HH\arraykey).
ReflectionClass instance doesn’t represent an enum, the method
throws.return await ...) can
significantly improve performance of code that uses a lot of such calls.[] on a Map object
($map[] = Pair {$key, $value};) is now a type-checker error.
$map[$key] = $value; instead.HH_FIXME can be used
temporarily, to help migrating code. Runtime support will likely be removed
in a future release.__call,
so calling any method that is not explicitly declared is now a type-checker
error.
HH_FIXME can be used temporarily, to
help migrating code. Runtime support will likely be removed in a future
release.Fred Emmott
Posted March 24, 2020
HHVM 4.50 is released! This release marks the end of support for 4.44; HHVM 4.45–4.49 remain supported, as do the 4.8 and 4.32 LTS releases.
Additionally, we are no longer building binary packages for MacOS High Sierra for any version of HHVM, as High Sierra is no longer offered by our build infrastructure provider.
hhvm.hack_arr_is_shape_tuple_notices INI setting, which raises
a notice on $dict is shape() and $vec is tuple(); these are currently
always false, but may be true in the future, so are unsafe to depend on.HH\BuiltinEnum<T> is now covariant.__get, __set, __isset, __unset) have been removed from
the typechecker definitions of builtins, such as the XMLReader, Imagick,
DateTime, and SimpleXML extensions.array() literals will be removed; the hhvm.hack.lang.disable_array=true
INI setting can be used to enable a runtime fatal when they are used, in
addition to the preexisting disallow_array_literal=true .hhconfig option.Ján
Posted March 18, 2020
HHVM 4.49 is released! This release marks the end of support for 4.43; HHVM 4.44–4.48 remain supported, as do the 4.8 and 4.32 LTS releases.
.hhconfig option disable_modes (previously disable_partial) will
cause the typechecker to treat all files as strict (comments after <?hh
no longer have special meaning).
false for the foreseeable future.hackfmt flag --format-generated-code can be used to format generated
and partially generated files.hackfmt output to be missing when
formatting partially generated files, and other minor fixes and improvements
for hackfmt.Shapes::idx instead of ??.<, >, <=, >=, <=>) a legacy PHP array with a non-array
now throws InvalidOperationException (previously only raised a Notice). It
had already been a typechecker error.class_meth is used with arguments that are not
a ::class and a string literal (a string literal as the 1st argument will
also not cause a runtime error, but ::class literal is recommended). It had
already been a typechecker error.
<<__DynamicallyCallable>> and use HH\dynamic_class_meth().__call or __get. Currently, you can use the INI option
hhvm.no_use_magic_methods=true to trigger warnings whenever a magic method
is invoked, e.g. when an undefined method is called on a class that has the
__call magic method.true, false, and null with the “fuzzy” equality
operators (==, !=) will be changed so that non-empty Hack arrays are
== true and empty Hack arrays are == false and == null.
hhvm.hack_arr_empty_based_bool_eq_cmp=true can be used to
enable this behavior now.Fred Emmott
Posted March 09, 2020
HHVM 4.48 is released! This release marks the end of support for 4.42; HHVM 4.43–4.47 remain supported, as do the 4.8 and 4.32 LTS releases.
abstract modifier should be), instead
of at the function declaration.hackfmt
will now ignore any code in such a range, as formatting it could un-suppress
errors.hack-codegen is partially generated, hackfmt will
only format the manual sections.hackfmt will not modify files containing @generated.hh_client lsp --config now accepts .hhconfig settings, in addition to
hh.conf (system-wide) settings.$x is SomeEnum if an exhaustive switch statement contains a
default: block.switch ($enum)
blocks; while the enum is not enforced at runtime, we feel this behavior is
better as it raises an error when the enum is expanded but switch statements
are not. Note that a switch statement that does not match (no matching case,
no default) are still expected to throw an exception in a future release, or
now with the hhvm.throw_on_non_exhaustive_switch=2 setting.HHVM_VERSION_ID is of the form XXYYYZZ instead of XXYYZZ; if you are
extracting parts, please use the HHVM_VERSION_MAJOR, HHVM_VERSION_MINOR,
and HHVM_VERSION_PATCH constants instead.disable_partial (will be renamed disable_modes shortly) - a boolean flag that disables partial mode (and all other modes!) from Hack completely. Comments after the <?hh are just comments, and non-hhi files are inherently strict. The default value will be false for the foreseeable future.Ján
Posted March 03, 2020
HHVM 4.47 is released! This release marks the end of support for 4.41; HHVM 4.42–4.46 remain supported, as do the 4.8 and 4.32 LTS releases.
.hhconfig flags:
ignored_fixme_codes: a comma delimited list of error codes (4110, 2071,
etc.) that allow you to gradually forbid HH_FIXMEs in your codebase. Hack
will ignore any HH_FIXME or HH_IGNORE_ERROR with the specified codes. An
empty list is the default, meaning only the hardcoded unfixmeable codes (see
default_ignored_fixme_codes in errors.ml)
are forbidden.disallowed_decl_fixmes: a comma delimited list of error codes (4110,
2071, etc.) that allow you to gradually forbid HH_FIXMEs in your codebase.
Hack will ignore any HH_FIXME or HH_IGNORE_ERROR outside of the body of a
function with the specified codes. Declaration-level FIXMEs tend to
obscure more errors than intended, so tend to be more important to fix up.error_codes_treated_strictly: a comma delimited list of error codes
(4110, 2071, etc.) that allow you to gradually forbid HH_FIXMEs in your
codebase. Partial mode files accept a number of errors that are not
allowed in strict mode. If an error is in this list, we will report it as
an error—even in a partial mode file. Not every error and position
can be reported clearly though. Certain errors (like missing types) can
cascade into other code, yielding other error codes or being hidden by
partial mode. Still, this list can provide a means to incrementally fix
things in partial mode files without strictifying the whole file. The
default is an empty list, which uses the normal partial/strict modes.use function, use const, or use type declaration is now a
parser error.
namespace is now a reserved keyword, trying to use it as an identifier will
result in a parser error.
HHVM_VERSION_ID is now XXYYYZZ instead of XXYYZZ.
</>, but breaks any
code trying to parse HHVM_VERSION_ID into individual parts.HHVM_VERSION_MAJOR, HHVM_VERSION_MINOR,
HHVM_VERSION_PATCH (added in HHVM 4.42) instead of parsing the value.children declarations will be removed.
XHPChildValidation trait from
xhp-lib v3.1
should be used instead, see
HHVM 4.46 release notes
for more information and migration instructions..hhconfig option disable_xhp_children_declarations=true can be used
to get the future behavior now.Fred Emmott
Posted February 24, 2020
HHVM 4.46 is released! This release marks the end of support for 4.40; HHVM 4.41–4.45 remain supported, as do the 4.8 and 4.32 LTS releases.
case foo_expr: vs switch(bar_expr)default case; as enums are not enforced at runtime, these defaults are
not strictly unreachable.HH\autoload_get_paths(), returning a list of all files known to the
autoloader.children declarations will be removed; special syntax is no
longer required to support this feature, and allows more easily making it
compatible with the main XHP type system.
XHPChildDeclarationConsistencyValidation requires that the new and old
forms of child declaration are equivalentXHPChildValidation requires that only a new declaration is present--add-xhp-children-declaration-method and
--remove-xhp-child-declarationschildren declarations is completely removed, we expect
to remove support for XHP category declarations: they are only used with
children declarations, and by moving children declarations to standard Hack
code, they can be replaced with normal interfaces.Ján
Posted February 20, 2020
A security update has been released for all supported HHVM versions. Please update to one of the following versions to make sure you’re secure:
This security update addresses vulnerabilies in JSON decoding:
The new packages also include updates to some of the bundled dependencies:
libzip librarylibsqlite3 library from 3.23.1 to 3.30.1, as the older
version might be affected by multiple published vulnerabilitiesNote that the bundled dependencies are only used on systems that don’t already provide those libraries.
Ján
Posted February 19, 2020
HHVM 4.45 is released! This release marks the end of support for 4.38 and 4.39 (some versions were supported for longer than usual because 4.37 was skipped); HHVM 4.40–4.44 remain supported, as do the 4.8 and 4.32 LTS releases.
is_array($value) to be less restrictive.
The type-checker now understands the refined type to be the intersection of
$value’s original type and varray_or_darray, instead of always rewriting
the type to varray_or_darray.
darray value to is_array, the type-checker
no longer rewrites $value’s type to varray_or_darray but keeps treating
it as a darray.HH\autoload_type_to_path(),
HH\autoload_function_to_path() and HH\autoload_constant_to_path() can be
used to look up entries in the autoload map (e.g. for debugging).hh_client --type-at-pos now returns additional information about how the
type was determined.switch statements are no longer allowed. They now produce a
type-checker error as well as a fatal error at runtime, and in the future will
be treated as a parsing error.new_inference_lambda=true option in
.hhconfig enables this behavior.array_key_exists() now throws an InvalidArgumentException if the provided
key is null.
hhvm.hack_arr_compat_check_null_hack_array_key=true and
hhvm.hack_arr_compat_notices=true INI options can be used to raise a
notice.ArrayAccess
interface no longer provides its “magic” behavior. The interface still exists
but its methods now need to be called directly (e.g. $stack->push(42)
instead of $stack[] = 42;).final method, the type-checker now raises an
error in the child class instead of the parent class. This doesn’t introduce
any new errors but may require some HH_FIXMEs to be moved.
<<__Const>> or
<<__LateInit>>.this as a reified generic type parameter in a
type annotation (e.g. ClassWithReifiedGeneric<this::T> $arg) is now a
type-checker error.
foo<this::T>()) including
constructor calls (new ClassWithReifiedGeneric<this::T>()).array() literals will be removed; use vec/dict/keyset instead if
possible, otherwise varray or darray.
hhast-migrate --php-arraysswitch statements
where none of the cases matched the provided value.
default branch should be added to any switch statements that
intentionally don’t cover all possible cases.hhvm.throw_on_non_exhaustive_switch=2 INI option to enable this
behavior now (or set the value to 1 to raise a warning instead of throwing
an exception).true to a function declared as
function takes_arraykey<T as arraykey>(T $arg) will be a runtime error in
the future.
hhvm.emit_generics_ub=true with
hhvm.enforce_generics_ub=2 to enable this behavior now (or set the latter
value to 1 to raise a warning instead of a fatal error).is_array() will likely be changed to also return true for
Hack arrays (vec, dict and keyset).
true for legacy arrays (array, varray and
darray). This change should make it easier to migrate from legacy arrays
to Hack arrays.HH\is_php_array() was added in this release, which
only returns true for legacy arrays (the current behavior of
is_array()). You can replace any calls to is_array() with this function
to guarantee no behavior changes in the future.HH\is_any_array() to preemptively migrate any is_array()
calls to the future behavior.vec, dict and keyset) with boolean values using
the “fuzzy” comparison operators == and != will be changed to consider
empty arrays equal to false and non-empty arrays to true.
array, varray, darray). It should make it
easier to migrate from legacy arrays to Hack arrays.=== and !== are not affected, they will
always evaluate to false when comparing values of different types. It is
highly recommended to use these strict operators for comparisons and
use C\is_empty() for checking the emptiness of arrays instead.hhvm.hack_arr_compat_hack_arr_cmp_notices=1 INI option to raise a
notice whenever Hack arrays are compared with boolean values, and therefore
the result may be affected by this future change.Fred Emmott
Posted February 10, 2020
HHVM 4.44 is released! HHVM 4.38–4.43 remain supported, as do the 4.8 and 4.32 LTS releases.
__Deprecated attribute is no longer permitted on any types, such as
classes, enums, or type aliases; it had no effect in these positions.(int) NAN is now consistently the minimum 64-bit signed integer, instead of
['foo', 'bar']) are now a
parse error. array() is still supported, but will be removed in the
near future. Ideally, use vec/dict/keyset instead, but varray and
darray remain supported.<, <=, <=> etc) will be changed
to throw when a PHP array is compared with a non-array. This operation
currently raises a typechecker error, and raises a notice if
hhvm.hack_arr_compat_notices=true and
hhvm.hack_arr_compat_check_compare_non_any_array=true INI options are set.
The behavior of !==, and === will not change.array_key_exists() will change to throw an exception if the specified key is
null. A notice is raised if the
hhvm.hack_arr_compat_check_null_hack_array_key=true and
hhvm.hack_arr_compat_notices=true INI options are set.new_inference_lambda=true .hhconfig setting;
this can lead to the detection of additional type errors (example below)Stringish objects will change to raise a runtime exception;
the hhvm.notice_on_implicit_invoke_to_string option can be used to detect
this.
(string) casts, and various forms of implicit
casting (e.g. concatenation, comparisons, printfs, and interpolation);
searching for (string) will not find all problematic code.switch ($foo) { /* empty */ }) will become a parse
error.array() literals will be removed; use vec/dict/keyset instead if
possible, otherwise varray or darray.If the type can not be inferred in a usable way, the typechecker will now raise an error instead of assuming the behavior is safe.
1
2
3
4
5
6
7
8
9
10
function just_return_it<T>((function(T): void) $f):(function(T): void) {
return $f;
}
function break_it():void {
// No error here
$g = just_return_it($y ==> $y->this_method_does_not_exist());
// Can even try and invoke it on a string
$g('ohno');
}
Ján
Posted February 03, 2020
HHVM 4.43 is released! This release marks the end of support for 4.36; HHVM 4.37–4.42 remain supported, as do the 4.8 and 4.32 LTS releases.
int $x = 42;).json_decode, str_split, array_fill,
class_implements, class_uses, class_parents now return darray instead
of the legacy array type. This change should be largely transparent, as
darray and array are interchangeable at runtime, but the change might be
observable by serialize, var_dump or similar functions.contains method on Set, ImmSet and ConstSet is now declared to
take an arraykey argument instead of mixed. The method would already throw
at runtime when called with any non-arraykey value.Fred Emmott
Posted January 27, 2020
HHVM 4.42 is released! This release marks the end of support for 4.35; HHVM 4.36–4.41 remain supported, as do the 4.8 and 4.32 LTS releases.
4361, instead of
an exception. This error code should never be suppressed - please file a bug
report if you see this
error code.Foo::bar| can
now autocomplete to Foo::bar($id).HHVM_VERSION_MAJOR, HHVM_VERSION_MINOR, and HHVM_VERSION_PATCH
constants; these should be used instead of parsing the HHVM_VERSION or
HHVM_VERSION_ID constants. HHVM_VERSION_ID is recommended for direct
comparisons, e.g. with >=.\HH\enumname<T> type to the runtime; this is similar to
classname<T>, for Hack enums.readdir() and rewinddir() if the directory is already
closed; false will be returned instead.() ==> async {} (returning an async block);
it now suggests async () ==> { } instead (an async lambda).HHVM_VERSION_ID will change from XX.YY.ZZ to XX.YYY.ZZ, to support the
expected release of HHVM 4.100 later this year; if using standard comparison
operators to compare two version IDs, this should not be a significant change,
unless checking for < 50000 or similar - replace that check with
HHVM_VERSION_MAJOR === 4. If you’re converting to/from human-readable form,
consider migrating to the new HHVM_VERSION_MAJOR, HHVM_VERSION_MINOR, and
HHVM_VERSION_PATCH or existing HHVM_VERSION (string “x.y.z”) constants.ArrayAccess objects is being removed.
$x['foo'] for both read and write (replace with explicit
offsetSet or offsetGet calls)isset($x['foo']) ($x->offsetExists('foo')) and
unset($x['foo']) ($x->offsetUnset('foo').hhvm.notice_on_array_access_use=true INI setting can be used to raise
notices for this behavior at runtime.Ján
Posted January 21, 2020
HHVM 4.41 is released! This release marks the end of support for 4.34; HHVM 4.35–4.40 remain supported, as do the 4.8 and 4.32 LTS releases.
HH\enumname<TEnum>, represents the name of the enum type
TEnum (similarly to classname<TClass>).HH\type_structure_for_alias, returns the TypeStructure of
the specified type alias (similarly to HH\type_structure for type constants
in classes).
TypeStructure API remains experimental and may be changed or
removed in the future.usort, uasort, uksort now accept callbacks that return
any num value (int or float), allowing for more convenient sorting of
float arrays.
Vec\sort,
Dict\sort,
Keyset\sort.%foo), and the special values
pcdata, any and empty (case-sensitive).HH_FIXMEs to be moved....$args) were updated to provide more information in different cases. In
some cases this results in changed error numbers, but it shouldn’t result in
any new errors.returnsReference was removed from ReflectionFunction and
ReflectionMethod. It always returned false since HHVM
no longer supports references.Fred Emmott
Posted January 13, 2020
HHVM 4.40 is released! This release marks the end of support for 4.33; hhvm 4.34–4.39 remain supported, as do the 4.8 and 4.32 LTS releases.
<foo x="1" x="2" />) is now
a syntax errorA change last year unintentionally made the parser accept arbitrary types
for XHP children declarations, however:
We are changing the typechecker to verify that XHP children declarations do not refer to undefined types; in the context of XHP children declarations, the following types will be considered valid by the typechecker:
pcdata, any, or empty.%foo.We expect this change to be included in 4.41.
There are some additional things to be aware of:
Additionally, this release includes disabled support for xhp class foo {}
as an alternative syntax to class :foo {}; this is to unblock future work on
improving interactions between XHP and namespaces - usage is not recommended at
this time.
Ján
Posted January 07, 2020
HHVM 4.39 is released! Since the 4.32 release has long term support, it remains supported, as do the 4.8 LTS and 4.33–4.38 releases.
int,
float, num and
dynamic. In rare cases
this may result in a typechecker error moving to a different location, e.g.
from where a value is assigned to where it is used.set_pre_timeout_handler() must now accept a nullable
wait handle argument (?Awaitable<mixed>). The wait handle will have a value
when the callback is invoked right after a wait handle had finished. The wait
handle is required in order to get a good backtrace. This is a similar
behavior to the wait handle that is returned in the
IntervalTimer
class.Fred Emmott
Posted January 02, 2020
HHVM 4.38 is released! This release marks the end of support for 4.31; 4.32–4.36 remain supported, as does the 4.8 LTS release.
The 4.37 release was skipped due to the holiday season.
SA_RESTART to SIGVTALARM flags, allowing operations such as flock
to continue when interrupted by some profiling tools, instead of failing
with EINTR.string, rather than untyped data. They already always
returned strings in the runtime.-DNON_DISTRIBUTABLE_BUILD=ON to be
passed to cmake; editline remains supported as the default implementation,
and this does not affect our builds. In custom builds, hphpd and the PHP
readline-related functions may switch to using editline instead of readline.disable_lval_as_an_expression=false
.hhconfig option; this option will be removed in a future release.Fred Emmott
Posted December 17, 2019
We have decided to cancel next week’s release of HHVM 4.37, and expect to delay 4.38 until Thursday, the 2nd of January. HHVM 4.31 will be supported until the release of HHVM 4.38 or above. As HHVM 4.32 has long-term-support (LTS), it is unaffected by this change.
Our usual schedule is to release on Mondays or Tuesdays, and we expect many people - both at Facebook, and among our users - to be on vacation for Tuesday and Wednesday for the next two weeks. We believe that releasing new versions with breaking changes at this time would not be in the best interests of our users, especially as we would be less able to support them during this time.
We look forward to continuing the evolution of Hack and HHVM in 2020.
Ján
Posted December 16, 2019
HHVM 4.36 is released! This release marks the end of support for 4.30; 4.31–4.35 remain supported, as does the 4.8 LTS release.
asort,
arsort, krsort, uasort, uksort). These functions may change the type
of the passed-in container (e.g. vec to dict), which the original
typehints didn’t account for. This change may reveal new type errors in code
that uses these functions.Fred Emmott
Posted December 10, 2019
HHVM 4.35 is released! This release marks the end of support for 4.29; 4.30–4.34 remain supported, as does the 4.8 LTS release.
__construct(classname<T> $f) where T = nothing.__halt_compiler() and __COMPILER_HALT_OFFSET__ have been removed.require extends T; and ... extends T {} now consistently raise naming
errors (2049); previously, extend T was a naming error, while
require extends T raised a type error (4026). This may require modifying
FIXMEs in unsafe/invalid Hack code.hhvm.check_return_type_hints is less than 2, an E_WARNING will
be raised. If set to 2, an E_RECOVERABLE_ERROR will be raised for hard type.
hints, and E_WARNING for soft.Ján
Posted December 02, 2019
HHVM 4.34 is released! This release marks the end of support for 4.28; 4.29–4.33 remain supported, as does the 4.8 LTS release.
hh_client --concatenate-all path/ [morepaths/ ...], which creates a
single-file version of a Hack project. This respects required inclusion order
(e.g. parent classes before child classes), and resolves syntax issues such as
namespace declarations and potentially conflicting use statements. Example
usage:
hh_client --concatenate-all src/ for a libraryhh_client --concatenate-all src/ vendor/ bin/foo.hack for an executableself::abstractStaticMethod() to call an
abstract static method inside a trait. Previously, this was only a type
error if any classes used the trait without implementing the respective
method. The new behavior is consistent with abstract classes, where calling
self::abstractStaticMethod() was already an error. Use
static::abstractStaticMethod() instead (note that this may change the
behavior in some cases, but most likely the new behavior better captures the
original intent of the code).HH_FIXMEs to be moved from a parent class
to its child classes.Fred Emmott
Posted November 25, 2019
HHVM 4.33 is released! This release marks the end of support for 4.27; 4.28–4.32 remain supported, as does the 4.8 LTS release.
foo<vec>() now raises an error, as vec requires
a generic typenewtype FOO = int;, it was previously unpredicable if the type stucture
for new MyClass<FOO>() would return the type alias information
or not, and new MyClass<int>() could return FOO’s type alias
information. The correct type structure will now consistently be returned.
This only affects classes with reified generics - functions using reified
generics are unaffectedJán
Posted November 19, 2019
HHVM 4.32 is released! This release has long term support, so:
See also the new support lifecycle for older distributions.
fb_intercept2, fb_serialize,
xhprof_enable). See
header file
for the full list.source $BUILD/hphp/hack/dev_env.sh to set up
the correct environment for all OCaml tools (dune/cargo/opam/ocamlformat/…).MOVE method.varray_or_darray (a helper type, only existing in the typechecker,
for migrating from legacy arrays) now has two generic type parameters.
varray_or_darray<T> is implied to mean
varray_or_darray<arraykey, T>.foreach now extend a single
Traversable interface.
\HH\Traversable, but since this is an
“autoimported” type, the fully qualified name should never be
needed.\Traversable and
\HH\Traversable, with most (but not all!) types implementing
\HH\Traversable (an example exception is DOMNodeList which only
implemented \Traversable).\Traversable and \Iterator interfaces (inherited from PHP) have been
removed in favor of \HH\Traversable and \HH\Iterator. Hack code that
refers to Traversable and Iterator with no leading backslash will
continue to work unchanged, but code that had \Traversable or \Iterator
needs to either remove the leading backslash or add \HH (note that this
changes the behavior of the affected code, making it refer to a much larger
set of iterable types).HH\BuiltinEnum outside of built-in header files is once again
disallowed by the typechecker (error 2053). This restriction had recently been
lifted (in HHVM 4.28), but
it is being reintroduced because we discovered some new runtime issues when
the type is used.hhvm.php7.int_semantics has been removed.Fred Emmott
Posted November 19, 2019
We currently package for Debian 8 (Jessie) from 2015, and Ubuntu 16.04; this constrains us in several ways, such as:
To allow more time to be spent on improving Hack itself, in the future, we will be more aggressive about removing support for older distributions.
HHVM 4.32 - due to be announced later today - will be an LTS release; 4.56 will be the next LTS release, and is due in 24 weeks (week of 2020-05-04). 4.56 will be the last release that supports:
In HHVM 4.57 and above, we will aim to support:
stable (currently Buster). If the current stable was released in
the last 6 months, we will also aim to support oldstable (currently
Stretch). We are open to investigating support for Debian testing (currently
Bullseye), but are not currently doing so.In general, we do not intend to proactively stop testing/packaging for distributions as soon as they become ‘unsupported’; however:
Given we want to remove support for OpenSSL 1.0 and for systems using the C++5 ABI, we expect to stop building packages for several distributions - especially Debian 8 Jessie and Ubuntu 16.04 very shortly after the release of HHVM 4.56.
If we build a package for a distribution for a x.y.0 release, we intend to build packages for that distribution for any x.y.z releases - as long as the distribution itself continues to receive security updates from the distribution vendor.
In other words, dropping support for a distribution in a new release does not affect support for that distribution in past verisons of HHVM.
For example:
We strongly recommend using a supported distribution instead. That said, there are several options:
If you are using a current version of a distribution that we do not package for at all (e.g. CentOS), we would appreciate pull requests to add support to our packaging infrastructure; any new packaging should be:
master of a dependency from github is
not acceptablerpmbuild or debuild or similiar instead
of manually building a package from binaries created separatelyThe HHVM support lifecycle for any other distributions would likely be similar to our support lifecycle for Debian and Ubuntu, aiming to provide some upgrade window while allowing us to frequently update the minimum versions of dependencies.
Fred Emmott
Posted November 11, 2019
HHVM 4.31 is released! This release marks the end of support for 4.25; 4.26–4.30 remain supported, as do the LTS releases 3.30 and 4.8.
HH\Lib\SQL\Query object, and AsyncMysqlConnection::queryAsync()
method; this is an alternative to ::queryf(). Query objects:
queryf-style format string and a list of parametersvec<>s instead of Vector<>s%Q placeholder, which accepts another Query object;
this allows much more flexibility, such as concatenating queries with
$ab = new Query('%Q %Q', $a, $b)hh_server when posix_fallocate
fails with EINTRHH\Tuple\from_async() and
HH\Asio\va(); ideally, these should be replaced with concurrent blocks,
or, if a tuple is actually desired, tuple(await foo(), await bar()) can be
used insteadHH\Asio\va()’s typechecker definition as it is no longer usefulldap_mod_(del|replace|modify) now take a darray entry argument(unset) cast has been removed. Use the null literal insteadunserialize()ing a PHP array will now create a varray or darrayJán
Posted November 06, 2019
HHVM 4.30 is released! This release marks the end of support for 4.24; 4.25–4.29 remain supported, as do the LTS releases 3.30 and 4.8.
mailparse extension (issue
#8532)HH namespace (HH\dict, HH\Container, etc.), consistently
with how the runtime already treated them
HH\dict), or not report errors in code that would
fail at runtime (\dict)dict
instead of HH\dict, etc.)vec, dict, keyset,
Container, KeyedContainer, Traversable, KeyedTraversable,
Iterable, KeyedIterable, Iterator, KeyedIterator, AsyncIterator,
AsyncKeyedIterator, AsyncGeneratoruse statements
(use MyVector as Vector, use MyType as string, etc.)function($num) { return $num * 2; }) in favor of lambdas
($num ==> $num * 2)
error_php_lambdas=true to your .hhconfig
(this will likely become the default behavior in the future)fb_serialize()
to correctly distinguish between all the different array-like types (vec,
dict, keyset, varray, darray, array)
Fred Emmott
Posted October 29, 2019
HHVM 4.29 is released! This release marks the end of support for 4.23; 4.24–4.28 remain supported, as do the LTS releases 3.30 and 4.8.
HH\ from names that are automatically imported into
every namespace.hack files not being correctly indexed by some IDE features$someshape['somekey''] with two apostrophes; this was most common
with IDEs configured to automatically insert matching quotation marks.RuntimeOption::CheckIntOverflow option:
DO_NOT_USE in the name$c->toVector(), $c->toSet(), $c->toMap() have been removed from Hack
collections; use new Vector($c) etc or Hack Arrays instead; this is because
they are not type-safe, as variance checks were added for genericsSet::zip() now returns Set<nothing>, as pairs can not be stored in Sets;
this could lead to new type errors in code that would previously fail at
runtime. Similar changes have been made to ImmSet and other related classesunserialize() no longer creates references; if old serialized data
containing references is used, the referenced value will be copied insteadAwaitable’s fully-qualified name
is HH\Awaitable; it remains autoimported. In previous releases, the
runtime considered it to be HH\Awaitable, but the typechecker considered it
to be \Awaitableinoutarray (without generics) is now considered to be the union of array<_>
(a.k.a varray) and array<_, _> (a.k.a. darray); this can lead to
stricter handling of key (example 1,
example 2)Ján
Posted October 28, 2019
A security update has been released for all supported HHVM versions. Please update to one of the following versions to make sure you’re secure:
This security update addresses multiple potential vulnerabilies, mostly found by running a new fuzzer over the HHVM codebase.
More information can be found in the respective CVEs:
Ján
Posted October 23, 2019
HHVM 4.28 is released! This release marks the end of support for 4.22; 4.23–4.27 remain supported, as do the LTS releases 3.30 and 4.8.
Release 4.28.1 fixes some minor bugs that were introduced in 4.28.0.
set_pre_timeout_handler,
was added. The pre-timeout handler allows cheaper debugging of timeouts by
invoking analysis code a few seconds prior to requests timing out. It also
allows re-registering a new pre-timeout callback much like the memory
threshold callbacks.hackfmt to reformat code in a way that breaks
HH_FIXME comments in some cases.HH\BuiltinEnum—the parent type of all enums (previously error 2053).int, Vector,
Awaitable) will no longer override the built-in type. Such types can now
only be referenced using their namespaced name (e.g. MyNamespace\Vector, or
namespace\Vector if in the same namespace).use multiple traits that declare __construct()
from the same class.array_map(['ClassName', 'nonStaticMethodName'], $arr)).array where a tuple is
expected or vice-versa (previously, this was only an error if the
disallow_array_as_tuple flag was enabled). Note that this change only
affects arrays with a missing generic type, which would already be an error
in strict mode.unset on an element of an array or varray
(previously, this was only an error if the disallow_unset_on_varray flag was
enabled). It can only be called on dict and darray elements now..hhconfig flags were removed:
coercion_from_dynamic (see
documentation
for current coercion rules for dynamic values)coercion_from_unionsafe_array (it is now always a type error to use array where array<T>
is expected, which had already been the default behavior)safe_vector_array (it is now always a type error to use array<Tv> where
array<Tk, Tv> is expected, which had already been the default behavior)disallow_array_as_tuple (this changes the default behavior, see above)disallow_unset_on_varray (also changes the default behavior)Fred Emmott
Posted October 14, 2019
HHVM 4.27 is released! This release marks the end of support for 4.21; 4.22–4.26 remain supported, as do the LTS releases 3.30 and 4.8.
register_postsend_function() and register_shutdown_function() now take
a single function(): T argument, instead of a callable and variadic
argumentsbreak and continue with a level (e.g. break 3;) is now a parse error;
previously, a typechecker error was raisedabstract class C { abstract const type T; } function foo(C::T $x))Ján
Posted October 09, 2019
HHVM 4.26 is released! This release marks the end of support for 4.20; 4.21–4.25 remain supported, as do the LTS releases 3.30 and 4.8.
dynamic type can now be
used in more places (inside XHP, unset statements)(Cat | Dog) and
intersection types (FourLegged & Mammal) – this is an early
experimental prototype not meant for general use (it is entirely possible that
the prototype will never make it to a final release, depending on, for
example, how it affects typechecking performance in various scenarios), but if
you want to experiment with it, add union_intersection_type_hints=true to
your .hhconfigint, vec, Vector, Traversable, Awaitable)
are now case-sensitive at runtime (previously only the typechecker treated
them as case-sensitive)__get, __call) can no longer have
inout parameters&$reference parameters in built-in functions were migrated to
inout parameters or removed – from those, the following ones are not
backwards compatible:
flock (use hhast-migrate --ref-to-inout for automated migration)SplFileObject::flockNumberFormatter::parse (use parseWithPosition when the optional
argument is needed)IntlDateFormatter::parse (use parseWithPosition)Memcached::get (use getWithCasToken)Memcached::getByKey (use getByKeyWithCasToken)Memcached::getMulti (use getMultiWithCasTokens)Memcached::getMultiByKey (use getMultiByKeyWithCasTokens)current_ref (use current which returns the same value, but takes a
non-reference argument)key_ref (use key)xml_set_object_ref (use xml_set_object)PDOStatement::bindParam (use bindValue instead)PDOStatement::bindColumn (use bindValue)SQLite3Stmt::bindparam (use bindvalue)With all &$references in built-in functions gone, we expect that references
will be completely removed from the Hack language within the next few releases.
See detailed blog post.
Daniel Neiter
Posted October 01, 2019
PHP-style references (&$variable) have been a source of confusion and
unsoundness in the Hack type system (read on to learn why). After a long
effort, we are now finally ready to remove them from the Hack language.
We expect to remove support for PHP-style references from HHVM in about 2–4 weeks.
By far the most common use case for PHP references is passing function arguments by reference. Inout parameters are built to address this use case without relying on PHP references. See also Migrating to inout parameters.
We have updated all built-in functions with reference parameters (such as
sort(), array_pop(), or preg_match() with a &$matches argument) to use
inout parameters instead. In some cases, the function that takes an inout
argument has a new name (e.g. preg_match_with_matches()). You can migrate your
calls automatically using HHAST v4.21.7 or newer:
1
hhast-migrate --ref-to-inout
For references other than function parameters, the
Ref class can be used
to explicitly achieve reference semantics when necessary. A common example is
needing to share mutable state between a lambda and enclosing function:
1
2
3
4
5
6
7
8
9
10
11
function sort_and_count_comparisons(inout vec<int> $a): int {
$comparisons = Ref(0);
\usort(
inout $a,
($left, $right) ==> {
$comparisons->value++;
return $left - $right;
}
);
return $comparisons->value;
}
PHP references allow the same variable to be accessed using multiple different names. Changes done via one reference are visible through all references to the same variable. Let’s look at a simple example (all examples use PHP7 unless noted otherwise, as Hack no longer supports most of reference behaviors):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$var = 'abc';
$other_var = &$var; // $other_var is now an alias to $var
$one_more_var = &$other_var; // $one_more_var is also an alias to $var
$arr['key'] = &$var; // references can be stored inside arrays
$obj->prop = &$var; // and in object properties
$other_var = 'def'; // $var, $other_var, $arr['key'] and $obj->prop now contain 'def'
foreach($arr as &$x) { // iterate over array by reference
++$x; // modifying $x modifies $arr elements
}
function &returns_ref(&$arr) {
return $arr['key']; // references can be returned from functions
}
// functions can take parameters by reference
function increment(&$value) {
$value += 1;
}
References are widely used in PHP standard library—sort(),
array_pop(), preg_match() to name a few most frequently used examples.
Let’s look at another example:
1
2
3
4
5
6
7
$arr = array(0, 1, 2);
foreach ($arr as &$v) {
$v += 1;
}
foreach ($arr as $v) {
var_dump($v);
}
What is the produced output, and more importantly why does it work this way? (Spoilers).
This is almost never intended behavior, and the resulting issue is very easy to miss. As part of deprecating foreach-by-reference support at Facebook we have discovered multiple bugs, following this pattern.
PHP references are a major blocker for making the Hack type system sound (i.e. reaching the point where Hack typechecker is correct about types 100% of time). PHP references were designed for a dynamically typed language and they cannot be modeled in Hack type system without significantly restricting their power.
The unsoundness problem is best illustrated by another example (3v4l):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Foo {
public $prop;
}
$foo = new Foo();
$str = 'abc'; // $str is a string
$foo->prop = &$str;
var_dump($foo->prop); // "abc"
$arr = array();
$foo->prop = $arr;
var_dump($foo->prop); // array()
var_dump($str); // array() - surprise! $str is now an array
PHP references are a significant source of complexity and performance overhead in HHVM. Moreover, references make it possible for Hack code to observe a number of runtime implementation details (e.g. reference counting), blocking HHVM team from exploring more efficient alternatives.
Multiple efforts in HHVM have already taken advantage of references removal. All of these provided significant measurable CPU improvements when we deployed them to Facebook servers:
With references removal now complete, we expect more wins down the line.
Fred Emmott
Posted September 30, 2019
HHVM 4.25 is released! This release marks the end of support for 4.19; 4.20-4.24 remain supported, as do the LTS releases 3.30 and 4.8.
@param documentation is now shown in IDE signature help.getAttributeRecursive and getAttributesRecursive reflection methods
have been removed; they were previously marked as __Deprecated.inout parameters:
natsort(), natcasesort(), sort(), rsort(), asort(), arsort(),
ksort(), krsort(), usort(), uasort(), and uksort()array_pop(), array_push(), array_shift(), array_splice(),
array_unshift(), and shuffle()IntlTimeZone::getOffset()pagelet_server_task_result(), xbox_send_message(), and
xbox_task_result()call_user_method() and call_user_method_array() have been removed - they
have been deprecated since PHP4.double, real, integer, and
boolean; use float, int, and bool instead. These aliases were
previously typechecker errors.hhast-migrate --ref-to-inout can be used for many of the reference-to-inout
changes.
Ján
Posted September 25, 2019
A security update has been released for all supported HHVM versions. Please update to one of the following versions to make sure you’re secure:
This security update addresses a possible memory overflow in the
number_format() function.
More information can be found in the respective CVE:
Ján
Posted September 23, 2019
HHVM 4.24 is released! This release marks the end of support for 4.18; 4.19-4.23 remain supported, as do the LTS releases 3.30 and 4.8.
hhvm.hack.lang.hack_compiler_use_rust_parser_errors to hhvm.ini.await was used on the right side of a pipe |> operator.fun() and class_meth() can now be used inside constant expressions (this can be disabled by adding disallow_func_ptrs_in_constants=true to .hhconfig).1
2
3
4
class C {
const (function(): int) FUNCTION = fun('time');
private static (function(): void) $method = class_meth('Foo', 'bar');
}
object ((object)$value) is no longer supported by the runtime (it was already a type checker error in strict mode)pg_fetch_object was removed (use pg_fetch_assoc instead)str_replace (use str_replace_with_count instead when needed)str_ireplace (use str_ireplace_with_count)headers_sent (use headers_sent_with_file_line)openssl_encrypt (use openssl_encrypt_with_tag)array_multisort was removed completely (use array_multisort1, array_multisort2, etc. depending on the number of arguments you need to pass in—up to array_multisort9)hhast-migrate --ref-to-inout to automatically migrate your callsinout parameters:
similar_text, parse_strmb_convert_variables, mb_ereg, mb_eregi, mb_parse_strgetimagesize, exif_thumbnailmsg_send, msg_receiveldap_parse_result, ldap_control_paged_result_responseexec, passthru, systemfsockopen, pfsockopen, socket_server, stream_socket_accept, stream_socket_server, stream_socket_client, stream_socket_recvfrom, socket_getpeername, socket_getsockname, socket_recvfromdns_get_record, dns_get_mx, getmxrropenssl_random_pseudo_byteshhast-migrate --ref-to-inout to automatically migrate your callsAsyncMysqlConnectionPool::connect(): Awaitable<AsyncMysqlConnection> now declares a return type (previously untyped)hh_client --typed-full-fidelity-json is no longer supported (it has been producing incorrect results in most cases)hhvm.ini option hhvm.hack.lang.hack_compiler_use_rust_parser_errors (see above) is expected to be removed in the next release (HHVM 4.25)..hhconfig option coercion_from_dynamic will be removed soon. See documentation for detailed coercion rules for the dynamic type.hhvm.ini options hhvm.check_prop_type_hints and hhvm.check_return_type_hints will soon be changed to 3 (fatal error) and the options should be removed soon after that.Fred Emmott
Posted September 17, 2019
HHVM 4.23 is released! This release marks the end of support for 4.17; 4.18-4.22 remain supported, as do the LTS releases 3.30 and 4.8.
$class::foo<int>()inout parametershhvm.admin_server.stats_need_password INI setting.where constraints with genericsdefault: cases in a switch;
this was previously a runtime errordefault: case is present in a
switch but is not the last case.HH\ReifiedGenerics\getTypeStructure(): use
HH\ReifiedGenerics\get_type_structure() insteadHH\ReifiedGenerics\getClassname(): use
HH\ReifiedGenerics\get_classname() instead$GLOBALS without a subcript is now a parse error. Use
HH\global_keys() instead if you need to enumarate the full list.inout parameters; in many cases
this is just a change to the calling convention, however there are
more significant changes, due to inout parameters not permitting default
values; in particular:
Memcache::get() and memcache_get() no longer take a &$flags parameter;
this parameter previously had no effect in HHVM.preg_replace_callback() no longer has an optional $count parameter;
call preg_replace_callback_with_count() if a count is required.$position parameter for NumberFormatter::parseCurrency() is no longer
optional$isSystemID parameter for IntlTimeZone::getCanonicalID() is no longer
optional$issuesFound parameters for SpoofChecker::areConfusable() and
SpoofChecker::isSuspicious() are no longer optionalereg() and eregi() functions have been removedarray_walk() and array_walk_recursive() functions have been removedidn_to_ascii(), idn_to_utf8(), and idn_to_unicode() no longer take an
optional &$info parameterhhast-migrate --ref-to-inout can be used to
automatically migrate many of these cases.
hh_server with
--config symbolindex_search_provider=SqliteIndex&$cas_token parameters for various memcached functions will
be removed; we recommend moving to the inout versions of these functions.&$position parameters for NumberFormatter::parse() and
IntlDateFormatter::parse() will be removed; use
::parseWithPosition() instead.call_user_method()call_user_method_array()PDO::bindParam()PDO::bindColumn()SQLite3::bindparam()hhast-migrate --ref-to-inout can be used to
automatically migrate many of these cases.
Ján
Posted September 09, 2019
HHVM 4.22 is released! This release marks the end of support for 4.16; 4.17-4.21 remain supported, as do the LTS releases 3.30 and 4.8.
?dynamic1
2
3
function foo(): ?dynamic {
return 42; // now an error
}
dynamic (previously they were simply ignored)use const declarations in some cases1
2
3
use const Foo\A as A;
...
use const Foo\B as A; // now an error, previously not always an error
Ján
Posted September 03, 2019
HHVM 4.21 is released! This release marks the end of support for 4.15; 4.16-4.20 remain supported, as do the LTS releases 3.30 and 4.8.
hack.lang.hack_compiler_use_rust_parser=0 to
hhvm.ini. If you see any differences in behavior or other issues, please
open a GitHub issue.hh_client --rewrite-parameter-types <filename> is now
available to help with migration from partial to strict mode. It adds
<<__Soft>> type annotations based on inferred parameter types.1
2
class A { const arraykey C = 'string'; }
class B extends A { const int C = 42; }
await from working inside echo and unset
statements in some cases.preg_match and preg_match_all, automated migration is
available in HHAST 4.15.5 (runs on HHVM 4.18-4.20) and 4.21.2 (runs on
HHVM 4.21).
icu_match (use icu_match_with_matches instead)idn_to_ascii (no replacement available)idn_to_unicode (no replacement available)idn_to_utf8 (no replacement available)is_callable (use is_callable_with_name instead)preg_match (use preg_match_with_matches instead)preg_match_all (use preg_match_all_with_matches instead)apc_dec (last 2 arguments)apc_inc (last 2 arguments)curl_multi_info_readdatefmt_parsegrapheme_extractIntlTimeZone::getCanonicalIDintltz_get_canonical_idNumberFormatter::parseCurrencynumfmt_parsenumfmt_parse_currencySpoofChecker::areConfusableSpoofChecker::isSuspiciousapc_fetchdatefmt_localtimeIntlDateFormatter::localtimerequire extends
is used.NumberFormatter::parse will be
removed in the next release. Any calls that require this argument can be
migrated to NumberFormatter::parseWithPosition which has the old signature.check_attribute_locations=true to .hhconfig.1
2
<<__Memoize>> class C { ... } // invalid!
<<__ConsistentConstruct>> function f() { ... } // invalid!
Ján
Posted September 03, 2019
A security update has been released for all supported HHVM versions. Please update to one of the following versions to get the update:
This security update addresses a possible memory overflow in the GD extension when a carefully constructed invalid JPEG input is passed in.
More information can be found in the respective CVEs:
Ján
Posted August 27, 2019
HHVM 4.20 is released! This release marks the end of support for 4.14; 4.15-4.19 remain supported, as do the LTS releases 3.30 and 4.8.
HHVM 4.20.1 was released to fix a build issue related to the new Rust parser on Mac OS X. All Linux builds for 4.20.1 are identical to 4.20.0.
hack.lang.hack_compiler_use_rust_parser=1 to
hhvm.ini. If you see any differences in behavior or other issues, please
open a GitHub issue.hh_client --rewrite-return-type <filename> is now available to
help with migration from partial to strict mode. It adds <<__Soft>> type
annotations based on inferred return types.BadMethodCallException instead of causing a fatal error.fb_intercept2()
was added as a replacement for fb_intercept().fun_get_function()
was added.HH_FIXME[4110] has been replaced with several new, more specific error
codes. HHAST 4.15.2 provides an automated migration:
hhast-migrate --migrate-fixme-4110 <path> (this migration adds the new
FIXMEs without removing the old ones - after upgrading to HHVM 4.20, the old
FIXMEs can be removed with hh_client --remove-dead-fixmes). The Hack
Standard Library and other Hack libraries all provide a new release that works
on both HHVM 4.20 and previous HHVM versions.<<Attrib>> ...$arg) is now a parser
error.unset() on a class constant will soon be a parser error (previously,
such calls did nothing). You can enable this behavior now by adding
disable_unset_class_const=true to .hhconfig.class_meth() with arguments that are not string literals will soon
trigger a runtime warning (it is already a typechecker error). You can enable
this behavior now by running HHVM with
-vEval.EmitFuncPointers=1 -vEval.EmitClsMethPointers=1 -vEval.WarnOnNonLiteralClsMeth=1Fred Emmott
Posted August 19, 2019
HHVM 4.19 is released! This release marks the end of support for 4.13; 4.14-4.18 remain supported, as do the LTS releases 3.30 and 4.8.
<<__Explicit>> attribute, requiring that generics are specified;
for example, function foo<T>(T $a, T $b) {} foo(123, 'abc'). is valid,
as mixed is a valid type for T; however, for
function foo<<<__Explicit>> T>(T $a, T $b) {}, foo<int>(123, 456) is
valid, but foo<int>(123, 'abc') is not.ReflectionFunctionAbstract::getReifiedTypeParamInfo()dicts are now callable in the runtime; this will raise
a typechecker error, and is not suitable for use in new code.current_ref(), key_ref(), and
xml_set_object_ref(), in preparation for modifying current(), key(),
and xml_set_object() to not take their parameters by-reference.openssl_encrypt_with_tag(), as optional inout arguments are not
supported, in preparation for removing the optional byref tag argument from
openssl_encrypt()hhvm.server.ssl_client_ca_file and
hhvm.server.ssl_client_auth_level options; level 0 is disabled,
1 is optional, 2 is mandatory. If level is not 0, the CA file must be
specified.classname<T> variables."${foo}"-style string interpolation; use "{$foo}"
instead. hhast-migrate --dollar-brace-interpolation can be used to update
code as needed, and the disable_outside_dollar_str_interp=true .hhconfig
option can be used on previous versions to find problem cases.usort(), uasort(), and uksort() now specify the type of the callback,
instead of taking mixed.final interface and final trait are now parse errors.<<__EntryPoint>>
attribute to a class.var keyword.Stringish interface is deprecated, and can not be converted to a string
without a typechecker error. As a temporary aid, it may be useful to define a
function like the following:1
2
3
4
5
6
function stringish_cast(mixed $value): string {
return is_object($value) && $value is Stringish
/* HH_IGNORE_ERROR[4128] This is intentionally deprecated */
? $value->__toString()
: (string)$value;
}
StringishHH_FIXME[4110] and similar suppressions.
These changes can be found now with the use_new_type_errors=true option in
.hhconfig.Ján
Posted August 14, 2019
A security update has been released for all supported HHVM versions. Please update to one of the following versions to get the update:
This security update addresses a HTTP/2 Deny-of-Service vulnerability in the Proxygen library bundled with HHVM.
More information can be found in the respective CVEs:
Note that these vulnerabilities are not specific to HHVM or Proxygen, so keep an eye out for updates to other HTTP/2 server and client packages.
Ján
Posted August 12, 2019
HHVM 4.18 is released! This release marks the end of support for 4.12; 4.13-4.17 remain supported, as do the LTS releases 3.30 and 4.8.
This release only contains minor improvements/cleanups, but there is one notable future change to be aware of.
HH_FIXME[4110]
may need to be updated to avoid typechecker errors.Fred Emmott
Posted August 07, 2019
HHVM 3.30.8, 4.8.2, 4.12.1, 4.13.1, 4.14.1, 4.15.1, 4.16.2, and 4.17.1 are now available; these are non-urgent bugfix releases, containing fixes backported from later releases.
| Versions | Issue |
|---|---|
| 4.16, 4.17 | Fixed a bug where HackC would access shared memory (unneeded by HackC), leading to an exception being thrown. |
| 3.30, 4.8, 4.12-4.14 | Fixed a bug when using CLI server mode that could lead to CLI clients hanging forever when the script is finished. |
| 4.8 | Improve reliability when Xenon is enabled by using SIGPROF instead of SIGVTALRM, and by ignoring Xenon signals if received extremely early in HHVM startup |
| 4.8 | Fix crash when attempting to use repo-authorititative mode on MacOS |
Ján
Posted August 05, 2019
HHVM 4.17 is released! This release marks the end of support for 4.11; 4.12-4.16 remain supported, as do the LTS releases 3.30 and 4.8.
Reified generics are now supported. See full documentation and migration guide.
1
2
3
4
function foo<reify T>(T $arg): void { ... }
foo<int>(42);
foo<string>(42); // now a runtime error
Reified generic types can be used in the function code:
1
2
3
4
5
6
7
8
9
10
11
12
13
abstract class BaseClass {
abstract public function foo(): void;
}
// Before:
function bar(classname<BaseClass> $classname): void {
$classname::foo();
}
// After:
function bar<reify T as BaseClass>(): void {
T::foo();
}
Also see how to
test and assert
reified generic types and how to
create new instances
of reified generic classes.
Ján
Posted July 29, 2019
HHVM 4.16 is released! This release marks the end of support for 4.10; 4.11-4.15 remain supported, as do the LTS releases 3.30 and 4.8.
1
2
3
4
5
class :a {
attribute string foo;
public function bar($baz): void {}
// ^ previously undetected missing type annotation
}
Fred Emmott
Posted July 22, 2019
HHVM 4.15 is released! This release marks the end of support for 4.9; 4.10-4.14 remain supported, as do the LTS releases 3.30 and 4.8.
noreturn methods.mixed ...$foo.inout parameter types are now invariant - both co- and contra- variant.
They were previously incorrectly treated as contravariant.instanceof is now a parse error. In 4.14.x, it was not a parser error, but
no longer refined types. In HHAST 4.14.x, hhast-migrate --instanceof-is can
be used to replace expressions of the form $x instanceof Foo with
$x is Foo, and expressions of the form $x instanceof $some_expression with
\is_a($x, $some_expression).disallow_byref_calls=true .hhconfig option."${foo}" will be removed, and can be replaced with "{$foo}";
hhast-migrate --dollar-brace-variable-migration can be used to migrate
code, and the disable_outside_dollar_str_interp=true .hhconfig setting can
be used to enforce this immediately.Fred Emmott
Posted July 15, 2019
HHVM 4.14 is released! As 4.8 has long term support, it remains supported, as do 3.30 and 4.9-4.13.
instanceof no longer refines types; use is expressions instead.
hhast-migrate --instanceof-is can be used to automatically convert
expressions of the form $x instanceof SomeType to expressions of the form
$x is SomeType, $x is SomeType<_>, $x is SomeType<_, _> etc.
If the RHS of an instanceof is not a classname in sourcecode, but rather
an expression, HHAST4.14.4 and up will migrate to a \is_a() call. This does not
refine the variable on the LHS for the typechecker.re"(())"
is now handled correctly.instanceof no longer refines types.$this is no longer allowed in PHP-style static closures, e.g.
$x = static function () { $this->foo(); }.new on Closure are now
case-insensitive to match the runtime behavior.DateTime::COOKIE and DATE_COOKIE now use the correct format for cookies.
The old value is available as DATE_RFC850. This replaces full day-of-week
(e.g. ‘Monday’) with 3-letter abbreviations (e.g. ‘Mon’).$shape['somefield'] ?? null is now a type error if 'somefield' is known
not to exist; it is still permitted if 'somefield' /may/ exist.The typechecker is now able to track multiple type constraints for the same variable, creating intersection types; they can not be declared in source code.
For example:
1
2
3
4
5
6
7
8
9
10
11
12
13
function f(Foo $x): void {
// $x is Foo
if ($x is IBar) {
// before: $x is IBar
// now: $x is Foo & IBar (intersection)
expects_an_IBar($x); // correctly works in both
expects_a_Foo($x); // no longer an error!
}
// before: $x is Foo | IBar (union)
// now: $x is Foo
expects_an_IBar($x); // correctly an error in both
expects_a_Foo($x); // no longer an error!
}
As well as allowing more valid code to be understood by the typechecker, this can exposed via hover type information and via error messages.
An expression is of type (A & B) if it is both of type A and of type
B, which is the case inside the if statement above. Intersections are in some
ways similar to type *unions *(denoted by |), which allow tracking types through
control flow and are also internal to the typechecker (they can not be declared
in source code). Having both intersections and unions allows us to greatly
improve type refinement in Hack, leading to a more intuitive experience.
As part of this work, tracking for unions has also been improved:
1
2
3
4
5
6
7
8
function f(mixed $x): void {
if ($x is int || $x is string) {
// before: $x is mixed
// now: $x is int | string
expects_an_arraykey($x); // no longer an error!
}
// both: $x is mixed
}
Previously, it was common to work around this limitation with temporary variables or type assertions:
1
2
3
4
5
6
7
8
function f(Foo $x): void {
$x_for_hack = $x; // now unnecessary
if ($x_for_hack is IBar) {
expects_an_IBar($x_for_hack);
expects_a_Foo($x);
}
expects_a_Foo($x as Foo); // "as" no longer needed
}
These workarounds can now be removed:
1
2
3
4
5
6
7
function f(Foo $x): void {
if ($x is IBar) {
expects_an_IBar($x);
expects_a_Foo($x);
}
expects_a_Foo($x);
}
The difference between type /intersections/ and type /unions/ is essentially the same as the one between the logical ‘AND’ and the logical ‘OR’.
Something is an intersection type (I1 & I2) if it is both I1 and I2.
Intersections are obtained with refinements:
1
2
3
4
5
function f(I1 $x): void {
if ($x is I2) {
// here $x is both an I1 and I2, and gets type (I1 & I2)
}
}
Something is a union type (A | B) if it is either A or B; the
type system does not know which one it actually is.
1
2
3
4
5
6
7
8
9
10
11
12
if (something()) {
$x = new A();
} else {
$x = new B();
}
// here $x is either A or B and has type (A | B)
$v = vec[new A(), new B()];
$y = $v[$i]
// $y is either A or B and has type (A | B)
instanceof RefinementIn previous versions of Hack/HHVM, expressions of the form $x instanceof Foo
would inform the typechecker that $x is of type Foo; this is no longer the
case, replaced by is and as expressions. For example:
1
2
3
4
5
6
7
8
9
10
11
class Foo {}
function takes_foo(Foo $_): void {}
function do_stuff(mixed $in): void {
if ($in instanceof Foo) {
takes_foo($in); // valid in 4.13, but not in 4.14
}
if ($in is Foo) {
takes_foo($in); // valid in 3.28+, including 4.14
}
}
is expressions require matching generics; for example:
1
2
3
4
5
6
7
8
9
10
class NoGenerics {}
class OneGeneric<T> {}
class TwoGenerics<Ta, Tb> {}
function do_stuff(mixed $in, classname<SomeType> $what): void {
if ($in is NoGenerics) { }
if ($in is OneGeneric<_>) { }
if ($in is TwoGenerics<_, _>) { }
if (is_a($in, $what)){ /*$in is still mixed here*/ }
}
hhast-migrate --instanceof-is can be used in
HHAST 4.13 to
automatically convert these expressions.
The old behavior of instanceof can also be disabled on 4.13 by setting
disable_instanceof_refinement=true in .hhconfig.
Fred Emmott
Posted July 09, 2019
HHVM 4.13 is released! This release marks the end of support for the 4.7.x series.
concurrent
statements.is and as expressions with wildcard generics
when not using repo-authoritative mode (~ 5x in some tests).hhvm.trust_autoloader_path option (defaults to false); if true, the
autoloader will not invoke realpath.if statements now refine the type in both the if block and
else block.zend_logo_guid(), zend_thread_id(), and zend_version() have been
removed.HH\global_get_safe() as it functioned identically to
HH\global_get().($foo ? $x = 1 : $x = 2), $x is an int. This is expected
to reduce the number of errors for safe code, but may raise new errors in
some situations.Shapes::keyExists($shape, 'field') now refines the type in the same way as
$shape is shape('field' => mixed, ...). This is expected to reduce the
number of errors for safe code, but may raise new errors in some situations.@sometype $foo to
<<__Soft>> sometype $foo; this new syntax is supported for experimental use.Fred Emmott
Posted July 01, 2019
HHVM 4.12 is released! This release marks the end of support for the 4.6.x series.
async keyword, e.g.
abstract methods and interfaces.<<__EntryPoint>> functions.hh_client --retries is now a synonym of --timeout&$output_headers argument has been removed from
SoapClient::__soapcall, as optional inout parameters are not supported.Fred Emmott
Posted June 24, 2019
HHVM 4.11 is released! This release marks the end of support for the 4.5.x series.
inst_meth()/class_meth() with
private or protected methods.curl 'http://localhost:8003/invalidate-units?path=/my/file.php&path=/my/other/file.php'inout instead of by-reference in the
HHIs; both inout and references continue to work at runtime.hh_client --extract-standalone, to create self-contained files
containing a function and all recursive dependencies.darray type and the HH\darray() function
(autoimported) is now required to be an arraykey.use() clause positioning is now a parser
error; Hack requires use() after the return type, while PHP7 has use()
before the return type.dict(), vec(), and keyset() are now in the HH\ namespace; they remain
autoimported, so this change only breaks fully-qualified references.Fred Emmott
Posted June 18, 2019
HHVM 4.10 is released! This release marks the end of support for the 4.4.x series.
($foo->bar)().<foo bar={await baz()}>{await foo()}</foo>.if: else: endif;) has
been removed; this was previously banned by the typechecker in hack files, but
supported at runtime.$x = &$y) are no longer supported by the parser.Fred Emmott
Posted June 13, 2019
HHVM 4.9.1 is released, fixing a performance regression on MacOS. There are no significant changes on other platforms.
We have added additional apt distributions to make it easier to update
to releases that are not the latest, but are still supported: for 4.3-4.9, we
have added DISTRIBUTION-MAJOR.MINOR apt distributions. For example, if your
/etc/apt/sources.list currently contains
deb https://dl.hhvm.com/ubuntu bionic main, you can replace bionic with
bionic-4.3, bionic-4.4 etc through to bionic-4.9.
Given all new releases have overlapping support, we are no longer handling
LTS releases specially in apt; for example, the 4.8 series is available through
bionic-4.8. We have not changed the distribution names for past releases, so
3.30 remains available through bionic-lts-3.30 instead of bionic-3.30.
We have also made similar changes to our MacOS bottles:
1
2
3
4
$ brew tap hhvm/hhvm
$ brew install hhvm # install the latest release
$ brew install hhvm-nightly # install the latest nightly build
$ brew install hhvm-4.8 # install the lastest 4.8.x
We have not renamed past releases, so 3.30 remains available as hhvm@3.30-lts
in homebrew.
Fred Emmott
Posted June 10, 2019
HHVM 4.9 is released! Additionally, 3.30.6, 4.3.1, 4.4.1, 4.5.1, 4.6.1, 4.7.1, and 4.8.1 are released with security updates. This release marks the end of support for the 4.3.x series.
In 4.9, it is no longer possible to enable PHP support, and various conditional behaviors have been unified, especially in the parser. For example, the lexer no longer special-cases PHP files for different behavior.
Additionally, the mysqli extension has been removed in favor of Hack’s
async MySQL extension. Users of the mysqli extension may find it useful to use
the 4.8 release while migrating, which is an LTS release.
localhost by default. This
behavior can be controlled by the hhvm.server.ip INI setting. The HTTP
server mode (Proxygen) continues to listen on all interfaces by default.scrypt_enc(); heap corruption was possible
if the scrypt parameters (N, r, and p) were configurable by an attacker - for
example, by providing the output of scrypt_enc() in a context where Hack/PHP
code would attempt to verify it by re-running scrypt_enc() with the same
parameters. This has been resolved by changing scrypt_enc() to use
libsodium’s implementation, and scrypt_enc() now requires that HHVM was
built with libsodium support. In 4.9, we consider scrypt_enc() deprecated,
and it will be removed in a future release.this type is now enforced at runtime by default; this behavior can
currently be controlled via the hhvm.this_type_hint_level INI setting:
4.9 defaults to 3, and prior release default to 0..php file, it must start with <?hh`; the
previous behavior of outputting leading content verbatim has been removed.$a = 'a'; ++$a) now
raises a notice.array_fill_keys() will now raise an error if used with non-arraykey keys;
array_fill_keys() has different coercion rules than actual array access,
which can lead to subtle bugs.hhvm.server.allow_duplicate_cookies INI setting.array_multisort() is now limited to 9 arguments, to allow the removal of
byref-variadics from the runtime.type_structure(), various Xenon functions, and ASIO monitoring functions
are now in the HH namespaces; these functions are autoimported in both
4.9 and prior versions, so the leading backslash can be removed.hhvm.force_hh INI setting now defaults to true; as all files are now
handled as Hack files, this only controls some smaller behaviors which are
not to PHP vs Hack:
json_encode() now returns false if used for an unsupported typeJSON_PARTIAL_OUTPUT_ON_ERROR is set, json_encode() will use null
to represent unsupported types.shell_exec() returns "" instead of null on failure-0.0 is now "0" instead of "-0"scrypt_enc() will be removed in a future release.hhvm.force_hh INI setting will be removed in a future release.scrypt_enc()We recommend migrating password storage to:
sodium_crypto_pwhash_str()sodium_crypto_pwhash_str_verify()sodium_crypto_pwhash_str_needs_rehash()For migration purposes, it is possible to verify scrypt_enc() hashes using
the sodium extension:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function verify_scrypt_enc(string $password, string $stored): bool {
list($_, $algo, $n, $r, $p, $salt, $stored_hash) = Str\split($stored, '$');
invariant($algo === 's', 'did not get an scrypt result');
$salt = \base64_decode($salt);
$stored_hash = \base64_decode($stored_hash);
$opslimit = (1 << $n) * $r * $p * 4;
$memlimit = (1 << $n) * $r * 128;
$password_hash = sodium_crypto_pwhash_scryptsalsa208sha256(
Str\length($stored_hash),
$password,
$salt,
$opslimit,
$memlimit,
);
return \hash_equals($password_hash, $stored_hash);
}
Fred Emmott
Posted June 03, 2019
HHVM 4.8 is released! This release has long term support, so:
@lateinit, to indicate that an attribute
is required, but may be set via ->setAttribute(). This is currently
equivalent to @required, however if the check_xhp_attribute option is set
in .hhconfig, an error is raised if a @required attribute is ommitted at
instantiation; for example, class :a { attribute string b @required; } <a />
will raise a typechecker error because of b not being specified, however
class :c { attribute string d @lateinit; } <c /> will raise a runtime error
if ->setAttribute('d', 'someValue') is not called before render, but will
not raise a typechecker error. This new behavior will not be optional in a
future release..hhconfig options disable_unsafe_expr and disable_unsafe_block are
now supported, removing support for // UNSAFE and /* UNSAFE_EXPR */; we
recommend using hhast-migrate --add-fixmes then using sed or similar to
remove the UNSAFE and UNSAFE_EXPR comments. This behavior will not be
optional in a future release.Ref<T> class,
to wrap values in objects.false; for example, $x = null; if ($x) { /* ... */ }.and, or, and xor operators have been removed from the runtime; they
previously raised typechecker errors. Use $a && $b, $a || $b, or
(bool) $a !== (bool) $b instead.is or instanceof with generics;
this may lead to the typechecker raising errors in more places.Fred Emmott
Posted May 28, 2019
HHVM 4.7 is released! This release will be supported for 6 weeks, and HHVM 4.2+ remain supported. This release marks the end of support for HHVM 4.1.
\HH\global_keys() and \HH\global_key_exists(); in these can be used
in combination with \HH\global_get() and \HH\global_set() as a replacement
for $_GLOBALS; these are currently undocumented, and we aim to resolve this
shortly.HH\rqtrace namespaceDOMDocument::createAttributeNSdeclare() and enddeclare() are no longer supportedTa::Tb if Ta is nullable.empty() is no longer supported; hhast-migrate --empty-expression can be
used to replace empty($expr) with (!$expr ?? false) in HHAST 4.6.1 under
HHVM 4.6Fred Emmott
Posted May 21, 2019
HHVM 4.6 is released! This release will be supported for 6 weeks, and HHVM 4.1+ remain supported.
await is now supported in many expressions.concurrent {} blocks as a more readable replacement for
HH\Lib\Tuple\from_async() and \HH\Asio\va().hh_client --file-dependents foo.hack [bar.hack ...] to provide a list
of files that are known to dependent on the specified files.Shapes::idx() and Shapes::at()$c has type errors, do not raise additional errors for $c::f(), to
reduce noise.hackfmt now provides information on the problem if it encounters a parse
error.json_decode() when string
keys are already present as literals in the source code.type_structure()await-as-an-expressionFor example, $sum = await x() + await y(); is now valid Hack; for details, see
the documentation.
concurrentConcurrent blocks provide a more readable alternative to
HH\Lib\Tuple\from_async() and HH\Asio\va(); we expect these functions to be
removed in a future release of HHVM and the HSL.
1
2
3
4
5
6
7
// Old style:
list($x, $y) = await Tuple\from_async(foo(), bar());
// New style:
concurrent {
$x = await foo();
$y = await bar();
}
For details, see the documentation.
await as an expression, the precedence has changed.
hhast-migrate --await-precedence can be used with HHVM 4.5 and HHAST 4.5 to
parenthesize affected expresisons.sscanf() and fscanf().(real) cast has been removed; use (float) instead.func_num_args() is no longer supported; use variadics instead.class Foo { function Foo() {} }) are no longer
supported. Use function __construct() {} instead.hh_parse encounters errors, it will now report them and exit non-0,
unless another behavior is specified with CLI arguments.Fred Emmott
Posted May 13, 2019
HHVM 4.5 is released! This release will be supported for 6 weeks, and HHVM 4.1+ remain supported.
This weeks’s release is focused on performance improvements and increased consistency between typechecker and runtime errors.
Shapes::at(), which is similar to Shapes::idx(), but throws if the
field is not set. This is useful for optional fields.$foo->$bar()) and property access ($foo->$bar)
now raise a typechecker error unless $foo is dynamic.$foo->someStaticMethod()). This was previously a typechecker
error.UNSAFE, UNSAFE_BLOCK, and UNSAFE_EXPR
comments in a future release, in favor of more explicit HH_FIXME[code]
comments and future language features. The behavior of UNSAFE comments
can be disabled with the disable_unsafe_expr and disable_unsafe_block
options in .hhconfigHSL-Experimental 4.5.0 adds advanced async helper classes, including
Async\Poll and Async\Semaphore among others. We strongly recommend
avoiding Async\Poll when alternatives exist.
For details, see the release notes.
Fred Emmott
Posted May 06, 2019
HHVM 4.4 is released! This release will be supported for 6 weeks, and HHVM 4.1+ remain supported.
This weeks’ work was mostly performance improvements, bug fixes, and work on future features.
hh_server --config, allowing overriding hhconfig options
via the CLI__callStatic() is no longer supported; if manual analysis is not practical
for migration, we recommend adding logging wrappers while using a previous
version of HHVM.ext_session and the $_SESSION superglobal have been removedhhvm.jit_profile_interp_requests option has been removed, as it no
has any effectFred Emmott
Posted April 30, 2019
HHVM 4.3 is released! This release will be supported for 6 weeks, and HHVM 4.1+ remain supported.
__LateInit in repo-authoritative modeparent:: now includes instance methods, not just static
methodsisset() usagehhvm.warn_on_coerce_builtin_params INI setting<> operator; this can be replaced with !=, and is supported
by hhast-migrate --hhvm-4.2-to-4.3 or hhast-migrate --ltgt-to-neparent::__construct() is called with
parameters that violate where constraintshhvm.forbid_division_by_zero ini setting.ext_sessionhhvm.jit_profile_interp_requests INI setting as other changes
made it unuseddisable_optional_and_unknown_shape_fields experimental hhconfig
option from 3.23.Fred Emmott
Posted April 23, 2019
HHVM 4.2 is released! This release will be supported for 6 weeks, and HHVM 4.1 remains supported.
This is the first release on an accelerated schedule; we now aim to make new releases every monday, each supported for 6 weeks. There is no planned change to the LTS cycle.
4.1’s release branch was cut in late March, so 4.2 contains approximately a month’s changes; 4.2 and future releases do not have the same branch cut system, so 4.3 and above should be expected to contain approximately one weeks’ changes.
statcache-clear admin server commandCURLPROXY_HTTPS constant--error-format=raw for scripting/automation$x is MyAbstractFinalClass now raises a typechecker error, as it is
impossible for any $x to be an instance of an uninstantiable classget_class()settype() function has been removedhhvm.enable_intish_cast=0 option.<<__UNSAFE_Construct>> has been removed.if) to be lowercase; this
was previously only required by the typechecker.filter_has_var(), filter_input(), and filter_input_array() have been
removed.$GLOBALS will result in a runtime error.Memcached::get() and
Memcached::getbykey()inout parameters.array-like kinds are now valid Keyed{Traversable,Container} (without
generics).$x['foo'] ?? $bar where $x['foo'] is not a valid
field.make hack_test now runs Hack’s tests; previously it built various test
utilities, but did not run the tests.hhvm.hard_type_hints option has been removed; type-hint violations now
always raise runtime errors, unless they are explicit soft type hints. This
option was primarily useful for enabling stricter enforcement of parameter
types for PHP5 code.hackfmt’s handling of empty function bodies (e.g. HHI definitions).
This does not affect abstract or interface methods.instanceof will be removed, in favor of the is and as operators. It
can be disabled with the disable_instanceof=true .hhconfig and
hhvm.hack.lang.phpism.disable_instanceof HHVM INI settings.Fred Emmott
Posted April 09, 2019
HHVM 4.1 is released! This release will be supported for 8 weeks; we aim to start publishing weekly releases shortly, however this will not change the lifecycle for HHVM 4.1.
null type; this allows $foo is null as an alternative
to $foo === null, consistent with $foo is nonnull.nothing (bottom/empty) type..hh and .hack files are now supported in repo-authoritiative mode. We
recommend using .hack files..hack filesdisable_unsafe_block .hhconfig option to ban // UNSAFEReflectionProperty::getAttribute() and ::getAttributes() are now supportedinout parameters are now supported in async
functionsThese changes are mostly working towards removing references from the language,
and removing support for functions that can inspect or modify the caller, such
as compact() or extract()
<?hh is no longer valid by itself; replace with <?hh // partial;
hhast-migrate --explicit-partial-mode can be used for this change.assume_php .hhconfig option has been removed; it is always false.global statements (e.g. global $foo) are no longer supporteddisallow_array_cell_pass_by_ref and disallow_assign_by_ref options
have been removed; these behaviors are now errors&$_SERVER or &$GLOBALS['foo']function () use (&$foo) {})
are no longer supportedis_array(), is_object() and similar functions are no longer auto-imported
to every namespace; use hhast-migrate --no-namespace-fallback$$foo) are no longer supported in the runtime.get_magic_quotes_gpc(), get_magic_quotes_runtime(), and
set_magic_quotes_runtime() have been removed.hhvm.enable_zend_sorting option has been removed; when the sort order
was undefined, this option would make HHVM match PHP5’s behavior, but this
would use a slower algorithm.phpt (PHP template) files are no longer supported in repo-authoritative
mode.forward_static_call() now raises an errordefine() has been removedwhere constraintsthis:: is no longer used in is or as constraints at generics make it
unsafestdClass is now final__PHP_Incomplete_Class is now final, does not typecheck, and is no longer
directly instantiablefunc_get_args(), func_get_arg(), and func_num_args() have been removed.get_defined_vars() has been removedget_called_class() has been removedKeyedContainer keys must now be arraykey; this affects Map, ImmMap,
Set, and ImmSet.$php_errormsg or $http_response_header are no longer
specialarray_keys() now only takes one argumentphar extension has been removed, as HHVM does not support building
phars and was no longer able to execute PHP phars.Closure::bindTo and Closure::call have been removed; these were already
typechecker errorsrecord is a reserved word in preparation for a new data structure type.<?php now raises a runtime error; while PHP is no longer supported by HHVM,
it is still possible to allow the <?php tag by setting the
hhvm.enable_php=true INI setting.
We disabled it by default as executing PHP files with HHVM 4 tends to give confusing and misleading error messages due to changes around references; disabling support allows a much clearer error message to be provided.
The parser no longer understands markup sections; they are both typechecker
and runtime errors. Relatedly, ?> is no longer recognized.
1
2
3
4
5
This is a leading markup section
<?php
// foo
?>
This is a markup section, but not a leading markup section
Shebang lines (e.g. #!/usr/bin/env hhvm) are still permitted as the first
line of a file.
<?hh will imply strict mode, instead of being an errorfilter_input() and filter_array() will be removed in a future release$_SESSION will be removed in a future releasedeclare() will be removed in a future releasedisable_static_local_variables=true option in .hhconfighhvm.hard_type_hints option will be removed; type hints will always
be enforced (this has been the default behavior for some time).hhvm.hack.lang.phpism.disable_static_closures INI setting can be used to
disable support in 4.0hackificator, augmented_types, remove_soft_types, and
compare_coverage.py as they have been unmaintained for some time.disallow_byref_dynamic_calls .hhconfig
optionStatic local variables will no longer be supported - for example:
1
2
3
4
function foo(): void {
static $foo = null;
// ...
}
There are several approaches for replacing them:
<<__Memoize>> or <<__MemoizeLSB>>self:: or static::
is used correctly; the behavior of static local variables dependeded on the
caller, so this could not be inferred.If the function is potentially recursive, you may need to copy the property into a local, so that deeper calls do not affect the value in their callers.
The hhvm.check_prop_type_hints INI setting can be used to enable runtime
enforcement of property types. This enables additional optimizations.
Valid values are:
We expect property type enforcement to be mandatory in a future version.
Fred Emmott
Posted April 03, 2019
These releases address CVE-2019-3561; it was previously possible to read
unintended memory locations if invalid offsets were passed to strrpos.
Additionally, 3.30.5 makes it possible to configure hackfmt behavior via
.hhconfig, such as:
hackfmt.add_trailing_commashackfmt.indent_widthhackfmt.tabshackfmt.line_widthThese options were already supported in 4.0.
Fred Emmott
Posted February 28, 2019
This release is fixes some IDE features in .hack files, especially in
.hack files which contain the string <?hh such as code generators.
Unfortunately, fixing this required breaking the same IDE features for PHP
files that contain leading markup (content before the <?) - for example:
1
2
3
4
5
6
<html>
<head>
<title><?php echo htmlspecialchars(get_page_title(); ?></title>
</head>
...
</html>
Files that start with <? or a shebang line (e.g. #!/usr/bin/env hhvm)
immediately followed by <? at the start of the second line are not affected.
Additionally, our MacOS packages have been rebuilt to workaround some incompatibilities with recent versinos of dependencies, and to require Sandybridge-or-newer processors. Requiring Sandybridge provides a 19x speedup over Homebrew’s defaults for some real-world workloads.
Fred Emmott
Posted February 19, 2019
HHVM 4.0.2 is released! This release:
.hhconfig default_mode option being
inconsistently applied.hack files as HTTP request entrypoints by default; previously,
the hhvm.php_file.extensions[hack]=1 INI setting was required.Fred Emmott
Posted February 14, 2019
HHVM 4.0.1, 3.30.4, and 3.27.7 are released; these issues fix CVE-2019-3552, a potential denial of service if Thrift is used to process untrusted input.
Fred Emmott
Posted February 11, 2019
HHVM 4.0 is released! This release adds support for .hack files, non-experimental support for HSL regular expressions, and removes several PHP behaviors.
With this release, we no longer aim to be compatible with PHP. While this release does not ban <?php and similar tags, various changes make HHVM unable to execute most PHP projects. PHP-incompatible changes in this release mostly fit in to one of three goals:
compact(), extract(), get_declared_variables(), func_get_args(), or parse_str() with a single argument.We are considering removing support for <?php in the next release: the primary benefit would be a clearer error message (such as “HHVM no longer supports PHP code”) rather than more-specific messages such as parse errors which may be less useful. We welcome feedback on this via IRC, Facebook, or Twitter.
HHVM is no longer able to execute Composer; Composer 1.8.4 includes support for identifying the HHVM version when executing via PHP, which is how we currently recommend installing dependencies for Hack projects.
We are currently working to move to a package manager that fully supports multiple languages.
HHVM 4.1 will be released and supported following the current release schedule (i.e. released in 8 weeks, and then supported for 8 weeks). 4.2 will be released 1 week later, and mark the start of a weekly release schedule.
Each weekly release will receive security support for 6 weeks, and we are keeping the current long-term-release cycle: every 24 weeks, a release is made that will be supported for 48 weeks. This means that there will be up to 8 releases concurrently supported.
We recommend updating weekly, but holding back if a release is particularly painful. We decided on 6 weeks to also make monthly upgrades a workable option.
.hack File ExtensionWe now recommend using the .hack file extension if your editor/IDE support it; files with this extension are always strict, and do not require or allow a <? header line. For example, this is a complete .hack file:
1
2
3
4
5
6
7
#!/usr/bin/env hhvm
<<__EntryPoint>>
function main(): noreturn {
print("Hello, world!\n");
exit(0);
}
Other extensions such as .php and .hh remain supported, and require the <?hh header. We recommend only using these temporarily, for existing code - not for new projects.
It’s important to note that this means that HHVM will attempt to execute any .hack files that users can request, even if they do not include ‘<?’.
The HH\Lib\Regex namespace is no longer part of hsl-experimental, and is now part of the main HSL project. The 3.28.2 release notes provide an overview of this feature.
<% %>) are no longer supportedtoken_get_all(), token_name(), php_strip_whitespace(), show_source(), highlight_file(), and highlight_string(); these functions have been unable to fully handle Hack code since 3.27.create_function() has been removed; use lambdas or closures instead.foreach. For manual iteration, ->next() must be called before accessing the values.& at the callsite. This was previously a typechecker error, and is now also a runtime error.$$foo) are no longer supportedparse_str() now requires two argumentsassert() will no longer evaluate string argumentsextract() has been removedcompact() has been removed.hack files, specifying a mode will be required; for example, <?hh // strict will remain valid, but <?hh by itself will not. We recommend moving to .hack files if possible, otherwise <?hh // strict. If neither is immediately practical, <?hh can be replaced with <?hh // partial. You can enable this behavior with the “default_mode=error” .hhconfig option.if statements. In 4.0, you can disable support via the hhvm.hack.lang.phpism.disable_nontoplevel_declarations INI setting.await will be changing, to allow await to be used as an expression. You can enable the new precedence with the hhvm.hack.lang.enable_stronger_await_binding=true INI setting - in problematic cases, this will lead to await being parsed as an expression, which will currently raise an error. We expect this to mostly affect await statements using the ternary operator, such as await $foo ? $bar : $baz; currently, this is parsed as await ($foo ? $bar : $baz), but in future releases it will be parsed as (await $foo) ? $bar : $baz. hhast-migrate --await-precedence can be used to add parentheses automatically.hhvm.enable_zend_sorting option will be removed. This option makes HHVM use a slower, PHP-compatible sorting algorithm, which has different behavior in edge cases such as when elements compare as equal.$x =& $y) will be removed. The disallow_assign_by_ref typechecker option can be used to opt-in to this behavior now.some_function(&$_GET)global keyword will be removed, e.g. function foo() { global $bar; }function f() { static $foo = 42; return ++$foo; }); we plan to provide an optional ban in 4.1func_num_args, func_get_args, and func_get_arg will be removed in 4.1. Use variadics instead.get_defined_vars() will be removedget_class() will require an argument.get_called_class() will be removed.get_class_vars() will be removed.hhvm.warn_on_coerce_builtin_params INI setting.array_map([$this, 'privateFunc'], $arr) will fail as array_map is not part of the class.class T<T> {} will be invalid.hhvm.hack_arr_compat_notices option and the associated notice options listed below:
hhvm.hack_arr_compat_check_intish_cast to raise notices.hhvm.hack_arr_compat_check_ref_bind to raise notices.null, false, or uninitialized variables will not be able to be treated as arrays. Set hhvm.hack_arr_compat_check_falsey_promote to raise notices.hhvm.hack_arr_compat_check_empty_string_promote to raise notices.hhvm.hack_arr_compat_check_compare will raise notices for ordering comparisons between arrays and non-arrays (scalars and objects) and for equality comparisons between arrays and Hack arrays. For example, [] > 3 or [] === vec[]arraykey values will not be able to be used as array keys and will not be automatically coerced. Set hhvm.hack_arr_compat_check_array_key_cast to raise notices. For example, false will no longer be converted to 0, null will not be converted to "", and 1.23 will no longer be automatically converted to 1 or "1.23" depending on the context.+) operator. Set hhvm.hack_arr_compat_check_array_plus to raise notices.Additionally, several ‘future changes’ that were announced with 3.30 are still planned:
int + int to be int, instead of int + int = num. This behavior can be enabled with the hhvm.hack.lang.ints_overflow_to_ints INI settinguse() parameters. This restriction can be enabled in the typechecker by adding the disallow_anon_use_capture_by_ref .hhconfig optiongoto will no longer be supported in Hack files. This restriction can be enabled in the type-checker by adding the disallow_goto.hhconfig optionhhvm.hack.lang.phpism.undefined_const_fallback)hhvm.hack.lang.phpism.undefined_const_as_string)$php_errormsg or $http_response_header will no longer be special (hhvm.hack.lang.phpism.disable_reserved_variables)hhvm.fatal_on_convert_object_to_string); this includes removal of support for __toString()hhvm.notice_on_array_access_use is enabled)constant(): hhvm.hack.lang.phpism.disable_constantdefine(): hhvm.hack.lang.phpism.disable_defineforward_static_call(): hhvm.hack.lang.phpism.disable_forward_static_callforward_static_call_array(): hhvm.hack.lang.phpism.disable_forward_static_call_arraycall_user_func(): hhvm.hack.lang.phpism.disable_call_user_funccall_user_func_array(): hhvm.hack.lang.phpism.disable_call_user_func_arrayFred Emmott
Posted February 01, 2019
HHVM 3.30.3 is released; this release contains several bugfixes:
# comments in IDE integration - previously these would be
rendered as markdown headings.Fred Emmott
Posted January 14, 2019
HHVM 3.30.2 and 3.27.6 are released; these releases address:
number_format() error casesstream_get_line() and bz2 readsHH\Asio\curl_exec() which was introduced in
3.30.0Fred Emmott
Posted December 18, 2018
HHVM 3.30.1 and 3.27.5 are released; these releases address CVE-2018-6340, a stack read overflow in Memcache::getExtendedStats(). Exploiting this requires control over memcached server hostnames and/or ports.
Additionally:
Fred Emmott
Posted December 17, 2018
HHVM 3.30 is released! This release has long term support, ending in November 2019.
This release is the final release where we aim to support PHP code, and as such, contains several opt-in changes that break compatibility; as well as the specific options below (which we expect to remove during the next few releases), a hhvm.enable_php=false option is available, which disables support for files that begin with <?php. We do not anticipate removing this option in the immediate future - the primary purpose is to enable testing to make sure that Hack projects do not have hidden PHP dependencies.
C\first, C\first_key, C\last, and C\last_key on containers$shape->foo now suggests $shape['foo']is_int() and similar can no longer be used to refine primitive types. Use is int etc instead (hhast-migrate --is-refinement applies this change)<<__Entrypoint>> attribute is now <<__EntryPoint>>; we consider the syntax stable, however the required function signature is not yet final. We recommend using function(): noreturn or function(): Awaitable<noreturn> for now, to provide the greatest compatibility for potential future changesTraversables; this is not a safe/meaningful test given that generators are Traversablesints will wrap in future releases, instead of being converted to floats, allowing the type of int + int to be int, instead of int + int = num. This behavior can be enabled with the hhvm.hack.lang.ints_overflow_to_ints INI setting
Generators will no longer auto-prime; they should ideally be accessed via foreach. For manual iteration, ->next() must be called before accessing the values. This behavior can be enabled with the hhvm.hack.lang.autoprime_generators INI setting
hhvm.disable_return_by_reference=1 INI settinghhvm.throw_on_call_by_ref_annotation_mismatch=1 INI settinguse() parameters. This restriction can be enabled in the typechecker by adding the disallow_anon_use_capture_by_ref .hhconfig optiongoto will no longer be supported in Hack files. This restriction can be enabled in the type-checker by adding the disallow_goto .hhconfig option$$foo) will be removed (hhvm.hack.lang.phpism.disable_variable_variables)hhvm.hack.lang.phpism.undefined_const_fallback)hhvm.hack.lang.phpism.undefined_const_as_string)parse_str() will require multiple arguments (hhvm.hack.lang.phpism.disable_parse_str_single_arg)hhvm.hack.lang.phpism.disable_execution_operator)$php_errormsg or $http_response_header will no longer be special (hhvm.hack.lang.phpism.disable_reserved_variables)hhvm.fatal_on_convert_object_to_string); this includes removal of support for __toString()ArrayAccess on non-builtin types (hhvm.notice_on_array_access_use)assert(): hhvm.hack.lang.phpism.disable_assertdefine(): hhvm.hack.lang.phpism.disable_defineconstant(): hhvm.hack.lang.phpism.disable_constantcompact(): hhvm.hack.lang.phpism.disable_compactextract(): hhvm.hack.lang.phpism.disable_extractforward_static_call(): hhvm.hack.lang.phpism.disable_forward_static_callforward_static_call_array(): hhvm.hack.lang.phpism.disable_forward_static_call_arraycall_user_func(): hhvm.hack.lang.phpism.disable_call_user_funccall_user_func_array(): hhvm.hack.lang.phpism.disable_call_user_func_arrayFred Emmott
Posted October 30, 2018
HHVM 3.29.1 and 3.27.4 are released! These releases contain bugfixes and improvements:
inout parameters$PATH includes spacesinout parametersstream_await() on FDs when using CLI server (included in 3.29.0)stream_await() will throw an InvalidOperationException if called on an unawaitable file descriptor. This includes actual on-disk files on Linux, as they are not supported by epoll. We recommend that callers attempt to stream_await(), and handle this exception if neccessary. The stream metadata can not be used to identify whether or not a stream is awaitable - for example, hhvm foo.php has an awaitable STDIN, but hhvm foo.php < myfile has an awaitable STDIN on MacOS (kqueue) but not on Linux (epoll). In prior releases, behavior varied; the most common result was writing an error to STDOUT, and the awaitable not resolving, with request timeout eventually being reached (included in 3.29.0).The last issue is technically a BC break; we have included it in this release as the usual behavior without that patch is to hang forever; throwing immediately seems likely to be an improvement in the vast majority of cases.
Fred Emmott
Posted October 22, 2018
HHVM 3.29 is released! This release has a large amount of changes in the typechecker; these mostly are now raising type errors for situations that already failed at runtime, or banning rare cases that make the type system unsound.
new is valid, NEW is not)class true {} is not valid$x = vec[]; $x[] = 'a string'; now gets you a vec<string>Throwable class is now sealed to the Exception and Error classesawait in pseudomains?-> operator. Previously a runtime error.::class on the RHS of instanceof expressions; uneeded.await in non-async lambdas. Previously a runtime error.Containers or SimpleXMLElementsabstract final classes) as shape field typescase statements that are after a default statement(object) cast (convert to stdClass) in strict mode<> operator in Hack -the equivalent != operator is still available- migration included in HHAST: hhast-migrate --ltgt-to-neShapes::toDict(), in the same way as Shapes::toArray() - for example, if all the fields are strings, you can get a dict<string, string>/e modifier (eval) for preg_replace(). Deprecated in PHP 5.5, removed from 7.0. Use preg_replace_callback() instead.stream_await() will throw an InvalidOperationException if called on an unawaitable file descriptor. This includes actual on-disk files on Linux, as they are not supported by epoll. We recommend that callers attempt to stream_await(), and handle this exception if neccessary. The stream metadata can not be used to identify whether or not a stream is awaitable - for example, hhvm foo.php has an awaitable STDIN, but hhvm foo.php < myfile has an awaitable STDIN on MacOS (kqueue) but not on Linux (epoll). In prior releases, behavior varied; the most common result was writing an error to STDOUT, and the awaitable not resolving, with request timeout eventually being reached.$$foo) in Hack code (previously required by the typechecker)// hackfmt-ignore comments, to turn off formatting for a nodeShapes::idx() results now refine the type of the shapeCurrently, <<Attributes>> are unchecked, except if they start with __ (indicating a builtin), and can contain any amount of static expressions of any type; it was possible to whitelist valid attribute names via user_attributes=foo,bar, but not to provide any additional checking.
We have addressed these problems by introducing typed user attributes, where attributes are represented by classes and objects; the parameters of an attribute must be valid for the class constructor, and the objects can be retrived via reflection.
For example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?hh // strict
namespace MyTestFramework {
final class DataProvider implements \HH\MethodAttribute {
public function __construct(public string $function) {
}
}
}
namespace MyThingBeingTested {
use type MyTestFramework\DataProvider;
final class MyTest extends MyTestFramework\TestCase {
<<DataProvider('provideFoo')>>
public function testFoo(): void {
}
<<DataProvider(123)>> // type error, not a string
public function testBar(): void {
}
<<DataProvider('foo', 'bar')>> // type error, too many arguments
public function testBaz(): void {
}
}
<<DataProvider('foo')>> // type error, can't use DataProvider on functions, only methods
function doStuff(): void {
}
}
Attributes can be retrieved via reflection:
1
2
3
4
<?hh
$rc = new ReflectionClass('C');
$my_attr = $rc->getAttributeClass(MyAttribute::class);
invariant($my_attr is MyAttribute, 'we get an instance of the class');
Attribute classes implement at least one of these interfaces:
ClassAttributeEnumAttributeTypeAliasAttributeFunctionAttributeMethodAttributeInstancePropertyAttributeStaticPropertyAttributeParameterAttributeIn 3.29, it is possible to declare attributes with this form, and if done, they were validated. In 3.30, declaring all attributes will be required, and it is possible to require this in 3.29 by setting an empty whitelist in .hhconfig:
1
user_attributes=
is expressions in pipe expressionsas expressions in list assignments, e.g. list($a, $b) = $mixed as (int, int);as expressions in foreach, e.g. foreach(f($x as nonnull) as $y)<<__LateInit>> now works correctly for private properties on abstract classesis_bool(), is_int() etc. This is currently opt-in via the disable_primitive_refinement .hhconfig optionuser_attributes= .hhconfig optionFred Emmott
Posted October 01, 2018
HHVM 3.28.3 is released, containing two bugfixes:
as expressions, e.g.
list($a, $b) = $foo as (int, int)Fred Emmott
Posted September 28, 2018
HHVM 3.28.2 contains bugfixes, and several features that weren’t quite ready for 3.28.0:
if statements in hackfmt<<__Entrypoint>>, removing the need for pseudo-mains.
Update: as of 3.30, this is now <<__EntryPoint>>This is a new attribute, marking a single function in a file as being the ‘main’ function for this file:
Update: as of 3.30, this attribute is now called <<__EntryPoint>>
1
2
3
4
5
6
7
8
9
10
11
12
<?hh // strict
<<__Entrypoint>>
function main(): noreturn {
exit(0);
}
// ... or ...
<<__Entrypoint>>
async function main(): Awaitable<noreturn> {
exit(0);
}
Entrypoint functions will be automatically executed if they are in the top-level file; they will not be automatically executed if the file is included via include, require, or the autoloader.
Like other functions in Hack, the function names must be unique within your project - i.e. projects with multiple entrypoints can not call both ‘main’.
noreturn or Awaitable<noreturn> in a future release, and we recommend using these types for now.$_GLOBALS['argv']; in a later release, we are likely to expose this via a function, possibly called HH\Request\argv(); we welcome feedback and suggestions for this APIThis feature is a combination of a new language feature, and new library functions; the library functions are currently in the hsl-experimental package, and we expect them to move to the main HSL package in a future release.
Regular expressions take advantage of a new Hack feature called prefix strings. Prefix strings allow the user to tag string literals, giving the typechecker more information.
In the Regex\ namespace, a regular expression is represented by the Pattern type instead of a string. A Pattern is obtained by using a re-prefixed string literal:
1
$pattern = re"/foo(bar)?/";
Now, the typechecker knows that the string is a regular expression! This means that it can warn us at typecheck time if we have written a malformed pattern:
1
2
3
4
5
$pattern = re"I am not a regular expression";
// ERROR: Bad regex pattern; Missing delimiter(s). (Typing[4275])
$pattern = re"/(no closing paren/";
// ERROR: Bad regex pattern; Missing ) [17]. (Typing[4275])
Furthermore, the Pattern type has a type parameter which represents the shape of a match (containing positional and named capture groups), and the Regex\ APIs return this shape. This means that the keys of the shape are also known at typecheck time:
1
2
3
4
5
6
7
8
9
10
11
12
13
use namespace HH\Lib\Regex;
$match = Regex\first_match(
$some_string,
re"/^(positional)and(?<named>foo)$/"
);
if ($match is nonnull) {
$match[0]; // OK, full matched string
$match[1]; // OK, first positional group
$match['named']; // OK, named group
$match['nonexistent']; // ERROR: The field nonexistent is undefined (Typing[4108])
}
If a capture group isn’t matched in the input string, the value for its key will be set to the empty string.
Regular expressions matches are supported by existing IDE features, such as type-on-hover and shape key autocomplete:

For the full API, see the source; it will join the main HSL documentation once the feature is no longer experimental.
For now, the prefix string is the only way to obtain a Pattern, meaning this library only works with statically known regular expressions. We will be introducing support for dynamic patterns soon.
The Regex\ namespace requires limited forms of two new Hack features: prefix strings and integer keys on shapes.
Thanks to Marcy Park for building this feature, and Christopher Chedeau, Fred Emmott, Robert Lynch, and Kunal Mehta for API design.
Fred Emmott
Posted September 26, 2018
As HHVM moves away from PHP, Hack projects need to be able to move away from PHP dependencies; the most common dependency is PHPUnit, by a large margin. As such, we are releasing HackTest (a framework for declaring and running unit tests) and retargetting fbexpect (an expressive assertion library) to be a supported library for non-Facebook users.
These libraries provide a slightly different API to PHPUnit:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<?hh // strict
use type Facebook\HackTest\HackTest;
use function Facebook\FBExpect\expect;
final class MyTest extends HackTest {
<<__Override>>
public static async function beforeFirstTestAsync(): Awaitable<void> {
// this can be used to emulate setUpBeforeClass()
}
<<__Override>>
public async function beforeEachTestAsync(): Awaitable<void> {
// this can be used to emulate setUp()
}
<<__Override>>
public async function afterEachTestAsync(): Awaitable<void> {
// this can be used to emulate tearDown()
}
<<__Override>>
public static async function afterLastTestAsync(): Awaitable<void> {
// this can be used to emulate tearDownAfterClass()
}
public function testFoo(): void {
// replaces $this->assertSame('bar', foo());
expect(foo())->toBeSame('bar');
}
public function provideBars(): vec<(string, int)> {
return vec[
tuple('foo', 123),
tuple('bar', 456),
];
}
<<DataProvider('provideBars')>> // replaces @dataProvider doccomment
// tests can be async
public async function testBar(string $a, int $_b): Awaitable<void> {
$s = await get_message_async();
// replaces @expectException and setExpectedException()
expect(() ==> {
throw new \Exception($s);
)->toThrow(\Exception::class);
}
}
To make moving from PHPUnit to HackTest practical, we have extended HHAST to automate the required code changes - though the composer changes must be made separately.
We start with a Hack project that uses PHPUnit:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
myproject$ hhvm vendor/bin/phpunit tests/
PHPUnit 5.7.27 by Sebastian Bergmann and contributors.
............................................................. 61 / 1309 ( 4%)
............................................................. 122 / 1309 ( 9%)
............................................................. 183 / 1309 ( 13%)
............................................................. 244 / 1309 ( 18%)
............................................................. 305 / 1309 ( 23%)
............................................................. 366 / 1309 ( 27%)
............................................................. 427 / 1309 ( 32%)
............................................................. 488 / 1309 ( 37%)
............................................................. 549 / 1309 ( 41%)
............................................................. 610 / 1309 ( 46%)
............................................................. 671 / 1309 ( 51%)
............................................................. 732 / 1309 ( 55%)
............................................................. 793 / 1309 ( 60%)
............................................................. 854 / 1309 ( 65%)
............................................................. 915 / 1309 ( 69%)
............................................................. 976 / 1309 ( 74%)
............................................................. 1037 / 1309 ( 79%)
............................................................. 1098 / 1309 ( 83%)
............................................................. 1159 / 1309 ( 88%)
............................................................. 1220 / 1309 ( 93%)
............................................................. 1281 / 1309 ( 97%)
............................ 1309 / 1309 (100%)
Time: 13.95 seconds, Memory: 41.69MB
OK (1309 tests, 1310 assertions)
Then, we need to swap out the composer dependencies from PHPUnit to HackTest and FBExpect
1
2
3
4
myproject$ hhvm ~/composer.phar remove --dev phpunit/phpunit 91carriage/phpunit-hhi
...
myproject$ hhvm ~/composer.phar require --dev hhvm/hacktest facebook/fbexpect
...
Then we migrate the tests with HHAST, and run them with HackTest instead of PHPUnit:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
myproject$ hhvm ~/code/hhast/bin/hhast-migrate --phpunit-to-hacktest tests/
myproject$ hhvm vendor/bin/hacktest tests/
...............................................................................
...............................................................................
...............................................................................
...............................................................................
...............................................................................
...............................................................................
...............................................................................
...............................................................................
...............................................................................
...............................................................................
...............................................................................
...............................................................................
...............................................................................
...............................................................................
...............................................................................
...............................................................................
.............................................
Summary: 1309 test(s), 1309 passed, 0 failed, 0 skipped, 0 error(s).
Finally, you might need to update your CI systems (such as TravisCI or CircleCI) to use HackTest instead of PHPUnit.
If you find cases that HHAST does not migrate correctly, we welcome GitHub issues and pull requests against the HHAST project.
Thanks to Wilson Lin, Robert Lynch, and Kunal Mehta for their work on these projects.
Fred Emmott
Posted September 12, 2018
HHVM v3.30 will be the last release series where HHVM aims to support PHP. The key dates are:
Ultimately, we recommend that projects either migrate entirely to the Hack language, or entirely to PHP7 and the PHP runtime.
We expect support for real-world PHP code to break rapidly: for example, we are likely to replace reference parameters (&$foo) to builtins with inout parameters, make INT64_MAX + 1 === INT64_MIN (instead of a float), among other changes. In the short term, we expect it to be fairly straightforward to migrate code to deal with these changes, but this will require that any dependencies written in PHP are either forked and migrated to Hack, or migrated away from.
We’re extremely grateful to the users and developers of PHP, and are glad to have been part of those communities.
We are proud of Hack, but there are still many areas where we want to make major improvements to the language; during the next 2-3 years, we will be working towards making Hack a language that builds on the best parts of its’ heritage to produce:
During these 2-3 years, aggressive growth of our user base is not a primary goal: we want most people’s first exposure to Hack to be the improved language that we are working towards. However, we will be increasing our investment in Hack/HHVM open source, to continue to support our existing users, and aim to build a community ready to support growth in the future.
As we expect the language to evolve rapidly, we strongly recommend using the regular releases instead of the LTS releases for large projects; while this does mean you need to upgrade more often, both us and our users have found that it is generally easier to catch up on 2 months worth of changes 3 times as often than 6 months of changes in one go. We will also be re-evaluating the length of our release cycle; one possibility is that we will move to releases every 4 weeks, with these releases being supported for 6-8 weeks.
For this time period, most of Facebook’s Hack libraries and tools on GitHub will only target the latest release, not LTS versions; branches and fixes will be made as-needed, but these branches will be community supported, except for security issues reported via Facebook’s Whitehat Program.
The priorities of the Hack/HHVM open source team are to support our existing users, and to reduce the pain of the removal of PHP support. This will involve creating additional projects, and polishing several existing projects to reach a state suitable for v1.x.
Currently, plans include:
We hope to help the community build what is needed; please get in contact via Facebook, Reddit, Twitter, or in #hhvm on irc.freenode.net.
In 2019, we expect this work to continue and expand in scope, and to provide more automated migrations to update code to deal with language changes.
Fred Emmott
Posted August 30, 2018
HHVM 3.28.1 is released! This release fixes a segmentation fault when talking to recent MySQL server implementations.
Kunal Mehta
Posted August 28, 2018
HHVM 3.28 is released! This release contains new language features, bugfixes, performance improvements, and improvements to the debugger and editor/IDE support.
is and as expressions for type refinement, providing a consistent alternative to the is_*() functions and instanceofconst type TMyVec<T as Foo> = vec<T><<__MemoizeLSB>> attribute: this is like <<__Memoize>>, but the cache has Late Static Binding: subclasses have their own memoize cache<<__LateInit>> attribute: this marks a property as being initialized via a non-standard mechanism, i.e. not via standard assignment in the constructor. Reading uninitialized <<__LateInit>> properties is a runtime errorThe experimental <<__MemoizeLSB>> and <<__LateInit>> attributes have not been tested as thoroughly as other features, and are more likely to have correctness or stability issues, or to require BC-breaking changes in the near future.
Language-level restrictions here only apply to Hack code, not PHP.
hh_file_parse, hh_format, and format_hack tools; these are replaced by hh_parse and hackfmtsealed_classes option in 3.27)Traversable and KeyedTraversable are now sealed, and do not allow direct user subclasses; you most likely want to extend Iterator or KeyedIterator insteadRescheduleWaitHandle, SleepWaitHandle, StaticWaitHandle etc) are now sealed.$$ and $this can no longer be passed by reference in Hack codenew Foo()->bar()) is a parse error again; support was unintentionally added in HackC, but not wanted as it is ambiguous: (new Foo())->bar() vs new (Foo()->bar()) where Foo()->bar() could return a classname<T>? and : in the ?: operator (disallow_elvis_space in 3.27)Set is now a KeyedIterator<arraykey, Tv> instead of KeyedIterator<mixed, Tv>dict keys are now constrained to arraykey - this was previously a runtime requirement, but not reported by the typechecker?enum, ?bool, ?array, ?vec, ?dict, ?keyset, ?Map, ?Set, ?Vector, and the immutable/const variants of these, is now a ‘sketchy null check’ errordecl_override_require_hint in 3.27)abstract keyword is not permitted in interface declarationshackfmtforce_hh is not setThese changes are currently opt-in - we expect them to be mandatory in 3.29.
assume_php=false : raise errors for using types/functions in partial-mode files that aren’t declared in Hack or HHI files. This was previously announced, but not actually enforceddisallow_return_by_ref=true : ban returning by referencedisallow_array_cell_pass_by_ref=true :bans &$foo[0]Separately, we expect to remove support for the previous approaches to type-refinement in a future version; we do not yet have a specific target version.
is and as Expressions| Old | New |
|---|---|
is_int($x) |
$x is int |
$x instanceof MyClass |
$x is MyClass |
MyEnum::isValid($x) |
$x is MyEnum |
is_int($x) || is_string($x) |
$x is arraykey |
$x === null || is_int($x) |
$x is ?int |
$x !== null |
$x is nonnull |
is_vec($x) |
$x is vec<_>; |
is_dict($x) |
$x is dict<_, _>; |
TypeAssert\matches_type_structure(type_structure(static::class, "TFoo"), $x) |
$x as this::TFoo |
Hack previously had a collection of inconsistent APIs for type testing. For example, you currently use instanceof for classes/interfaces, the is_int() et al. functions for primitives, and the isValid static method for enums. Furthermore, it can be unclear which language constructs refine the type of a variable from the typechecker’s perspective—we often receive questions in Hacklang Support about why a particular expression didn’t refine the type of a variable. The goal of the is operator is to make type testing:
At runtime, the is operator determines whether a value is of a certain type and evaluates to a boolean. Statically, it refines the type of a variable when used in an if statement, invariant, or ternary expression. If the type does not exist, the expression will evaluate to false (although that will be a typechecker error).
1
$x is T;
Similarly, type assertion in Hack is suboptimal. The goal of the as operator is to make type assertion consistent, predictable, and ergonomic, as well as more performant.
At runtime, the as operator evaluates to the left operand if its type matches, otherwise it throws TypeAssertionException. Statically, it unconditionally refines the type of the left operand. The as operator also comes in a non-throwing variant ?as, which evaluates to null if the type doesn’t match.
1
2
$x as T;
$x ?as T;
The as operator has notable benefits over the userland assertion libraries, both statically and at runtime. For example, the operator is able to refine the type of variables in the typechecker, unlike TypeAssert and others. Not only does this allow you to write better, more natural code, but it also enables HHVM to better optimize during compilation, which makes it faster than the userland implementations!
Aside from the typehints discussed in the “Limitations” section below, the is and as operators can be used with any type in the Hack language!
For primitives and primitive unions, the operators work as you’d expect.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
1 is int; // true
1 as int; // 1
'foo' is int; // false
'foo' as int; // TypeAssertionException
1 is num; // true
1 as num; // 1
1.5 is num; // true
1.5 as num; // 1.5
'foo' is num; // false
'foo' as num; // TypeAssertionException
For enums, the operators will validate that the value is in the given enum. CAUTION: the operators will perform integral key coercion to preserve compatibility with BuiltinEnum::isValid. We will fix this separately in the future.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
enum MyEnum: int {
FOO = 1;
}
1 is MyEnum; // true
1 as MyEnum; // 1
42 is MyEnum; // false
42 as MyEnum; // TypeAssertionException
'foo' is MyEnum; // false
'foo' as MyEnum; // TypeAssertionException
'1' is MyEnum; // CAUTION - true
'1' as MyEnum; // CAUTION - '1'
For generic types, you must use the _ (wildcard) placeholder for the type parameters. This is discussed in more detail in the “Generics” subsection of the “Limitations” section below.
1
2
3
4
interface MyInterface<T> {}
$x is MyInterface<_>;
$x as dict<_, _>;
For structural types (i.e. tuples and shapes), the operators will validate the size and recursively validate every field in the value. This means you should be mindful of using them with enormous structural types*.
1
2
3
4
5
6
$x is (int, ?string, bool); // OK
$x as shape(
'foo' => int,
?'bar' => (int, ?string, MyEnum),
...
); // OK
For type aliases and type constants, the operators will test the value against the underlying runtime type.
1
2
3
4
5
6
7
8
9
10
11
12
13
type Foo = (int, ?string, bool);
tuple(1, null, false) is Foo; // true
varray[1, null, false] is Foo; // true
dict[0 => 1, 1 => null, 2 => false] is Foo; // false
abstract class C {
const type T as num = int;
public function isT(mixed $x): void {
$x is this::T; // OK
}
}
nonnull TypeHack refines the nonnull type specially - if the input variable of is nonnull or as nonnull is known to be of type ?T, it is refined to T, instead of simply to nonnull
1
2
3
function foo(?string $x): void {
$y = $x as nonnull; // $y has type `string`
}
Types that cannot be properly tested at runtime are not supported. *Use of the is and as operators with an unsupported type will raise an unfixmeable typechecker error and will potentially raise a fatal runtime error.
The use of generics with the is and as operators is unsupported, because generics are erased at runtime.
1
2
3
4
5
6
final class Foo<Tu> {
public function bar<Tv>(mixed $x) {
if ($x is Tu) {...} // UNSUPPORTED
$x as Tv; // UNSUPPORTED
}
}
Similarly, using the is and as operators on generic classes and type aliases is unsupported.
1
2
3
4
5
6
7
8
final class Bar<T> {}
type Baz = Bar<int>;
if ($x is Bar<int>) {...} // UNSUPPORTED
if ($x is Baz) {...} // UNSUPPORTED
$x as Bar<int>; // UNSUPPORTED
$x as Baz; // UNSUPPORTED
However, you can use the wildcard typehint in place of generics, and the typechecker will infer the type to the best of its ability. For now, the wildcard can only be used in is and as expressions. In the following example, we know that vec<T> is a Container<T>, so this code is valid:
1
2
3
4
5
6
7
8
function f(Container<int> $x): void {
if ($x is vec<_>) {
expect_vec_of_int($x); // OK
}
expect_vec_of_int($x as vec<_>); // OK
}
function expect_vec_of_int(vec<int> $y): void {}
In this example, we know that the type parameter of keysets must be arraykeys, so this code is valid:
1
2
3
4
5
6
7
8
function f(mixed $x): void {
if ($x is keyset<_>) {
expect_keyset_of_arraykey($x); // OK
}
expect_keyset_of_arraykey($x as keyset<_>); // OK
}
function expect_keyset_of_arraykey(keyset<arraykey> $y): void {}
You may be asking, “The wildcard is ugly! Why do we have to use it when we don’t have to use it for instanceof?” In strict mode, we require all typehints to have their type parameters specified. If type parameters are not specified, the typechecker assumes that they are the “any” type, an extremely permissive type that provides very poor typechecking. The instanceof operator is an exception to this rule—instead of the “any” type, we assume that each type parameter is some type for which we have no information, which allows us to infer its constraints. The wildcard makes this behavior explicit in syntax and allows us to consistently require that typehints have type parameters.
Because we cannot verify the input/output types of a function at runtime, they are unsupported.
1
2
if ($x is (function(string): int)) {...} // UNSUPPORTED
$x as (function(string): int); // UNSUPPORTED
PHP arrays and the aliases are unsupported:
1
2
3
$x is array<_>; // UNSUPPORTED
$x is varray<_>; // UNSUPPORTED
$x as darray<_, _>; // UNSUPPORTED
Because opaque type aliases would require additional validation in Hack code, they are unsupported. For example, in the following code, we only know that IDs are ints at runtime—how would we know that the operand is a valid ID?
1
2
3
4
newtype ID as int = int;
if ($x is ID) {...} // UNSUPPORTED
$x as ID; // UNSUPPORTED
Similarly to instanceof, we don’t support complex expressions when refining types. For example, we’d expect that the following example would refine the type of $x to Foo | Bar, but it currently does not refine the type at all.
1
2
3
4
5
function f(mixed $x): void {
if ($x is Foo || $x is Bar) {
// $x is of type mixed
}
}
In the future, once we converge on only one operator that performs type testing, we can begin to invest in supporting more complex expressions and more intelligently refine types of local variables.
Fred Emmott
Posted August 15, 2018
HHVM 3.27.2 is released! This release contains several bugfixes:
HH\facts_parse in multiple simultaneous requestshh_client crash on shutdown in some situationsFred Emmott
Posted July 19, 2018
HHVM 3.27.1 and 3.24.8 are released! The releases contain several bugfixes:
"{$$foo}" in PHP filesif (Shape::keyExists()) refinementsFred Emmott
Posted June 18, 2018
HHVM 3.27 is released! This version has long-term support, and contains performance, IDE, typechecker, and other improvements:
Shapes::removeKey() now takes the shape as an inout parameter instead of by referenceawait and yield are now permitted in finally blocksforward_compatibility_level option to .hhconfig to make managing upgrades easier.enable_experimental_tc_features in .hhconfig contains sealed_clases. This bans extending the built-in Container and KeyedContainer classes, and we expect this to be required in 3.28disallow_unsafe_comparisons=true is set in .hhconfig. We expect this to be required in 3.28arraykeys in Hack code when disallow_non_arraykey_keys=true is set in .hhconfig. We expect this to be required in 3.28, and was already a runtime error if non-array keys were actually used.decl_override_require_hint=true is set in .hhconfigShapes::keyExists() checks when enable_experimental_tc_features in .hhconfig contains shape_field_check.Shapes::keyExist() now refines the type when used as a condition$nullable_string ? $foo : $bar is now detected), and always-false identity checks (e.g. $not_nullable === null or $int === $string).varray<T> and darray<Tk, Tv> types; these should be considered aliases for array<T> and array<Tk, Tv>, and are used as an implementation detail of some internals. Hack code should continue to use the vec<T>, keyset<T>, and dict<Tk, Tv> types instead.relatedInformation field is now used for Hack errors, providing more detailed diagnostic information in editors such as Visual Studio CodetextDocument/renametextDocument/documentSymbolstrict_types leading to crashes or unexpected TypeErrorsuntrusted_mode option to .hhconfig. When true, it is intended to be safe to run hh_client or hh_server --check $(pwd) on potentially malicious code: hh_server will fail early if dangerous options are also set. If you find issues with this feature, or any other security issue in HHVM or Hack, please report them via Facebook’s Whitehat (Bug Bounty) Program.We have released 3.27 two weeks ahead of schedule - we expect future releases to follow the original schedule. To reduce issues:
This feature is currently opt-in, though we expect it to be mandatory in 3.28.
Sealed classes/interfaces are only able to be directly extended/implemented by a whitelist of classes and/or interfaces - though, those subclasses can be extended arbitrarily unless they are final or also sealed. In this way, sealing provides a single-level restraint on inheritance.
Classes/interfaces are sealed by providing a whitelist of classnames to the __Sealed attribute:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<<__Sealed(Some::class, None::class)>>
abstract class Option<T> {
abstract function get(): T;
}
final class Some<T> extends Option<T> {
public function __construct(
private T $value,
) {}
public function get(): T {
return $this->value;
}
}
final class None<T> extends Option<T> {
public function get(): T {
invariant_violation('none');
}
}
// ERROR
final class Few<T> extends Option<T> {}
__Sealed attribute?Attach it to a class/interface and specify classnames that may extend/implement it. These must be of the form Foo::class.
Extending/implementing a sealed class/interface with a class/interface not in the whitelist will raise both a typechecker and runtime error.
There is no runtime enforcement for sealing of the collection interfaces in 3.27, in order to keep sealed classes opt-in in this release. We expect runtime enforcement for these collection interfaces in 3.28.
Only classes and interfaces may be sealed — traits and enums may not. Further, traits may presently not implement sealed interfaces. We expect full support for traits in the future, both for sealing them and for implementing/using sealed interfaces/traits.
Sealing a final class will raise a typechecker error and parse error at runtime, as that would be redundant.
Yes. Sealing only applies to direct extension.
Sparingly, if ever—your classes should be final whenever possible! Potential use cases for this feature include preventing new instances of a deprecated class from being added, or for simulating ADTs as demonstrated above.
The collection interfaces were only intended for internal implementations, and it has been unsafe to create custom implementations of the collection interfaces since they were introduced; however, users have implemented them, leading to unexpected and undefined behavior.
This option exists to make it easier to upgrade to new versions of HHVM and Hack, however it is only a temporary migration aid - it does not allow permanently opting out of changes, and decreases the safety of your code.
forward_compatibility_level can be set to a valid release number (such as 3.27), a date as an integer (e.g. 20180618), or omitted. Dates are intended to be used for incrementally supporting features as they’re added to nightly builds. For each release, the branch cut date is equivalent; for example, “forward_compatibility_level=3.27” is equivalent to “forward_compatibility_level=20180604”.
This option suppresses errors - it does not restore old behavior, and may raise fewer errors. This means that:
forward_compatibility_level=3.26forward_compatibility_level=3.26 might be invalid under 3.26If set to the current release or newer, there is no change in behavior.
If set to older than the current release, a warning will be reported, but the exit status of hh_client and hh_server will be 0. Some other Hack errors might not be raised that would be without this warning. For example, hh_client in 3.27 reports a warning if set to 3.26.
If set to older than the previous release, an error will be reported, and hh_client and hh_server will exit with non-zero status, like any other error. For example, hh_client in 3.28 will report an error if set to 3.26.
This option is intended for short-term use, to allow resolving issues when new releases raise errors with circular dependencies, or when doing a staged roll-out of a new version. The option should be removed as soon as possible.
Additionally, it can be used to detect unintentional backwards-incompatible changes in Hack, especially when testing against nightly builds.
The following .hhconfig features are opt-in, and we expect them to be required behavior in 3.28:
1
2
3
4
5
disallow_elvis_space=true
disallow_non_arraykey_keys=true
disallow_unsafe_comparisons=true
decl_override_require_hint=true
enable_experimental_tc_features=shape_field_check,sealed_classes
Fred Emmott
Posted May 24, 2018
HHVM 3.26.3 is released! This release contains several bugfixes, and improvements to IDE support:
folly::secureRandom (random_bytes() and random_int()) buffer on fork. This does not affect 3.25 or below.hackfmt instead of hh_format for IDE code formatting features (hh_format fails on most modern Hack code)use statements in classes autocomplete should only suggest traitsyield and await are unsupported; this improves handling of IDisposable, IAsyncDisposable, __callStatic, and increases PHP compatibility.extra_paths= option to .hhconfig to include dependencies outside of the project root. This is experimental, and may be removed at any time.Fred Emmott
Posted May 15, 2018
HHVM 3.26.2 is released! This release contains several bugfixes and improvements:
Fred Emmott
Posted May 11, 2018
HHVM 3.26.1 is released! This release contains several bugfixes, primarily improving support for PHP code when using HackC:
ext_factparse: return empty lists instead of null for empty filesis_array() and similar checks for superglobalsisset() for superglobalsif statements with empty bodies when using the if(0): endif; syntaxinout parametersFred Emmott
Posted May 07, 2018
HHVM 3.26 is released! Highlights include a new frontend, relicensing of the typechecker and related tools and libraries to MIT, and support for Ubuntu 18.04. Packages have been published in the usual places.
The Hack & HHVM team is excited to announce that HackC — the new front-end for HHVM — is now on by default in this release, after about a year of work by many. This includes a full-fidelity parser (FFP) and bytecode emitter for the Hack and PHP languages. The FFP already powered several tools, such as Hack’s IDE integration via the Language Server Protocol, hackfmt, and hhast; in addition to the runtime, we expect the typechecker (hh_client and hh_server) to use the FFP in the future, leading to a single unified parser for typechecking, execution, IDE services, and other tools.
HackC passes all of HHVM’s tests - including the PHP specification tests - and produces semantically equivalent bytecode. That said, if you encounter problems:
hhvm.hack_compiler_default=false INI settingYou can verify which frontend is being used by inspecting the __COMPILER_FRONTEND__ magic constant.
As previously announced, Hack is now available under the MIT license. 3.26 is the first stable release to include Hack under these terms.
nonnull type, allowing more thorough and consistent typing - e.g.
function nullthrows<T as nonnull>(?T $in): Tdynamic type to allow safer dynamic code, as an alternative to untyped or mixedhh_parse now can produce dot (Graphviz) representations of the AST - e.g. hh_parse --full-fidelity-dot test.hh | dot -Tpng ast.png; open ast.pnghh_client ide) has been removed; the VSCode Language Server Protocol (hh_client lsp) should be used insteadFOO’ is always equivalent to ‘namespace\FOO’)using blocks and Disposables instead.mixed)?:) operator - e.g. $foo = bar() ? /* hello, world */ : baz();. To ban this syntax, set disallow_elvis_space=true in your .hhconfig. We expect this to be required in 3.27.dynamic is a new type we’ve added to Hack’s type system. The dynamic type is a special type in Hack used to help capture dynamism in our codebase in typed code, in a more manageable manner than mixed. With the dynamic type, the presence of dynamism in a function is local to the function, and dynamic behaviors cannot leak into code that doesn’t know about it.
For example, this untyped code will not raise type errors, as the typechecker assumes any use of untyped variables ($x) is valid:
1
2
3
4
5
6
7
8
function takesInt(int $x) : int {
//...
}
function f($x) {
$id = $x->getInt();
$y = takesInt($id);
}
With dynamic, the local usage is allowed, but dynamism must be removed at the function boundaries:
1
2
3
4
5
6
7
8
9
10
11
function takesInt(int $x) : int {
//...
}
function f(dynamic $x) : void {
// Calling a method on a dynamic type is allowed,
// and will result in another dynamic
$id = $x->getInt();
// error! id is type dynamic, not compatible with int
$y = takesInt($id);
}
Finally, with mixed, the type must be refined before use:
1
2
3
4
5
6
7
8
function takesInt(int $x) : int {
//...
}
function f(mixed $x) : void {
$id = $x->getInt(); // error! $x is mixed, cannot call getInt()
$y = takesInt($id);
}
dynamic is permissive of most local operations: like untyped expressions, you can treat it like an integer and add it, or a string and concatenate it, or call any methods on it.dynamic in an arithmetic operation like “+” or “-” will result in a num, using a dynamic in a string operation will result in a string, but calling a method on a dynamic will result in another dynamic:1
2
3
4
5
function f(dynamic $x) : void {
$y = $x + 5; // $y is a num
$y = $x . "hello!"; // $y is a string
$y = $x->anyMethod(); // $y is dynamic
}
dynamic is a supertype of all types(including mixed, though this might change). If a function accepts or returns a dynamic type any value can be used without performing a cast. We may limit or change this behavior in the future based on feedback and usage.dynamic is permissive locally, so you don’t have to null check it. That said, this means there are no guarantees by the typechecker that your type is actually nonnull. We also may change this behavior in the future.dynamic is not a subtype of any regular type. That is, you cannot pass it to a function that expects a nondynamic type, or return it from a function that returns a nondynamic type (besides mixed) without casting.Fred Emmott
Posted May 04, 2018
These releases contain several bugfixes:
Additionally:
Fred Emmott
Posted April 11, 2018
This morning, we re-licensed Hack itself under the MIT license, and we will be doing the same for most of our Hack libraries and tools over the next few days, including the Hack Standard Library.
We’re relicensing Hack, these tools, and these libraries to a license that is broadly used in the community to ease concerns about compatibility, and to avoid holding back adoption for non-technical reasons.
HHVM itself remains under the PHP and Zend licenses.
Fred Emmott
Posted March 30, 2018
These releases contains several bugfixes:
$GLOBALS via file uploadsFred Emmott
Posted March 22, 2018
These releases contains several bugfixes:
Fred Emmott
Posted March 15, 2018
HHVM 3.25 is released! This release contains new features, bug fixes, performance improvements, and supporting work for future improvements. Packages have been published in the usual places.
Additionally, we are releasing 3.24.4 and 3.21.8 which address CVE-2018-6332, but do not include the other changes listed below.
Highlights of 3.25 include:
Throwable, Error, and Exception hierarchy is now always present, including in Hack and in PHP5 mode - however, internals will not raise instances of Error or subclasses if PHP5 mode is enabled.inout function parameters are now supported, to replace references.hhvm.hack.lang.auto_typecheck=1 ini setting.foo(...) { bar(func_get_args()); }) are no longer supported in strict mode. Use named variadics and splats instead (e.g. foo(string ...$args) { bar(...$args); }).$$foo) are no longer supported in decl mode.??T) being inferred when using await.array, array<Tv>, and array<Tk, Tv> types are no longer interchangeable. To ease migration, you can currently opt-out of this by setting safe_array=false and safe_vector_array=false in your .hhconfig, however we expect to remove this option in a future release.hh_client hanging after spawning a server, or if it ran shortly after a server was started.Hack inout parameters are a replacement for PHP references, aiming to remove confusing corner-cases and make additional performance improvements possible.
inout parameters allow local data to flow in and out of a function call. Changes to the data in the body of the function become visible to the caller after control returns.
1
2
3
4
function f(inout int $var): void {
var_dump($var);
$var = 42;
}
Calling f() as follows,
1
2
3
$x = 0;
f(inout $x);
var_dump($x);
will result in the output:
1
2
int(0)
int(42)
In the scope containing $x, the call to f() causes $x to be overwritten with a new value immediately after the call finishes execution.
To declare a parameter as inout, add the inout keyword before the type annotation. If there is no type annotation, add it before the variable name.
1
2
3
function g(int $x, inout string $y): void {...}
// Untyped - invalid in strict mode, discouraged in other modes:
function h(inout $z) {...}
When calling a function with one or more inout parameters, the corresponding arguments also need to be preceded by the inout keyword so that the calling convention is apparent.
1
2
3
4
$s = 'foo';
g(42, inout $s);
h(inout $s[1]);
h($s[1]); // typechecker error, inout expected
When designing inout we wanted to ensure the feature is performant and behaves intuitively, so we added some additional restrictions:
inout parameters are local variables with an arbitrary number of index expressions allowed.
$x) or indexed elements contained inside a local ($vec[$y][z()][2]).inout parameters, though support might be added in the future. Right now, these include class constructors, async functions, and generators.inout parameters and PHP references (&) when defining or calling a function.inout parameters cannot have default values or be variadic.inout parameters cannot be memoized.inout argument, the other should not be used in a write context within the same statement.
swap(inout $a, inout $a[0]) and $a = h(inout $a[0]).inout parameters have “copy-in copy-out” behavior.
inout parameters look a lot like PHP references, but there are some key differences.
inout parameter within a function does not instantly update the variable that was passed into the call.
inout parameters are copied out.inout parameters are designed to be sound in Hack from day 1. They are fully supported in strict mode.
& references, the type checker is ignorant of their semantics. It cannot warn if types become fluid as a result of multiple references to the same variable.inout are required to be explicit, at both the declaration as well as the callsite.Any function definition with inout parameters is transformed by the compiler so that it returns the final values of its inout parameters in addition to the function’s return value (if any). At the callsite, the new values returned for the inout parameters are assigned back to their initial arguments.
A function bar taking one or more inout parameters, and corresponding call to bar():
1
2
3
4
5
function bar(inout Ta $a, Tb $b, ..., inout Tz $z, ...): Tr {
... // implementation, possibly changing $a and/or $z
return $ret;
}
$bar = bar(inout <A>, <B>, ..., inout <Z>, ...);
(with <A> etc. representing expressions) is roughly equivalent to:
1
2
3
4
5
function bar(Ta $a, Tb $b, ..., Tz $z, ...): Tr {
... // implementation, as above
return tuple($a, $z, $ret);
}
list(<A>, <Z>, $bar) = bar(<A>, <B>, ..., <Z>, ...);
where <A> and <Z> are only evaluated once to compute parameter names and offsets for read/write.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* Extends a vec by appending the elements of the Traversable in-place.
*/
function extend<Tv>(
inout vec<Tv> $vec,
Traversable<Tv> $traversable,
): void {
foreach ($traversable as $value) {
$vec[] = $value;
}
}
$v = vec[3, 2, 1];
extend(inout $v, keyset[4, 5]);
var_dump($v); // vec[3, 2, 1, 4, 5]
HHVM now supports debugging via the Visual Studio Code Debug Adapter Protocol, which will be replacing use of XDebug for debugging in the next release. The VS Code protocol offers a more modern and extensible feature set and the switch allowed us to fix several significant issues in the HHVM debugger back-end that were fundamentally broken due to use of XDebug. Documentation for this protocol can be found here: https://code.visualstudio.com/docs/extensionAPI/api-debugging
With this, HHVM now offers a completely new debugging engine back-end, which will prove to be faster, more reliable, and will allow us to iterate and build better debugging experiences much more effectively. Switching to the VS Code protocol aligns with our new support for Hack language services via the VS Code Language Server Protocol. Additionally, the VS Code debug protocol is part of a sizable and growing ecosystem that is well supported by several great open source projects.
The new HHVM debugger is compatible with IDEs that speak the VS Code Debug Adapter protocol including Nuclide and Visual Studio Code. This debugger will be replacing the existing XDebug-based HHVM debugger. **Note that this means support for the XDebug protocol is now deprecated, and will be removed completely in the next release of HHVM. **We are currently planning to replace hphpd in the near future with a new CLI debugging experience that is compatible with all VS Code debuggers, including HHVM, but will keep hphpd in place and supported until the replacement is ready.
Like HHVM’s other debuggers, this new debugger is disabled by default when HHVM is running in server mode. To enable it, set vs_debug_enable = true in your config file:
hhvm.debugger.vs_debug_enable=1
When enabled, in server mode the debugger will listen for incoming connections on TCP port 8999 by default. This can be overridden in your config file as well:
``hhvm.debugger.vs_debug_listen_port=<port>
To support debugging scripts, HHVM now accepts some new command line parameters:
1
hhvm --mode vsdebug --vsDebugPort <port> <... other args> <your_script.php>
This will execute the specified script with the new debugger enabled. On startup, HHVM will stop and wait for a debugger to connect on the specified port before beginning execution of the script. Compatible IDEs such as Nuclide will offer a way to attach to hhvm on the specified port and begin execution and debugging of the script.
It is also possible to begin running a script in a mode that allows the debugger to attach and break in later:
1
hhvm --mode vsdebug --vsDebugPort <port> --vsDebugNoWait true <...> <your_script.php>
This command is similar to the previous one, except HHVM will not wait for the debugger on startup. Instead it will begin executing your script immediately as normal, but it will accept a connection from your debugger on the specified port. The debugger can attach later and break into the target. This is useful for being able to break into long-running scripts that need to be debugged after executing for a while. Nuclide will offer a mechanism to list scripts started in this fashion and break in to them.
Support for connecting to the new HHVM debugger via Visual Studio Code is available via open source VS Code extensions, such as https://github.com/PranayAgarwal/vscode-hack
These features are opt-in in 3.25, but we expect them to be mandatory in HHVM 3.26. These are all supported by the active libraries and tools available on https://github.com/hhvm/.
To improve consistency and remove ambiguity, we are removing the root-namespace fallback for functions and constants:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?hh
namespace MyNS;
function main(): void {
// Always refers to \MyNS\MyClass();
new MyClass();
// Currently may refer to either \MyNS\my_func() or \my_func(), depending on what's
// available at runtime; in 3.26 and above, it will always refer to \MyNS\my_func()
my_func();
// Explicitly reference \MyNS\my_func():
namespace\my_func();
// Explicitly reference \my_func();
\my_func();
}
To enable this behavior in 3.25, set enable_experimental_tc_features = no_fallback_in_namespaces in your project .hhconfig file.
HHAST is able to automatically migrate codebases that have no other typechecker errors:
1
hhast$ bin/hhast-migrate --no-namespace-fallback /path/to/your/project/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?hh
function foo(int $first, int...$rest): void {}
// In 3.25, this is permitted, however it is unsafe as $args may be empty. We expect
// to ban this in 3.26.
function bar(int ...$args): void {
foo(...$args);
}
// Instead:
function bar(int $first, int ...$rest): void {
foo($first, ...$rest);
}
Tuples are still permitted if they have sufficient elements of the correct types, for example:
1
2
3
function bar((int, int) $args): void {
foo(...$args);
}
To enable this behavior in 3.25, set enable_experimental_tc_features = unpacking_check_arity in your project .hhconfig file.
We are removing destructors from Hack to simplify behavior and remove the need for strict reference counting in the runtime; common approaches to replace them include:
register_shutdown_function()To enable this behavior in 3.25, set disallow_destruct = true in your project .hhconfig file.
Destructors can also be banned at runtime by setting the hhvm.allow_object_destructors= false HHVM INI setting, though this will also affect PHP files.
PHP references are completely banned in strict mode, however they’re currently permitted in partial mode. While we’re not yet changing that, we are banning them inside arrays:
1
2
3
4
5
6
7
<?hh
function foo(): void {
$x = array(42);
// Will be banned in 3.26:
$z = &$x[0];
}
To enable this behavior in 3.25, set enable_experimental_tc_features = disallow_refs_in_array in your project .hhconfig file.
1
2
3
4
5
6
7
8
9
<?hh // strict
function foo(mixed $f): void {}
function bar(): void {
// Inference can't be used if passing untyped, so this is unsafe, and will be
// banned in 3.26
foo($a ==> $a);
}
To enable this behavior in 3.25, set enable_experimental_tc_features = disallow_untyped_lambda_as_non_function_type in your project .hhconfig file.
Fred Emmott
Posted March 02, 2018
These releases contains several bugfixes:
Fred Emmott
Posted February 07, 2018
This release contains several bugfixes:
Additionally, we have rebuilt the HHVM 3.21 MacOS binaries to be compatible with updates to other Homebrew packages.
Fred Emmott
Posted January 30, 2018
These releases contains several bugfixes:
parse_url() with upstream (PHP7), fixing support for URLs containing usernames and passwords that contain unusual characters (3.24.1, 3.21.6, 3.18.8).JSON_FB_HACK_ARRAYS flag for json_decode() when HHVM is built against the json-c library (3.24.1, 3.21.6).HHVM 3.18 is unsupported, and we recommend migrating to 3.21 or 3.24 as soon as possible. We are making an exception by releasing 3.18.8 as it fixes a regression we recently introduced in 3.18.7 - we are not expecting to release any further 3.18 updates.
Fred Emmott
Posted January 16, 2018
HHVM 3.24 is released! This release contains new features, bug fixes, performance improvements, and supporting work for future improvements. Packages have been published in the usual places.
Highlights include:
$foo = [3, 1, 2]; sort(&$foo);using blocks - an alternative to destructorshh_parse now offers a --full-fidelity-text-json option, which includes node content in the outputAs a release with long-term support, 3.24 is supported through 2018-12-17; it also marks the end of support for HHVM 3.18.
3.24 is the final release targeting PHP5; this includes source-level compatibility for PHP5 extensions (ext_zend_compat). We recommend migrating to Hack or PHP7.
As 3.24 is supported though 2018-12-17, this means that support will end at roughly the same time as PHP5 itself is scheduled to become unsupported (2018-12-31).
The Debian project is scheduled to end support for Wheezy in May 2018, and the Ubuntu project is scheduled to end support for Ubuntu Zesty in January 2018; as such:
In Hack code, by-ref function arguments must now be marked at the callsite, not just at the function declaration. We have extended HHAST to automate migrations; for example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
$ bin/hhast-migrate --help
Usage: bin/hhast-migrate [OPTIONS] PATH [PATH ...]
Options:
--implicit-shape-subtypes
Allow implicit structural subtyping of all shapes
--optional-shape-fields
Migrate nullable shape fields to be both nullable and optional
--hhvm-3.22-to-3.23
Apply all migrations for moving from 3.22 to 3.23
--ctpbr
Add required ampersands at call sites for byref arguments
--hhvm-3.23-to-3.24
Apply all migrations for moving from 3.23 to 3.24
--include-vendor
Also migrate files in vendor/ subdirectories
-v, --verbose
Increase output verbosity
-h, --help
display this text and exit
$ bin/hhast-migrate --ctpbr $HOME/code/fbmarkdown/src/
$ cd $HOME/code/fbmarkdown/src/
$ git diff
diff --git a/src/_Private/decode_html_entity.php b/src/_Private/decode_html_entity.php
index 7891b57..a44b441 100644
--- a/src/_Private/decode_html_entity.php
+++ b/src/_Private/decode_html_entity.php
@@ -25,7 +25,7 @@ function decode_html_entity(string $string): ?(string, string, string) {
\preg_match(
'/^&(#[0-9]{1,8}|#X[0-9a-f]{1,8}|[a-z][a-z0-9]*);/i',
$string,
- $matches,
+ &$matches,
) !== 1
) {
return null;
...
This is not required for PHP code.
“Using” blocks provide a mechanism to limit an object to a particular scope, invoking code on scope exit, without using destructors.
This is done by implementing either IDisposable or IAsyncDisposable:
1
2
3
4
5
6
7
8
9
10
/**
* Objects that implement IDisposable must be constructed in using statements
*/
interface IDisposable {
/**
* This method is invoked exactly once at the end of the scope of the
* using statement, unless the program terminates with a fatal error.
*/
public function __dispose(): void;
}
For example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Handle implements IDisposable {
public function __dispose(): void {}
public function foo(): void {}
}
function disposable_example(): void {
// Block scope
using ($x = new Handle()) {
$x->foo();
} // $x->__dispose() is implicitly called here
// Function scope
using new Handle();
// handle still exists here
} // __dispose() is now called on the anonymous handle
Further details are available in the documentation.
Many XHP elements currently implicitly copy attributes to the root XHP element they produce; this silently overrides elements that are declared on the root element, and is hard to reason about in large codebases.
We have added an attribute spread operator to explicitly copy attributes, and will be removing implicit copying from xhp-lib in the near future:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class :foo-old extends :x:element {
use XHPHelpers;
attribute string color, int age;
public function render(): XHPChild {
return <bar color="red" />;
}
class :foo-new {
attribute string color, int age;
public function render(): XHPCHild {
return <bar {...$this} color="red" />;
}
}
class :bar extends :x:element {
attribute string color, int age;
}
$xhp = <foo-old color="blue" />;
$xhp2 = <foo-new color="blue" />;
// Old: this XHP renders to <bar color="blue" />.
// New: Spread position matters, so the XHP renders to <bar color="red" />
@required attributes can no longer be nullable@required attributes can no longer have a default valueStringish now extends XHPChild?XHPChild<foo bar:baz="foo">In previous releases, Hack has assumed that if a partial file references an unknown definition (e.g. classes, functions, or constants), that it exists in a PHP file. This is no longer the case. We recommend adding HHI files for PHP libraries that are directly used in Hack code. Alternatively, HH_FIXME comments can be used to suppress these errors.
It is currently also possible to enable the old behavior by setting assume_php=true in your project’s .hhconfig file - however this is no longer a supported configuration, may be buggy, and will be removed from a future release (potentially 3.25). It should be considered a temporary migration aid only.
We are doing this change to:
assume_php=true, Hack is unable to raise errors for typos in function, class, or constant names except in strict filesFred Emmott
Posted January 12, 2018
Today we’re releasing HHVM 3.23.4, 3.21.5, and 3.18.7. These releases contain security improvements:
preg_quote() does not quote # control characterext_zend_compat: Fix potential memory issue with USE_ZEND_ALLOC=0Fred Emmott
Posted January 02, 2018
Today we’re releasing HHVM 3.23.3, 3.21.4, and 3.18.6. These releases contain:
Fred Emmott
Posted November 17, 2017
HHVM 3.23 is released! This release contains new features, bug fixes, performance improvements, and supporting work for future improvements. Packages have been published in the usual places, however we have rotated the GPG key used to sign packages; see the installation instructions for more information.
Highlights include:
using(), as this will conflict with the upcoming using featureignored_paths .hhconfig option, which contains an array of regular expressions - for example, ignored_paths = [ "vendor/.*tests?/" ].We have rotated the GPG key we use to sign our apt repositories; you will need to install the new key before installing updates:
1
2
3
sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xB4112585D386EB94
# or
curl https://dl.hhvm.com/conf/hhvm.gpg.key | sudo apt-key add -
Our downloads (including repositories) are now available via HTTPS, and distributed via CDN. You can migrate by running apt-get install apt-transport-https, then editing your apt sources (either /etc/apt/sources.list, or a file in /etc/apt/sources.list.d/) to use https://dl.hhvm.com/ instead of http://dl.hhvm.com/
Binary packages are now available for MacOS Sierra and High Sierra. They can be installed by installing Homebrew, then:
1
2
brew tap hhvm/hhvm
brew install hhvm
We are now publishing nightly builds for Debian, Ubuntu, and Docker. For apt, these are available in the main repository as the hhvm-nightly package, and for Docker, they’re available as the hhvm/hhvm:nightly and hhvm/hhvm-proxygen:nightly tags.
This release adds support for Debian 9 (Stretch), Ubuntu 17.04 (Zesty), and Ubuntu 17.10 (Artful).
The next release - 3.24 - will be the last release with support for Debian 7 (Wheezy). All HHVM support for Wheezy will end on the 31st of May, 2018, including for the 3.21 and 3.24 LTS releases. This is the same date that Wheezy itself becomes unsupported.
The language server protocol is a standard for languages to integrate with editors and IDEs. If you wish to create or contribute to on an integration, use hh_client lsp to launch an LSP server.
Editors and IDEs should consider the language server protocol usable if hh_client --json --version reports an API version >= 5, and prefer the LSP over previous approaches.
HHVM 3.24 will require that reference arguments are marked at the callsite - for example:
1
2
3
function foo(array<string> $bar): void {
sort(&$bar);
}
Hack in 3.23 allows this syntax, but does not require it. You can opt-in to the requirement by adding safe_pass_by_ref to enable_experimental_tc_features in your .hhconfig.
We are planning on extending HHAST to automate this migration.
In HHVM 3.24, the expected types of lambdas will be used to refine them; for example, this currently has no errors:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?hh // strict
class MyClass {}
class MyClosureRunner<-T> {
public function __construct(private (function(T): string) $closure) {}
}
function expectsMyClosureRunnerMyClass(
MyClosureRunner<MyClass> $x,
): MyClosureRunner<MyClass> {
return $x;
}
function getThing1(): MyClosureRunner<MyClass> {
$var = expectsMyClosureRunnerMyClass(
new MyClosureRunner(
function(/* MyClass */ $arg) {
$arg->missing_method();
return "ok";
},
),
);
return $var;
}
In 3.24, or with enable_experimental_tc_features=contextual_inference in your .hhconfig, the following error will be raised by the typechecker:
1
2
3
test.php:19:15,28: Could not find method missing_method in an object of type MyClass (Typing[4053])
test.php:10:19,25: This is why I think it is an object of type MyClass
test.php:3:7,13: Declaration of MyClass is here
In non-strict Hack code, the typechecker assumes that references to classes, functions, and so on that it doesn’t know about are references to PHP code, so they are ignored. We will be removing this behavior in 3.24. You can experiment with this by adding assume_php=false to your .hhconfig.
If your Hack code depends on PHP code, there are several options:
HH_FIXME comments in wrappers to suppress the errorsAdding hhvm.allow_object_destructors = false to your HHVM configuration will cause runtime errors whenever a class with a destructor is instantiated. We have done this as many libraries use destructors, but only in components that appear to be very rarely used; this allows experimenting to determine what destructors actually are in use in your codebase.
You can whitelist a destructor by adding the <<__OptionalDestruct>> attribute to the method; HHVM does not guarantee whether a destructor marked with this attribute will be called or not, regardless of the value of the hhvm.allow_object_destructors setting. This can be useful where the inheritance hierarchy requires the presence of a destructor, but invoking it is not actually necessary for program correctness.
We are expecting to ban destructors in Hack in one of the next few releases, however they will still be supported in 3.24, and we currently have no timeline for removing them from our PHP support.
We are working on a using statement, which limits a variable either to a specific block, or to the function as a whole. We provide interfaces for user-specified code to be executed on these objects when they are about to leave the scope.
This is still a work in progress, and we expect it to be ready for experimentation in 3.24.
We are working on replacing the parser and bytecode emitter used for Hack, with the goal of using a single parser for execution, typechecking, formatting, linting, and all other tooling surrounding Hack.
While this is not yet ready for production use, you can experiment with it on Linux by setting the following options in your HHVM ini file:
1
2
hhvm.hack_compiler_default=true
hhvm.hack_compiler_command=/path/to/hh_single_compile --daemon
We strongly recommend only testing on Linux for now: there are known issues on other platforms which may affect overall system stability, especially on MacOS.
When these options are set, HackC will only be used for Hack files, unless the hhvm.force_hh ini setting is turned on, in which case it will also be used for PHP files. You can check which emitter is being used for a particular file with:
1
2
3
<?hh
var_dump(__COMPILER_FRONTEND__);
Currently, this will either output string(4) "hhvm" for the old frontend, or string(5) "hackc" if using hh_single_compile. This constant is also supported in PHP code, which will always contain string(4) "hhvm" unless both hackc and force_hh are enabled..
We would particularly appreciate bug reports related to namespaces, or interactions between Hack and PHP code that are only reproducible with the new emitter.
Fred Emmott
Posted November 14, 2017
As part of modernizing and automating our binary packaging infrastructure, we’re rotating the GPG key we use to sign our apt repositories; we will also be signing our source tarballs in the future. We expect to switch the key later this week.
The new key can be installed with:
1
2
3
sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xB4112585D386EB94
# or...
curl https://dl2.hhvm.com/conf/hhvm.gpg.key | sudo apt-key add
The full public key is:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBFn8koEBEAC2tPtkphj8gZYHI9mTNUHfQalDo+MNWTGUTNB42asjhTNjipzM
VSxjaZSl5cMLg5YCRuT0AbSIe529FH23yEElc03cGVGgoEnmXtE4+2v7Xa30wCGO
5oUxKfbVatsxEs1y8QEr5Gt+CUFmsApOKgiZq0MsPYmFAuC9CbWdXYa8+E00bXOa
cHCpe+GncCxQmExm7TlrUnURnf3RnNWSEkuPKED/aVggzxNVN6RgRRm4ssZJasM3
TwoI1nVysO5jMfPClvupYscoktO44HBZzH2EeEdpjSV+toD3aZCbmWzXyZjogrFN
j4k5Mme0Xqr4DvRPk5M9SxcQASsCQ8VTyu+ZBUG6zJbddLDEA1BMNIZOG5MyX58O
zed255Q85SAyjHu8pltkfGLd56+MYsckpHaBPMFoCFM4iPcpXOlgcU96pdXJbrR2
mjYI4Le9qRJYYP2kGPkopPwK8nbZJ5Wr7xaclxEc/ODH3mv57KJD7lzmwpnvvmsn
kR/wUHOqwrXojp/oZCUK8KembLiT+MMkY3bne+IY9ef/1qwu4flVBP1CpoaMQEwh
dqzihfwyQ+57ATZHJaj8V9pKAxWh/Df4iFN5mMWA15eBLhRMbAWKJIoLQLcCYwBF
gH3HiO34/uQUHaX6VhRHllA38WUoZNhKmw/Kcd/FDQWlbzbgmI89LJEJuwARAQAB
tC1ISFZNIFBhY2thZ2UgU2lnbmluZyA8b3BlbnNvdXJjZStoaHZtQGZiLmNvbT6J
Ak4EEwEIADgWIQQFg0HGj8jeYBfXdaG0ESWF04brlAUCWfySgQIbAwULCQgHAgYV
CAkKCwIEFgIDAQIeAQIXgAAKCRC0ESWF04brlMp8D/4ia7wLi6OQEtR8uPIrtCdg
ClHvXTX0zihHPDomn77lRSfqEVapKcsvpyc9YTjv27EuRvymUG+o7971RY+rYes4
+POdsjlxJF5ZkNi8YxpUNEw2hTWC66o6vd4Gv4dJgugkZ5dvHKEwec7+mQna9O/p
F4rY/VVmh+4YJUzuuKMb2ZLHsZ3LJv/WBL9Ps+sRFHUN5lDfV00wAsfzEW+dxyh1
kkqXwTk70r8m5m+nCdf0z+giAU7XWRkbJV2HTatSgY1ozOYARe4v0MGyLwp74I6R
lrWPY97C9k4emF7WP2mglcBu+Eg2Q6A0Y3OgEiGnqkgRJEnrfpHa4wXM1sEUf4MV
5FQgyroZg45c375okr/RLP/pC4/x8ZM6GqLv4qTEOk6qWM7hWXhPRJ1TSVgCHv19
jki5AkwV4EcROpFmJzfW6V9i4swJKJvYXLr58W0vogsUc8zqII4Sl7JUKZ/oN4jQ
QX138r85fLawla/R0i30njmY7fJYKRwHeshgwHg6vqKobTiPuLarwn0Arv7G7ILP
RjbH/8Pi+U2l8Fm/SjHMZA6gcJteRHjTgjkxSAZ19MyA08YqahJafRUVDY9QhUJb
FkHhptZRf9qRji3+Njhog6s8EGACJSEOwmngAViFVz+UUyOXY94yoHvb19meNecj
ArL3604gOqX3TSSWD1Dcu4kBMwQTAQgAHRYhBDau9k0CB+fu41LUh1oW5ygb56RJ
BQJZ/JVnAAoJEFoW5ygb56RJ15oH/0g4hrylc79TD9xA1vEUexyOdWniY4lwH9yI
/DaFznIMsE1uxmZ0FE9VX5Ks8IFR+3P9mNDQVf9xlVhnR7N597aKtU5GrpbvtlJy
CoQVtzBqYKcuLC4ZFRiB33HwZrZIxTPH27UUaj1QBz748zIMC6wvtldshjNAAeRr
Jz28twPO2D7svNIaPt2+OXAuRs2yUhitcsDLBV0UlOQ8xH+hzWANyhaJAS7p0k35
kyFOG+n6+2qQkGdlHHuqEzdCL3EiOiK6RrvbWNUnwiG3BdZWgs43hZZBAseX3CHu
MM3vIX/Fc/kuuaCWi2ysyKf7jyi/RiVIAKuLbxAB8eHsyo2G5lA=
=3DTP
-----END PGP PUBLIC KEY BLOCK-----
This key is signed with the previous key; if you have both keys added, you can verify this with:
1
gpg --keyring /etc/apt/trusted.gpg --list-sigs
Alternatively, this message is signed by both keys:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
In November 2017, the HHVM project will be migrating from GPG key 0x1BE7A449, with fingerprint:
36AE F64D 0207 E7EE E352 D487 5A16 E728 1BE7 A449
to GPG key 0xD386EB94, with fingerprint:
0583 41C6 8FC8 DE60 17D7 75A1 B411 2585 D386 EB94
-----BEGIN PGP SIGNATURE-----
iQE+BAEBCAAoFiEENq72TQIH5+7jUtSHWhbnKBvnpEkFAloLG/wKHHB0QGZiLmNv
bQAKCRBaFucoG+ekSe/ZB/4tuH5ZgV1whKPgZIlhi9iDdqTEbANT2nuCaCQuSupU
Dfha1KiYYqnZraw2EBDs0Ve6xrfIdhMKEoF7L2yRsWq/2i490Tf1Ug28MWaLiI23
ZqBpmv9djA9l/xi4CjWWjJaI60kZOL4WUzXrwlU6g6GwcObJweBjrZgA0NMrZwQP
F3Ll0czrxXxUS4ujpv5wSwYVGpJ0zZik8krFzb80Ttkum6icYJuTV8/85VEh8qHo
0557G94w8p5iAUNIdYbG510A0WfKe9s/5CEFCDyYuo3igFYipFWPy5/jK2j7F3VU
4LaWbSfzMMyVI746AMr5LJeFFTRi9YhQg9nnwgay+/yNiQJLBAEBCAA1FiEEBYNB
xo/I3mAX13WhtBElhdOG65QFAloLG/wXHG9wZW5zb3VyY2UraGh2bUBmYi5jb20A
CgkQtBElhdOG65R+ag//SVhZyYiJj35UK8rdKe9y53VdJtDQdD4GGJk/Y52c2pAi
xgs5AdHuTwVb+OzPJMUf/HpBFfNR6Ny86LlFEGqJvnWTJ5gVM6iN+UhPqgFBviqN
Xc6U+Ix3XF0vx6fQSNtK8YSP201psV7d7QKvDTaIEt0pm5JkrCp4VCwwiEAK/R0S
RcFh3cghSzCrdYbmr5lX4I6jkjEw/DyjqGsM9ctldNmqxGC55MfYMrx3tw+PiHTx
eivtw6L0X9z4mRJ0ONs9ULjtamurQbHWyVw8CA/BJ89X/1B9mNyLCxJlT5vrlb6a
ctzbowOFH9IviKFMxIqdRdenDOjIvWdvIf6jloT8ibt5s+ZGixf/0rWYzCTdi+fS
cjbuc7DW4Aru2i6DdQb63mXCjhpmEnkX3gvq1b2TYYQSCm7bd6vSwEQmoTUGOkDZ
Jm7sH97WgiOOBw5EmyBM1Coa5OaOq8qWghE5buzFpONA9gBXTxgJRS8lxswC0K5o
od+AhGTEuecVCEl7lIP/N5ASjrEBkEVKsFaGCX0tSDfgqCZW1JJ+WPD+TllUoEfd
m9jEaNjiApKSOxYg94+1M5Mv+BWh3AoEwz5Jm1xFnVhEocPqhX5Bh53OEfVWoPNX
Po7IgHHd574CLddZrzCslCsnhISm/ARHA2MZBLhfgl71eqz4nqiSwQ4IkUHEMGQ=
=WORw
-----END PGP SIGNATURE-----
If you have either, you can verify this message by copying the above into a file, then
1
gpg --keyring /etc/apt/trusted.gpg --verify < file_containing_message_above
If you have either existing key, you will see at least 1 “gpg: Good signature” line in the output; unless you have both keys, you will also see “gpg: Can’t check signature: public key not found” for whichever key you do not have installed.
Fred Emmott
Posted October 26, 2017
Today, we’re releasing the first stable version of the Hack Standard Library. The Hack Standard Library addresses several issues:
dict, keyset, and vec types (Hack Arrays).string | object) can only be typed as taking mixed, and while nullable types are supported (?sometype), falseable types aren’t - so anything that returns sometype | false must be typed as returning mixed in Hack.Since v0.1, our priority has been finding and addressing inconsistencies in our API; we’re grateful to our community for helping us with this, and are proud to release v1.0 without any known issues.
Fred Emmott
Posted September 26, 2017
HHVM 3.22 is released! This release primarily contains bug fixes, performance improvements, and supporting work for future improvements. Packages have been published in the usual places; see the installation instructions for more information.
Max Wang
Posted September 18, 2017
Several months ago, PHP officially announced the end-of-life for PHP5.
The HHVM team is happy about the direction PHP has taken with PHP7, and we’re proud of the role we’ve played in pushing the language and runtime to where they are today. Since the PHP community is finally saying goodbye to PHP5, we’ve decided to do so as well.
Fred Emmott
Posted August 02, 2017
HHVM 3.21 is released! As this is an LTS release, it will be supported until HHVM 3.27, expected in 48 weeks. This release improves PHP7 compatibility, and adds several new features. Packages have been published in the usual places; see the installation instructions for more information.
Michael O'Farrell
Posted June 07, 2017
HHVM 3.20 is released! This release improves compatibility with PHP7, and adds a couple new features. Packages have been published in the usual places; see the installation instructions for more information.
Michael O'Farrell
Posted April 13, 2017
HHVM 3.19 is released! This release has some exciting new experimental features. Packages have been published in the usual places; see the installation instructions for more information.
Brett Simmers
Posted March 23, 2017
HHVM’s JIT is responsible for translating sequences of HipHop Bytecode (HHBC) into equivalent sequences of machine code in order to execute PHP code as efficiently as possible. When running in server mode, HHVM shares this generated code across the many different threads executing PHP requests. Up until about a year ago, the JIT had a global “write lease,” which prevented multiple threads from running the JIT concurrently. This decision was made primarily to improve the layout of the generated code, but also to reduce implementation complexity. The project was still unproven, and we had to balance between shipping a perfect system and never shipping anything.
Max Wang
Posted March 09, 2017
HHVM is now fully-functional on ARM hardware! This post tells the story of how our ARM port came to be.
Guilherme Ottoni
Posted February 17, 2017
Our initial version of the HHVM JIT didn’t use profile-guided optimizations, and we suspected that we were leaving performance on the table because of that. After adding HHIR and beefing up the JIT backend in 2013, a couple of us embarked on the journey of building a profiling mechanism and leveraging it to improve the JIT’s optimizations and HHVM’s performance.
Michael O'Farrell
Posted February 15, 2017
HHVM 3.18 LTS is released! This version will be the last to support GCC 4.8 and Ubuntu 14.04 Trusty. Packages have been published; see the installation instructions for more information.
Michael O'Farrell
Posted January 26, 2017
We recently finished our start-of-the-year planning, and here are some of the HHVM open source goals for the first half of 2017. Want to influence our priorities for the coming months? Fill out this survey .
Paul Bissonette
Posted September 15, 2016
The next LTS release of HHVM has been cut and packages are now available for Ubuntu 14.04, 15.04, 15.10, and 16.04; and Debian 7 and 8. This release replaces the 3.9 LTS and brings with it a host of improvements and new features.
Joel Marcey
Posted December 09, 2015
We are happy to announce our next generation of Hack and HHVM user documentation available at http://docs.hhvm.com.
Josh Watzman
Posted December 04, 2015
For those that haven’t been following along, the next version of the PHP language, version 7.0.0, was very recently released. Those of us working on HHVM offer our congratulations to all the contributors to this latest release! We’re all really excited to see this release come out the door, and for what it means for the future of PHP.
Dwayne Reeves
Posted October 30, 2015
“…use collections whenever and wherever possible. However, 100% usage of collections is obviously not realistic given how much arrays are used in various codebases …there just may be legitimate use cases for an array”
This is the guidance given to Hack developers on using arrays. While we still advise using collections whenever possible, in hindsight there are more “legitimate use cases” for arrays than we first believed. With that in mind, the team is planning on improving arrays so they are better supported in Hack. We’ve opened a number of issues on GitHub (#6451, #6452, #6453, #6454, #6455) with our initial plans. Since this would be a significant change in the language we are looking for feedback from the community. Before diving into what we are thinking of building, let’s take some time to examine the problem we want to solve.
Brett Simmers
Posted October 23, 2015
One of the most common questions we get about HHVM is why we don’t use LLVM for code generation. The primary reason has always been that while LLVM is great at optimizing C, C++, Objective-C, and other similar statically-typed languages, PHP is dynamically typed. The kinds of optimizations that provide huge performance benefits for static languages tend to be less useful in dynamic languages, or at least overshadowed by all the dynamic dispatching that’s done based on runtime types. We knew that there was probably something to be gained from using LLVM as a backend, but there were many larger opportunities go after first.
Josh Watzman
Posted October 21, 2015
HHVM 3.10.0 is out! You can get it from the usual places.
Josh Watzman
Posted August 31, 2015
We’re happy to announce official Mac OS X support in HHVM, with version 3.9! If you use Homebrew and want to get started now, the steps to use our official tap are really simple:
1
2
$ brew tap hhvm/hhvm
$ brew install hhvm
Paul Bissonette
Posted August 19, 2015
We’re happy to announce that HHVM 3.9.0 is now available. You can try one of our prebuilt packages for Ubuntu and Debian, or build from source.
Josh Watzman
Posted July 13, 2015
We’re happy to announce that HHVM 3.8.0 is finally available. You can, as always, try one of our prebuilt packages for Ubuntu and Debian, or build from source. (As of this writing, the packages are still building, so if a 3.8.0 package isn’t available for your supported distro, hold tight!)
Josh Watzman
Posted July 07, 2015
We just released HHVM versions 3.3.7, 3.6.5, and 3.7.3 which fix CVE-2015-4663, a serious issue affecting SSL/TLS certificate validation. Note that the issue affects file_get_contents, the stream API, etc, but does not affect anything using the cURL API directly.
Kasper Kopec
Posted June 16, 2015
In PHP, traits are a mechanism of code reuse that, while very powerful, are also difficult to type check both efficiently and exhaustively. In this post we’ll dive more deeply into the reasons for that and see how Hack solves those problems, allowing you to use traits in a safe way without limiting their expressiveness.
Paul Bissonette
Posted June 09, 2015
The HHVM team has concluded its first ever open source performance lockdown, and we’re very excited to share the results with you. During our two week lockdown, we’ve made strides optimizing builtin functions, dynamic properties, string concatenation, and the file cache. In addition to improving HHVM, we also looked for places in the open source frameworks where we could contribute patches that would benefit all engines. Our efforts centered around maximizing requests per second (RPS) with Wordpress, Drupal 7, and MediaWiki, using our oss-performance benchmarking tool.
Jez Ng
Posted May 28, 2015
Hack has recently enhanced its generics with two features: variance annotations and super type constraints. In this post, I’ll explain how they work and why they were added.
Paul Bissonette
Posted May 08, 2015

It’s that time of year again! Next week the HHVM Open Source team is beginning a lockdown. The next two weeks will feature beards, long hours, and performance wins. We’re excited to announce that this will be our first ever open source performance lockdown.
Josh Watzman
Posted May 04, 2015
As some of you have no doubt noticed, HHVM 3.7.0 has been out now for a few days. It comprises the internal “Earle”, “Fry”, “Gadd”, and “Harris” releases.
Owen Yamauchi
Posted April 23, 2015

We’d like to get more developers in the community using Hack. But we know there’s been something lacking: a good, consolidated resource for learning Hack and getting the most use out of it. We have documentation online, but it’s more of a reference than a tutorial.
Josh Watzman
Posted April 06, 2015
Dan Miller, an engineer at Etsy, wrote an extensive blog post detailing Etsy’s transition to HHVM on some of their production servers.
Sara Golemon
Posted March 11, 2015
Announcing the immediate release of HHVM 3.6.0. built upon our internal “Ballmer”, “Colbert”, and “Ditko” releases. This represents our second official LTS release following 6 months after the release of HHVM 3.3.
Joel Marcey
Posted February 19, 2015

Today we are excited to announce the availability of the initial specification for the Hack programming language.
Josh Watzman
Posted February 17, 2015
The next HHVM release, 3.6, is on the horizon. We expect it to be released at the very end of February or in early March. It’s going to be a big release. Not only will it be our second release with long-term support, but it will contain several exciting new features – and lay the groundwork for continued development later this year.
Josh Watzman
Posted January 20, 2015
We have released HHVM 3.5.0 – get it while it’s hot! It contains updates from the “Xzibit”, “Yelawolf”, and “Z*” internal branches – the last of the 2014 rapper theme. It also contains updates from the “Austin” internal branch, the first of the new 2015 theme. (Anyone want to guess at what the new theme is?)
Brett Simmers
Posted January 06, 2015
If you’ve been watching our GitHub wiki, following us on Twitter, or reading the wikitech-l mailing list, you’ve probably known for a while that Wikipedia has been transitioning to HHVM. This has been a long process involving lots of work from many different people, and as of a few weeks ago, all non-cached API and web traffic is being served by HHVM. This blog post from the Wikimedia Foundation contains some details about the switch, as does their page about HHVM.
Josh Watzman
Posted January 06, 2015
I just pushed HHVM 3.3.2 (and 3.4.2) onto the Debian and Ubuntu repositories. It contains fixes backported from PHP for several security issues that HHVM was also vulnerable to, as well as a fix for CVE-2014-9370, which is a header injection issue affecting only the deprecated built-in webserver. Most users of HHVM use FastCGI, which was not affected by CVE-2014-9370.
Sara Golemon
Posted December 05, 2014
For several months now, Hack has had a feature available called async which enables writing code that cooperatively multitasks. This is somewhat similar to threading, in that multiple code paths are executed in parallel, however it avoids the lock contention issues common to multithreaded code by only actually executing one section at any given moment.
Paul Tarjan
Posted November 20, 2014
Two big announcements back to back.
Box announced that they did their cutover to HHVM yesterday seeing their latency drop by 3x. I did a Q & A about HHVM today.
Joel Marcey
Posted November 20, 2014
We have released HHVM 3.4.0, the first minor point release after our HHVM 3.3.0 LTS. This branch contains updates from our T-Pain, Ultramagnetic, Vanilla Ice and Will.i.am internal releases.
Josh Watzman
Posted November 11, 2014
We’re proud to announce the first experimental release of the Hack Transpiler, a tool which allows projects that have converted from PHP to Hack to still make releases that target the PHP language. You can read the full announcement at code.facebook.com, or take a look at the documentation for the tool. It’s available in any nightly package dated today or later. It’s still experimental, so try it out and let us know how it goes!
Josh Watzman
Posted October 29, 2014
A recent addition to Hack is the __ConsistentConstruct attribute, which allows new static() to be safely, properly typed. The need for this special attribute first requires some background in how method overriding and polymorphism normally work, and how constructors are special.
Paul Tarjan
Posted October 28, 2014
Today we released HHVM 3.3.1, our first update to our long term support release. This includes 30 commits.
Fred Emmott
Posted October 23, 2014

XHP is a great way to safely create HTML user interfaces from PHP or Hack. We love how extensible it is, allowing you to create your own pseudo-elements that are composed of more basic building blocks - ultimately a series of HTML tags. This solves a similar problem to partial templates in other systems. At its most basic level, XHP provides an XML-like syntax for creating stringable objects representing markup:
Josh Watzman
Posted October 21, 2014
A lot has happened since we announced Hack. We’ve already highlighted our Hack developer day, as well as posting a series of community roundups (one, two, three) highlighting the projects that our amazing Hack community have been building.
Sara Golemon
Posted October 03, 2014
Compilers are fun. They take nice, human readable languages like PHP or Hack and turn them into lean, mean, CPU executin’ turing machines. Some of these are simple enough a CS student can write one up in a weekend, some are the products of decades of fine tuning and careful architecting. Somewhere in that proud tradition stands HHVM; In fact it’s several compilers stacked in an ever-growing chain of logic manipulation and abstractions. This article will attempt to take the reader through the HHVM compilation process from PHP-script to x86 machine code, one step at a time.
Fred Emmott
Posted September 19, 2014
Today we released HHVM 3.3.0, the first of our releases with long term support (until the August 13th 2015 release - potentially 3.9); some of the highlights:
David Martinez
Posted September 02, 2014
HHVM is known for its very intense and quick development pace: currently we ship to GitHub the exact same code we use to run the Facebook site within minutes of every commit, and we release a full version every 8 weeks. That is great and at the same time scary if you are trying to build a business or infrastructure around it.
Josh Watzman
Posted August 21, 2014
As always, I’m really excited to see what our community has been building and saying, and really exited to share what I’ve seen with everyone!
Joel Marcey
Posted July 30, 2014

The PHP language has been around for over 20 years and is clearly one of the most popular programming languages in the world. PHP is definitely the lingua-franca of the internet for server-side web programming.
Paul Tarjan
Posted July 23, 2014
The next version of HHVM is out (well it came out 6 days ago, I’ve just been at OSCON all week and haven’t had a chance to do this post).
Joel Marcey
Posted July 08, 2014
The HHVM community is awesome, particularly when it comes to directly helping us fix HHVM through pull requests. Until now, the actual pushing of commits (both our internal code and your pull requests) back to the master HHVM branch on GitHub has been a manual process, and takes more time than we would prefer (and I am sure may have frustrated you from time to time).
Josh Watzman
Posted June 25, 2014
Since the last roundup, our community has continued to produce some really cool projects using Hack. I’m really excited to have another long list to share with all of you!
Paul Tarjan
Posted May 29, 2014
The next version of HHVM is hot off the press. After a few delays, we finally tracked down the segfault. We fixed it in master, but turning off the optimizations was safer for the release. Thanks for your patience.
Josh Watzman
Posted May 09, 2014
In the weeks since the Hack open source launch and the Hack developer day, there has been a lot of information, code, blog posts, etc coming from our nascent community. To us on the team, it’s been incredible and encouraging to see the community reception to Hack. Here are some of the highlights of the things we’ve seen come out of our community. (And we almost certainly haven’t seen everything, so please let us know in the comments what we’ve missed!)
Fred Emmott
Posted April 21, 2014
Earlier this year we set an ambitious goal of passing the PHPUnit test suites of 20 popular frameworks by the end of June; at the time, we were passing on only 6! With a huge amount of help from the community (especially our OpenAcademy students), we’re proud to have hit this goal more than 2 months early, and we have more frameworks expected to reach 100% shortly.
Joel Marcey
Posted April 10, 2014
A few weeks ago, the Hack language was launched to the world. Yesterday, we held the first Hack Developer Day in Menlo Park, California. 150+ Members of the PHP and developer community came to Facebook headquarters and joined over 2000 people online for presentations by the engineers of Hack and HHVM. Afterwards we held a five hour hackathon, where the attendees worked with those engineers to write Hack code, either by converting current codebases or writing new code from scratch. By the way, bonus points to anyone who can decrypt the commit message used when Josh originally pushed Hack to open source.
Paul Tarjan
Posted April 07, 2014

We try our best to be a stable dependable runtime, but if you are reaching into the deep dark abyss of the PHP language, you might stumble upon a dark corner where we segfault or assert. First of all, we are sorry. Secondly, we would love you to report the issue, and if you can put together a small test case that is best. If it only reproduces under the full moon when you hold your head to the side and hop on one leg, then a stacktrace would be next best.
Paul Tarjan
Posted March 28, 2014
This is a fun one! :)
At our last major version bump (2.0.0), we basically became a whole new project. We switched from a “PHP -> C++” translator to a virtual machine. This version bump (3.0.0) is a much less dramatic code shift (we’re still a VM, don’t worry), but this time the big announcement is that we support a new language, Hack.
Paul Tarjan
Posted March 21, 2014
Yesterday, after our Hack announcement, we sat down with the heroku team to get Hack working on Heroku. And success! Read all about it over on the heroku blog.
Julien Verlaguet
Posted March 20, 2014
As you may have heard or seen already, the Hack programming language has been released for HHVM. Hack reconciles the fast development cycle of PHP with the discipline provided by static typing, while adding many features commonly found in other modern programming languages.
Paul Tarjan
Posted March 08, 2014
We haven’t done posts for point releases since our normal release schedule is so quick, but when there is a security fix we thought you should know as soon as possible.
Fred Emmott
Posted March 03, 2014
HHVM has a large suite of unit tests that must pass in several build configurations before a commit reaches master. Unfortunately, this test suite passing doesn’t tell you if HHVM can be used for anything useful - so we periodically run the test suites for popular, open source frameworks.
Emil Hesslow
Posted February 26, 2014
I joined the HHVM team right before Christmas for a hackamonth (or, in my case, a hack-a-two-months).
Joel Pobar
Posted February 25, 2014
The HHVM team has just wrapped up its planning for the first half of 2014. We’d like to share our plans, providing you a bit of context.
2014 Themes:
Open Source
Increase Web Efficiency
Make HHVM Hackable
Paul Tarjan
Posted February 01, 2014
It is that wonderful time again for an HHVM release. We’re sticking to our 8 week release cadence to keep everything fresh and in your hands. Also, remember you can run the nightly packages if you want a bleeding edge feature.
Paul Tarjan
Posted January 21, 2014
If you just can’t wait to get your hands on the latest HHVM code, but you don’t want to spend the time to compile it, we have a present for you.
Joel Marcey
Posted December 19, 2013
On November 4th, the HHVM team went on a 3-week performance and parity lockdown. The lockdown officially ended on November 22nd. Overall, this lockdown was a qualified success. Success was measured on 3 vectors:
Julek Kopczewski
Posted December 17, 2013
Today, we are happy to announce FastCGI support for HHVM. FastCGI is a popular protocol for communication between an application server (e.g. running your PHP code) and a webserver. With support for FastCGI, you will be able to run HHVM behind any popular web server (Apache, Nginx, Lighttpd, etc). The webserver is in charge of handling all the intricate details of the HTTP protocol. HHVM is in charge of what it does best, running PHP code blazingly fast.
Paul Tarjan
Posted December 13, 2013
We released a new version of HHVM today. This one includes all the hard work from our lockdown (detailed post to follow) and the ability to use HHVM with FastCGI.
Brett Simmers
Posted December 11, 2013
When the hhvm project was started almost 4 years ago, it had a two-part mandate: First, create a PHP JIT that could serve facebook.com at least as efficiently as hphpc, the PHP execution engine we were using at the time. Second, replace hphpi, the interpreter our PHP developers were using in their daily work. hphpc and hphpi were independent pieces of software with unintentional subtle differences in behavior and a significant maintenance burden. Unifying the execution engines used in production and development would make our jobs easier while giving the PHP devs a nicer experience at the same time. We had to find a balance between reaching these goals as quickly as possible and designing a system that could be extended and improved for many years after it replaced hphpc and hphpi. There were also concerns that just in time compilation might not be fast enough to keep up with Facebook’s aggressive deployment process. We were pushing a new version of the site to our fleet of web servers once every weekday, and the whole process took less than 20 minutes. We had to maintain that ability for hhvm to be a viable option. Taking all this into account, the initial JIT design was the simplest and fastest one that we thought had a good chance of succeeding.
Joel Marcey
Posted November 07, 2013
The HHVM team, along with our wonderful open source contributors, is constantly trying to improve the runtime. We know, however, that there is work to do to run the world’s PHP code reliably and consistently.
Paul Tarjan
Posted October 30, 2013
Do you use heroku to host your PHP app and want to save 2x-10x dynos? Or serve user requests 2x-10x faster? I’m happy to announce that you can now use HHVM on heroku. You should clone your app and try it out before pushing to production as HHVM doesn’t support every possible use of PHP (yet).
Paul Tarjan
Posted October 18, 2013
We released a new version of HHVM today. A big change is that we are now packaging for many of the popular distros.
Joel Marcey
Posted September 12, 2013
HHVM is a highly performant PHP runtime. In fact, it is nearly 40% faster than HPHPc, and only getting faster. For example, the HHVM team just rewrote the JIT to use an SSA intermediate representation (IR). HHIR (HipHop Intermediate Representation) is a strongly typed, SSA-form intermediate representation, positioned between HHBC (HipHop Bytecode) and machine code. It allows HHVM to perform optimizations that were very difficult to perform with the old JIT, using the context of the current runtime environment (e.g., reference counting elision).
Owen Yamauchi
Posted May 29, 2013
HHVM’s JIT compiler allows it to execute PHP faster than Zend PHP in most cases, unmodified. However, we’ve gotten some interest from the community in HipHop-specific optimization tips, so I put together a few for this post.
The principle that underlies all of these tips is: write code that HHVM can understand without running. The more HHVM knows before the code runs, the more it can optimize.
Paul Tarjan
Posted May 13, 2013
First of all, hi. I recently joined the team as you could probably see from my plethora of commits to github. I first fixed up closures a bit and moved our “PHP tests in C++” to have one fewer language. I’ll be doing many exciting things for hiphop but I’ll be mostly caring about making it incredibly easy for anyone to use for any PHP code. So please bug me if it doesn’t run your favorite piece of code.
Sara Golemon
Posted December 11, 2012
HipHop, if properly configured [1], will actually startup not one, but two http servers. The first, on port 80 by default, you’re already familiar with. Requests are translated to filesystem paths, and PHP files are executed to generate content. The other one, however, you might not have come across yet.
Owen Yamauchi
Posted November 29, 2012
In this post, I’ll expand on a topic that I briefly mentioned in the footnote to my previous post: memory management.
Most modern programming languages, including PHP, have automatic memory management. Programmers don’t explicitly free the memory they allocate, and the language runtime does that for them. There are a variety of approaches that language runtimes can take to implement this, and they lie on a spectrum.
Sara Golemon
Posted November 12, 2012
Been getting two or three spam comments/day. They don’t get through because moderation is enabled. They are an annoyance however, so I’ll be passing the annoyance on to you, dear reader, in the form of a very simple CAPTCHA.
Owen Yamauchi
Posted November 09, 2012
As part of our drive to improve HHVM’s performance, I started looking into the general topic of builtin functions. Currently, HHVM is calling implementations of builtin functions that were originally written for HPHPc, the static compiler. We wrote compatibility wrappers around them for HHVM, to get it up and running as quickly as possible. We have evidence that this compatibility layer is hurting HHVM’s performance, so we’re looking at ways to reduce or eliminate its impact.
Sara Golemon
Posted October 22, 2012
If you’ve looked at my previous entry Getting Wordpress Running on HHVM, you’ve already got a general idea for how to create a config.hdf file and get a web server up and running. Now you want to make sure it’s running as quickly, and efficiently as possible. But first, it’s worth understanding how HHVM runs your PHP scripts.
Sara Golemon
Posted September 24, 2012
This article aims to walk through the installation process for getting WordPress running on HHVM (HipHop Virtual Machine).
Sara Golemon
Posted September 22, 2012

Welcome to the inaugural post on the HipHop for PHP blog. In the coming days, weeks, months, and (dare I predict) years, we’ll be creating posts about the inner workings of HipHop, the practical implementation details of running it, and whatever else manages to fit on this site.
So sit back, add us to your RSS reader, and enjoy.