diff options
| author | nsfisis <nsfisis@gmail.com> | 2025-04-03 01:43:04 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2025-04-03 01:45:03 +0900 |
| commit | 6233331f23603ebab0a7aa626ff82d71426b3bd6 (patch) | |
| tree | 490affe4d44e251c996502847c2d87ed9d8cab17 | |
| parent | 44655d7a70ee5fd288f691a41631e8a6471d084d (diff) | |
| download | php-waddiwasi-6233331f23603ebab0a7aa626ff82d71426b3bd6.tar.gz php-waddiwasi-6233331f23603ebab0a7aa626ff82d71426b3bd6.tar.zst php-waddiwasi-6233331f23603ebab0a7aa626ff82d71426b3bd6.zip | |
feat: update php and package version
| -rw-r--r-- | TODO | 1 | ||||
| -rw-r--r-- | composer.json | 10 | ||||
| -rw-r--r-- | composer.lock | 621 | ||||
| -rw-r--r-- | examples/compile-php-to-wasm/Dockerfile | 4 | ||||
| -rw-r--r-- | examples/compile-php-to-wasm/php-wasm.js | 992 | ||||
| -rwxr-xr-x | examples/compile-php-to-wasm/php-wasm.wasm | bin | 4941810 -> 5088262 bytes | |||
| -rw-r--r-- | examples/php-on-wasm/php-wasm.php | 52 | ||||
| -rw-r--r-- | examples/rubyvm-on-php-on-wasm/php-wasm.php | 52 | ||||
| -rw-r--r-- | src/WebAssembly/BinaryFormat/Decoder.php | 2 | ||||
| -rw-r--r-- | src/WebAssembly/Execution/MemInst.php | 59 | ||||
| -rw-r--r-- | src/WebAssembly/Execution/StackOverflowException.php | 2 |
11 files changed, 893 insertions, 902 deletions
@@ -1,4 +1,3 @@ -* Support PHP 8.4 * Support text format (.wat) * Implement validation * Fix known bugs (BUGS) diff --git a/composer.json b/composer.json index b52fdf8..4b1c171 100644 --- a/composer.json +++ b/composer.json @@ -16,12 +16,12 @@ }, "require-dev": { "m3m0r7/rubyvm-on-php": "^0.3.3", - "phpstan/phpstan": "^1.12.0", - "phpstan/phpstan-deprecation-rules": "^1.2.0", - "phpstan/phpstan-strict-rules": "^1.6.0", - "phpunit/phpunit": "^11.3.1", + "phpstan/phpstan": "^1.12.23", + "phpstan/phpstan-deprecation-rules": "^1.2.1", + "phpstan/phpstan-strict-rules": "^1.6.2", + "phpunit/phpunit": "^11.5.15", "reliforp/reli-prof": "0.12.x-dev", - "symplify/easy-coding-standard": "^12.3.5" + "symplify/easy-coding-standard": "^12.5.11" }, "config": { "preferred-install": "dist", diff --git a/composer.lock b/composer.lock index e245f31..47cb3b6 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "02dabac18e30f5651aa264e75241034f", + "content-hash": "5bdf3a9814794abff1d728afd94ae1bf", "packages": [], "packages-dev": [ { @@ -90,16 +90,16 @@ }, { "name": "amphp/byte-stream", - "version": "v2.1.1", + "version": "v2.1.2", "source": { "type": "git", "url": "https://github.com/amphp/byte-stream.git", - "reference": "daa00f2efdbd71565bf64ffefa89e37542addf93" + "reference": "55a6bd071aec26fa2a3e002618c20c35e3df1b46" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/amphp/byte-stream/zipball/daa00f2efdbd71565bf64ffefa89e37542addf93", - "reference": "daa00f2efdbd71565bf64ffefa89e37542addf93", + "url": "https://api.github.com/repos/amphp/byte-stream/zipball/55a6bd071aec26fa2a3e002618c20c35e3df1b46", + "reference": "55a6bd071aec26fa2a3e002618c20c35e3df1b46", "shasum": "" }, "require": { @@ -153,7 +153,7 @@ ], "support": { "issues": "https://github.com/amphp/byte-stream/issues", - "source": "https://github.com/amphp/byte-stream/tree/v2.1.1" + "source": "https://github.com/amphp/byte-stream/tree/v2.1.2" }, "funding": [ { @@ -161,7 +161,7 @@ "type": "github" } ], - "time": "2024-02-17T04:49:38+00:00" + "time": "2025-03-16T17:10:27+00:00" }, { "name": "amphp/cache", @@ -230,16 +230,16 @@ }, { "name": "amphp/dns", - "version": "v2.2.0", + "version": "v2.4.0", "source": { "type": "git", "url": "https://github.com/amphp/dns.git", - "reference": "758266b0ea7470e2e42cd098493bc6d6c7100cf7" + "reference": "78eb3db5fc69bf2fc0cb503c4fcba667bc223c71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/amphp/dns/zipball/758266b0ea7470e2e42cd098493bc6d6c7100cf7", - "reference": "758266b0ea7470e2e42cd098493bc6d6c7100cf7", + "url": "https://api.github.com/repos/amphp/dns/zipball/78eb3db5fc69bf2fc0cb503c4fcba667bc223c71", + "reference": "78eb3db5fc69bf2fc0cb503c4fcba667bc223c71", "shasum": "" }, "require": { @@ -247,9 +247,10 @@ "amphp/byte-stream": "^2", "amphp/cache": "^2", "amphp/parser": "^1", - "amphp/windows-registry": "^1.0.1", + "amphp/process": "^2", "daverandom/libdns": "^2.0.2", "ext-filter": "*", + "ext-json": "*", "php": ">=8.1", "revolt/event-loop": "^1 || ^0.2" }, @@ -306,7 +307,7 @@ ], "support": { "issues": "https://github.com/amphp/dns/issues", - "source": "https://github.com/amphp/dns/tree/v2.2.0" + "source": "https://github.com/amphp/dns/tree/v2.4.0" }, "funding": [ { @@ -314,20 +315,20 @@ "type": "github" } ], - "time": "2024-06-02T19:54:12+00:00" + "time": "2025-01-19T15:43:40+00:00" }, { "name": "amphp/parallel", - "version": "v2.2.9", + "version": "v2.3.1", "source": { "type": "git", "url": "https://github.com/amphp/parallel.git", - "reference": "73d293f1fc4df1bebc3c4fce1432e82dd7032238" + "reference": "5113111de02796a782f5d90767455e7391cca190" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/amphp/parallel/zipball/73d293f1fc4df1bebc3c4fce1432e82dd7032238", - "reference": "73d293f1fc4df1bebc3c4fce1432e82dd7032238", + "url": "https://api.github.com/repos/amphp/parallel/zipball/5113111de02796a782f5d90767455e7391cca190", + "reference": "5113111de02796a782f5d90767455e7391cca190", "shasum": "" }, "require": { @@ -390,7 +391,7 @@ ], "support": { "issues": "https://github.com/amphp/parallel/issues", - "source": "https://github.com/amphp/parallel/tree/v2.2.9" + "source": "https://github.com/amphp/parallel/tree/v2.3.1" }, "funding": [ { @@ -398,7 +399,7 @@ "type": "github" } ], - "time": "2024-03-24T18:27:44+00:00" + "time": "2024-12-21T01:56:09+00:00" }, { "name": "amphp/parser", @@ -464,16 +465,16 @@ }, { "name": "amphp/pipeline", - "version": "v1.2.1", + "version": "v1.2.3", "source": { "type": "git", "url": "https://github.com/amphp/pipeline.git", - "reference": "66c095673aa5b6e689e63b52d19e577459129ab3" + "reference": "7b52598c2e9105ebcddf247fc523161581930367" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/amphp/pipeline/zipball/66c095673aa5b6e689e63b52d19e577459129ab3", - "reference": "66c095673aa5b6e689e63b52d19e577459129ab3", + "url": "https://api.github.com/repos/amphp/pipeline/zipball/7b52598c2e9105ebcddf247fc523161581930367", + "reference": "7b52598c2e9105ebcddf247fc523161581930367", "shasum": "" }, "require": { @@ -519,7 +520,7 @@ ], "support": { "issues": "https://github.com/amphp/pipeline/issues", - "source": "https://github.com/amphp/pipeline/tree/v1.2.1" + "source": "https://github.com/amphp/pipeline/tree/v1.2.3" }, "funding": [ { @@ -527,7 +528,7 @@ "type": "github" } ], - "time": "2024-07-04T00:56:47+00:00" + "time": "2025-03-16T16:33:53+00:00" }, { "name": "amphp/process", @@ -815,58 +816,6 @@ "time": "2024-08-03T19:31:26+00:00" }, { - "name": "amphp/windows-registry", - "version": "v1.0.1", - "source": { - "type": "git", - "url": "https://github.com/amphp/windows-registry.git", - "reference": "0d569e8f256cca974e3842b6e78b4e434bf98306" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/windows-registry/zipball/0d569e8f256cca974e3842b6e78b4e434bf98306", - "reference": "0d569e8f256cca974e3842b6e78b4e434bf98306", - "shasum": "" - }, - "require": { - "amphp/byte-stream": "^2", - "amphp/process": "^2", - "php": ">=8.1" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "^2", - "psalm/phar": "^5.4" - }, - "type": "library", - "autoload": { - "psr-4": { - "Amp\\WindowsRegistry\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "Windows Registry Reader.", - "support": { - "issues": "https://github.com/amphp/windows-registry/issues", - "source": "https://github.com/amphp/windows-registry/tree/v1.0.1" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2024-01-30T23:01:51+00:00" - }, - { "name": "daverandom/libdns", "version": "v2.1.0", "source": { @@ -912,16 +861,16 @@ }, { "name": "hassankhan/config", - "version": "3.1.0", + "version": "3.2.0", "source": { "type": "git", "url": "https://github.com/hassankhan/config.git", - "reference": "8e1c07f4fdc2b986b8a781f0dcba155af2a579b6" + "reference": "cf63da451c4d226df983017932b9cef1b6d49db5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/hassankhan/config/zipball/8e1c07f4fdc2b986b8a781f0dcba155af2a579b6", - "reference": "8e1c07f4fdc2b986b8a781f0dcba155af2a579b6", + "url": "https://api.github.com/repos/hassankhan/config/zipball/cf63da451c4d226df983017932b9cef1b6d49db5", + "reference": "cf63da451c4d226df983017932b9cef1b6d49db5", "shasum": "" }, "require": { @@ -968,9 +917,9 @@ ], "support": { "issues": "https://github.com/hassankhan/config/issues", - "source": "https://github.com/hassankhan/config/tree/3.1.0" + "source": "https://github.com/hassankhan/config/tree/3.2.0" }, - "time": "2022-12-20T19:48:37+00:00" + "time": "2024-12-09T16:20:44+00:00" }, { "name": "kelunik/certificate", @@ -1032,16 +981,16 @@ }, { "name": "laravel/serializable-closure", - "version": "v1.3.4", + "version": "v1.3.7", "source": { "type": "git", "url": "https://github.com/laravel/serializable-closure.git", - "reference": "61b87392d986dc49ad5ef64e75b1ff5fee24ef81" + "reference": "4f48ade902b94323ca3be7646db16209ec76be3d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/61b87392d986dc49ad5ef64e75b1ff5fee24ef81", - "reference": "61b87392d986dc49ad5ef64e75b1ff5fee24ef81", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/4f48ade902b94323ca3be7646db16209ec76be3d", + "reference": "4f48ade902b94323ca3be7646db16209ec76be3d", "shasum": "" }, "require": { @@ -1089,24 +1038,24 @@ "issues": "https://github.com/laravel/serializable-closure/issues", "source": "https://github.com/laravel/serializable-closure" }, - "time": "2024-08-02T07:48:17+00:00" + "time": "2024-11-14T18:34:49+00:00" }, { "name": "league/uri", - "version": "7.4.1", + "version": "7.5.1", "source": { "type": "git", "url": "https://github.com/thephpleague/uri.git", - "reference": "bedb6e55eff0c933668addaa7efa1e1f2c417cc4" + "reference": "81fb5145d2644324614cc532b28efd0215bda430" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/uri/zipball/bedb6e55eff0c933668addaa7efa1e1f2c417cc4", - "reference": "bedb6e55eff0c933668addaa7efa1e1f2c417cc4", + "url": "https://api.github.com/repos/thephpleague/uri/zipball/81fb5145d2644324614cc532b28efd0215bda430", + "reference": "81fb5145d2644324614cc532b28efd0215bda430", "shasum": "" }, "require": { - "league/uri-interfaces": "^7.3", + "league/uri-interfaces": "^7.5", "php": "^8.1" }, "conflict": { @@ -1171,7 +1120,7 @@ "docs": "https://uri.thephpleague.com", "forum": "https://thephpleague.slack.com", "issues": "https://github.com/thephpleague/uri-src/issues", - "source": "https://github.com/thephpleague/uri/tree/7.4.1" + "source": "https://github.com/thephpleague/uri/tree/7.5.1" }, "funding": [ { @@ -1179,20 +1128,20 @@ "type": "github" } ], - "time": "2024-03-23T07:42:40+00:00" + "time": "2024-12-08T08:40:02+00:00" }, { "name": "league/uri-interfaces", - "version": "7.4.1", + "version": "7.5.0", "source": { "type": "git", "url": "https://github.com/thephpleague/uri-interfaces.git", - "reference": "8d43ef5c841032c87e2de015972c06f3865ef718" + "reference": "08cfc6c4f3d811584fb09c37e2849e6a7f9b0742" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/8d43ef5c841032c87e2de015972c06f3865ef718", - "reference": "8d43ef5c841032c87e2de015972c06f3865ef718", + "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/08cfc6c4f3d811584fb09c37e2849e6a7f9b0742", + "reference": "08cfc6c4f3d811584fb09c37e2849e6a7f9b0742", "shasum": "" }, "require": { @@ -1255,7 +1204,7 @@ "docs": "https://uri.thephpleague.com", "forum": "https://thephpleague.slack.com", "issues": "https://github.com/thephpleague/uri-src/issues", - "source": "https://github.com/thephpleague/uri-interfaces/tree/7.4.1" + "source": "https://github.com/thephpleague/uri-interfaces/tree/7.5.0" }, "funding": [ { @@ -1263,7 +1212,7 @@ "type": "github" } ], - "time": "2024-03-23T07:42:40+00:00" + "time": "2024-12-08T08:18:47+00:00" }, { "name": "m3m0r7/rubyvm-on-php", @@ -1315,16 +1264,16 @@ }, { "name": "monolog/monolog", - "version": "3.6.0", + "version": "3.8.1", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "4b18b21a5527a3d5ffdac2fd35d3ab25a9597654" + "reference": "aef6ee73a77a66e404dd6540934a9ef1b3c855b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/4b18b21a5527a3d5ffdac2fd35d3ab25a9597654", - "reference": "4b18b21a5527a3d5ffdac2fd35d3ab25a9597654", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/aef6ee73a77a66e404dd6540934a9ef1b3c855b4", + "reference": "aef6ee73a77a66e404dd6540934a9ef1b3c855b4", "shasum": "" }, "require": { @@ -1344,12 +1293,14 @@ "guzzlehttp/psr7": "^2.2", "mongodb/mongodb": "^1.8", "php-amqplib/php-amqplib": "~2.4 || ^3", - "phpstan/phpstan": "^1.9", - "phpstan/phpstan-deprecation-rules": "^1.0", - "phpstan/phpstan-strict-rules": "^1.4", - "phpunit/phpunit": "^10.5.17", + "php-console/php-console": "^3.1.8", + "phpstan/phpstan": "^2", + "phpstan/phpstan-deprecation-rules": "^2", + "phpstan/phpstan-strict-rules": "^2", + "phpunit/phpunit": "^10.5.17 || ^11.0.7", "predis/predis": "^1.1 || ^2", - "ruflin/elastica": "^7", + "rollbar/rollbar": "^4.0", + "ruflin/elastica": "^7 || ^8", "symfony/mailer": "^5.4 || ^6", "symfony/mime": "^5.4 || ^6" }, @@ -1400,7 +1351,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/3.6.0" + "source": "https://github.com/Seldaek/monolog/tree/3.8.1" }, "funding": [ { @@ -1412,20 +1363,20 @@ "type": "tidelift" } ], - "time": "2024-04-12T21:02:21+00:00" + "time": "2024-12-05T17:15:07+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.12.0", + "version": "1.13.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c" + "reference": "024473a478be9df5fdaca2c793f2232fe788e414" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", - "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/024473a478be9df5fdaca2c793f2232fe788e414", + "reference": "024473a478be9df5fdaca2c793f2232fe788e414", "shasum": "" }, "require": { @@ -1464,7 +1415,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.0" }, "funding": [ { @@ -1472,20 +1423,20 @@ "type": "tidelift" } ], - "time": "2024-06-12T14:39:25+00:00" + "time": "2025-02-12T12:17:51+00:00" }, { "name": "nikic/php-parser", - "version": "v5.1.0", + "version": "v5.4.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1" + "reference": "447a020a1f875a434d62f2a401f53b82a396e494" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/683130c2ff8c2739f4822ff7ac5c873ec529abd1", - "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/447a020a1f875a434d62f2a401f53b82a396e494", + "reference": "447a020a1f875a434d62f2a401f53b82a396e494", "shasum": "" }, "require": { @@ -1528,9 +1479,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.1.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.4.0" }, - "time": "2024-07-01T20:03:41+00:00" + "time": "2024-12-30T11:07:19+00:00" }, { "name": "phar-io/manifest", @@ -1652,16 +1603,16 @@ }, { "name": "php-di/invoker", - "version": "2.3.4", + "version": "2.3.6", "source": { "type": "git", "url": "https://github.com/PHP-DI/Invoker.git", - "reference": "33234b32dafa8eb69202f950a1fc92055ed76a86" + "reference": "59f15608528d8a8838d69b422a919fd6b16aa576" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-DI/Invoker/zipball/33234b32dafa8eb69202f950a1fc92055ed76a86", - "reference": "33234b32dafa8eb69202f950a1fc92055ed76a86", + "url": "https://api.github.com/repos/PHP-DI/Invoker/zipball/59f15608528d8a8838d69b422a919fd6b16aa576", + "reference": "59f15608528d8a8838d69b422a919fd6b16aa576", "shasum": "" }, "require": { @@ -1695,7 +1646,7 @@ ], "support": { "issues": "https://github.com/PHP-DI/Invoker/issues", - "source": "https://github.com/PHP-DI/Invoker/tree/2.3.4" + "source": "https://github.com/PHP-DI/Invoker/tree/2.3.6" }, "funding": [ { @@ -1703,20 +1654,20 @@ "type": "github" } ], - "time": "2023-09-08T09:24:21+00:00" + "time": "2025-01-17T12:49:27+00:00" }, { "name": "php-di/php-di", - "version": "7.0.6", + "version": "7.0.7", "source": { "type": "git", "url": "https://github.com/PHP-DI/PHP-DI.git", - "reference": "8097948a89f6ec782839b3e958432f427cac37fd" + "reference": "e87435e3c0e8f22977adc5af0d5cdcc467e15cf1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-DI/PHP-DI/zipball/8097948a89f6ec782839b3e958432f427cac37fd", - "reference": "8097948a89f6ec782839b3e958432f427cac37fd", + "url": "https://api.github.com/repos/PHP-DI/PHP-DI/zipball/e87435e3c0e8f22977adc5af0d5cdcc467e15cf1", + "reference": "e87435e3c0e8f22977adc5af0d5cdcc467e15cf1", "shasum": "" }, "require": { @@ -1764,7 +1715,7 @@ ], "support": { "issues": "https://github.com/PHP-DI/PHP-DI/issues", - "source": "https://github.com/PHP-DI/PHP-DI/tree/7.0.6" + "source": "https://github.com/PHP-DI/PHP-DI/tree/7.0.7" }, "funding": [ { @@ -1776,20 +1727,20 @@ "type": "tidelift" } ], - "time": "2023-11-02T10:04:50+00:00" + "time": "2024-07-21T15:55:45+00:00" }, { "name": "phpstan/phpstan", - "version": "1.12.0", + "version": "1.12.23", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "384af967d35b2162f69526c7276acadce534d0e1" + "reference": "29201e7a743a6ab36f91394eab51889a82631428" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/384af967d35b2162f69526c7276acadce534d0e1", - "reference": "384af967d35b2162f69526c7276acadce534d0e1", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/29201e7a743a6ab36f91394eab51889a82631428", + "reference": "29201e7a743a6ab36f91394eab51889a82631428", "shasum": "" }, "require": { @@ -1834,25 +1785,25 @@ "type": "github" } ], - "time": "2024-08-27T09:18:05+00:00" + "time": "2025-03-23T14:57:32+00:00" }, { "name": "phpstan/phpstan-deprecation-rules", - "version": "1.2.0", + "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-deprecation-rules.git", - "reference": "fa8cce7720fa782899a0aa97b6a41225d1bb7b26" + "reference": "f94d246cc143ec5a23da868f8f7e1393b50eaa82" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/fa8cce7720fa782899a0aa97b6a41225d1bb7b26", - "reference": "fa8cce7720fa782899a0aa97b6a41225d1bb7b26", + "url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/f94d246cc143ec5a23da868f8f7e1393b50eaa82", + "reference": "f94d246cc143ec5a23da868f8f7e1393b50eaa82", "shasum": "" }, "require": { "php": "^7.2 || ^8.0", - "phpstan/phpstan": "^1.11" + "phpstan/phpstan": "^1.12" }, "require-dev": { "php-parallel-lint/php-parallel-lint": "^1.2", @@ -1879,27 +1830,27 @@ "description": "PHPStan rules for detecting usage of deprecated classes, methods, properties, constants and traits.", "support": { "issues": "https://github.com/phpstan/phpstan-deprecation-rules/issues", - "source": "https://github.com/phpstan/phpstan-deprecation-rules/tree/1.2.0" + "source": "https://github.com/phpstan/phpstan-deprecation-rules/tree/1.2.1" }, - "time": "2024-04-20T06:39:48+00:00" + "time": "2024-09-11T15:52:35+00:00" }, { "name": "phpstan/phpstan-strict-rules", - "version": "1.6.0", + "version": "1.6.2", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-strict-rules.git", - "reference": "363f921dd8441777d4fc137deb99beb486c77df1" + "reference": "b564ca479e7e735f750aaac4935af965572a7845" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/363f921dd8441777d4fc137deb99beb486c77df1", - "reference": "363f921dd8441777d4fc137deb99beb486c77df1", + "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/b564ca479e7e735f750aaac4935af965572a7845", + "reference": "b564ca479e7e735f750aaac4935af965572a7845", "shasum": "" }, "require": { "php": "^7.2 || ^8.0", - "phpstan/phpstan": "^1.11" + "phpstan/phpstan": "^1.12.4" }, "require-dev": { "nikic/php-parser": "^4.13.0", @@ -1928,41 +1879,41 @@ "description": "Extra strict and opinionated rules for PHPStan", "support": { "issues": "https://github.com/phpstan/phpstan-strict-rules/issues", - "source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.6.0" + "source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.6.2" }, - "time": "2024-04-20T06:37:51+00:00" + "time": "2025-01-19T13:02:24+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "11.0.6", + "version": "11.0.9", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "ebdffc9e09585dafa71b9bffcdb0a229d4704c45" + "reference": "14d63fbcca18457e49c6f8bebaa91a87e8e188d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ebdffc9e09585dafa71b9bffcdb0a229d4704c45", - "reference": "ebdffc9e09585dafa71b9bffcdb0a229d4704c45", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/14d63fbcca18457e49c6f8bebaa91a87e8e188d7", + "reference": "14d63fbcca18457e49c6f8bebaa91a87e8e188d7", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^5.1.0", + "nikic/php-parser": "^5.4.0", "php": ">=8.2", - "phpunit/php-file-iterator": "^5.0.1", + "phpunit/php-file-iterator": "^5.1.0", "phpunit/php-text-template": "^4.0.1", "sebastian/code-unit-reverse-lookup": "^4.0.1", "sebastian/complexity": "^4.0.1", "sebastian/environment": "^7.2.0", "sebastian/lines-of-code": "^3.0.1", - "sebastian/version": "^5.0.1", + "sebastian/version": "^5.0.2", "theseer/tokenizer": "^1.2.3" }, "require-dev": { - "phpunit/phpunit": "^11.0" + "phpunit/phpunit": "^11.5.2" }, "suggest": { "ext-pcov": "PHP extension that provides line coverage", @@ -2000,7 +1951,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.6" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.9" }, "funding": [ { @@ -2008,7 +1959,7 @@ "type": "github" } ], - "time": "2024-08-22T04:37:56+00:00" + "time": "2025-02-25T13:26:39+00:00" }, { "name": "phpunit/php-file-iterator", @@ -2257,16 +2208,16 @@ }, { "name": "phpunit/phpunit", - "version": "11.3.1", + "version": "11.5.15", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "fe179875ef0c14e90b75617002767eae0a742641" + "reference": "4b6a4ee654e5e0c5e1f17e2f83c0f4c91dee1f9c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fe179875ef0c14e90b75617002767eae0a742641", - "reference": "fe179875ef0c14e90b75617002767eae0a742641", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/4b6a4ee654e5e0c5e1f17e2f83c0f4c91dee1f9c", + "reference": "4b6a4ee654e5e0c5e1f17e2f83c0f4c91dee1f9c", "shasum": "" }, "require": { @@ -2276,25 +2227,26 @@ "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.12.0", + "myclabs/deep-copy": "^1.13.0", "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", "php": ">=8.2", - "phpunit/php-code-coverage": "^11.0.5", - "phpunit/php-file-iterator": "^5.0.1", + "phpunit/php-code-coverage": "^11.0.9", + "phpunit/php-file-iterator": "^5.1.0", "phpunit/php-invoker": "^5.0.1", "phpunit/php-text-template": "^4.0.1", "phpunit/php-timer": "^7.0.1", "sebastian/cli-parser": "^3.0.2", - "sebastian/code-unit": "^3.0.1", - "sebastian/comparator": "^6.0.2", + "sebastian/code-unit": "^3.0.3", + "sebastian/comparator": "^6.3.1", "sebastian/diff": "^6.0.2", "sebastian/environment": "^7.2.0", - "sebastian/exporter": "^6.1.3", + "sebastian/exporter": "^6.3.0", "sebastian/global-state": "^7.0.2", "sebastian/object-enumerator": "^6.0.1", - "sebastian/type": "^5.0.1", - "sebastian/version": "^5.0.1" + "sebastian/type": "^5.1.2", + "sebastian/version": "^5.0.2", + "staabm/side-effects-detector": "^1.0.5" }, "suggest": { "ext-soap": "To be able to generate mocks based on WSDL files" @@ -2305,7 +2257,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "11.3-dev" + "dev-main": "11.5-dev" } }, "autoload": { @@ -2337,7 +2289,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/11.3.1" + "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.15" }, "funding": [ { @@ -2353,7 +2305,7 @@ "type": "tidelift" } ], - "time": "2024-08-13T06:14:23+00:00" + "time": "2025-03-23T16:02:11+00:00" }, { "name": "psr/container", @@ -2518,16 +2470,16 @@ }, { "name": "psr/log", - "version": "3.0.1", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "79dff0b268932c640297f5208d6298f71855c03e" + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/79dff0b268932c640297f5208d6298f71855c03e", - "reference": "79dff0b268932c640297f5208d6298f71855c03e", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", "shasum": "" }, "require": { @@ -2562,9 +2514,9 @@ "psr-3" ], "support": { - "source": "https://github.com/php-fig/log/tree/3.0.1" + "source": "https://github.com/php-fig/log/tree/3.0.2" }, - "time": "2024-08-21T13:31:24+00:00" + "time": "2024-09-11T13:17:53+00:00" }, { "name": "reliforp/reli-prof", @@ -2572,25 +2524,25 @@ "source": { "type": "git", "url": "https://github.com/reliforp/reli-prof.git", - "reference": "a9511b5b18da6da91e3d938b164a04a23a57c928" + "reference": "9bdf8e9a7d0e05ddbc8110b526d23ae0e49935f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reliforp/reli-prof/zipball/a9511b5b18da6da91e3d938b164a04a23a57c928", - "reference": "a9511b5b18da6da91e3d938b164a04a23a57c928", + "url": "https://api.github.com/repos/reliforp/reli-prof/zipball/9bdf8e9a7d0e05ddbc8110b526d23ae0e49935f7", + "reference": "9bdf8e9a7d0e05ddbc8110b526d23ae0e49935f7", "shasum": "" }, "require": { "amphp/amp": "3.0.2", - "amphp/parallel": "2.2.9", + "amphp/parallel": "2.3.1", "ext-ffi": "*", "ext-filter": "*", "ext-json": "*", "ext-pcntl": "*", - "hassankhan/config": "3.1.0", - "monolog/monolog": "3.6.0", + "hassankhan/config": "3.2.0", + "monolog/monolog": "3.8.1", "php": "^8.1", - "php-di/php-di": "7.0.6", + "php-di/php-di": "7.0.7", "sj-i/php-cast": "1.0.0", "symfony/console": "6.3.8", "webmozart/assert": "1.11.0" @@ -2637,20 +2589,20 @@ "issues": "https://github.com/reliforp/reli-prof/issues", "source": "https://github.com/reliforp/reli-prof/tree/0.12.x" }, - "time": "2024-06-01T14:08:21+00:00" + "time": "2025-01-20T15:06:42+00:00" }, { "name": "revolt/event-loop", - "version": "v1.0.6", + "version": "v1.0.7", "source": { "type": "git", "url": "https://github.com/revoltphp/event-loop.git", - "reference": "25de49af7223ba039f64da4ae9a28ec2d10d0254" + "reference": "09bf1bf7f7f574453efe43044b06fafe12216eb3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/revoltphp/event-loop/zipball/25de49af7223ba039f64da4ae9a28ec2d10d0254", - "reference": "25de49af7223ba039f64da4ae9a28ec2d10d0254", + "url": "https://api.github.com/repos/revoltphp/event-loop/zipball/09bf1bf7f7f574453efe43044b06fafe12216eb3", + "reference": "09bf1bf7f7f574453efe43044b06fafe12216eb3", "shasum": "" }, "require": { @@ -2707,9 +2659,9 @@ ], "support": { "issues": "https://github.com/revoltphp/event-loop/issues", - "source": "https://github.com/revoltphp/event-loop/tree/v1.0.6" + "source": "https://github.com/revoltphp/event-loop/tree/v1.0.7" }, - "time": "2023-11-30T05:34:44+00:00" + "time": "2025-01-25T19:27:39+00:00" }, { "name": "sebastian/cli-parser", @@ -2770,23 +2722,23 @@ }, { "name": "sebastian/code-unit", - "version": "3.0.1", + "version": "3.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "6bb7d09d6623567178cf54126afa9c2310114268" + "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/6bb7d09d6623567178cf54126afa9c2310114268", - "reference": "6bb7d09d6623567178cf54126afa9c2310114268", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/54391c61e4af8078e5b276ab082b6d3c54c9ad64", + "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64", "shasum": "" }, "require": { "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^11.0" + "phpunit/phpunit": "^11.5" }, "type": "library", "extra": { @@ -2815,7 +2767,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/code-unit/issues", "security": "https://github.com/sebastianbergmann/code-unit/security/policy", - "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.1" + "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.3" }, "funding": [ { @@ -2823,7 +2775,7 @@ "type": "github" } ], - "time": "2024-07-03T04:44:28+00:00" + "time": "2025-03-19T07:56:08+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -2883,16 +2835,16 @@ }, { "name": "sebastian/comparator", - "version": "6.0.2", + "version": "6.3.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "450d8f237bd611c45b5acf0733ce43e6bb280f81" + "reference": "24b8fbc2c8e201bb1308e7b05148d6ab393b6959" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/450d8f237bd611c45b5acf0733ce43e6bb280f81", - "reference": "450d8f237bd611c45b5acf0733ce43e6bb280f81", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/24b8fbc2c8e201bb1308e7b05148d6ab393b6959", + "reference": "24b8fbc2c8e201bb1308e7b05148d6ab393b6959", "shasum": "" }, "require": { @@ -2903,12 +2855,15 @@ "sebastian/exporter": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^11.0" + "phpunit/phpunit": "^11.4" + }, + "suggest": { + "ext-bcmath": "For comparing BcMath\\Number objects" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "6.0-dev" + "dev-main": "6.3-dev" } }, "autoload": { @@ -2948,7 +2903,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", "security": "https://github.com/sebastianbergmann/comparator/security/policy", - "source": "https://github.com/sebastianbergmann/comparator/tree/6.0.2" + "source": "https://github.com/sebastianbergmann/comparator/tree/6.3.1" }, "funding": [ { @@ -2956,7 +2911,7 @@ "type": "github" } ], - "time": "2024-08-12T06:07:25+00:00" + "time": "2025-03-07T06:57:01+00:00" }, { "name": "sebastian/complexity", @@ -3149,16 +3104,16 @@ }, { "name": "sebastian/exporter", - "version": "6.1.3", + "version": "6.3.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e" + "reference": "3473f61172093b2da7de1fb5782e1f24cc036dc3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e", - "reference": "c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/3473f61172093b2da7de1fb5782e1f24cc036dc3", + "reference": "3473f61172093b2da7de1fb5782e1f24cc036dc3", "shasum": "" }, "require": { @@ -3167,7 +3122,7 @@ "sebastian/recursion-context": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^11.2" + "phpunit/phpunit": "^11.3" }, "type": "library", "extra": { @@ -3215,7 +3170,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", "security": "https://github.com/sebastianbergmann/exporter/security/policy", - "source": "https://github.com/sebastianbergmann/exporter/tree/6.1.3" + "source": "https://github.com/sebastianbergmann/exporter/tree/6.3.0" }, "funding": [ { @@ -3223,7 +3178,7 @@ "type": "github" } ], - "time": "2024-07-03T04:56:19+00:00" + "time": "2024-12-05T09:17:50+00:00" }, { "name": "sebastian/global-state", @@ -3525,28 +3480,28 @@ }, { "name": "sebastian/type", - "version": "5.0.1", + "version": "5.1.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "fb6a6566f9589e86661291d13eba708cce5eb4aa" + "reference": "a8a7e30534b0eb0c77cd9d07e82de1a114389f5e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb6a6566f9589e86661291d13eba708cce5eb4aa", - "reference": "fb6a6566f9589e86661291d13eba708cce5eb4aa", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/a8a7e30534b0eb0c77cd9d07e82de1a114389f5e", + "reference": "a8a7e30534b0eb0c77cd9d07e82de1a114389f5e", "shasum": "" }, "require": { "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^11.0" + "phpunit/phpunit": "^11.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-main": "5.1-dev" } }, "autoload": { @@ -3570,7 +3525,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/type/issues", "security": "https://github.com/sebastianbergmann/type/security/policy", - "source": "https://github.com/sebastianbergmann/type/tree/5.0.1" + "source": "https://github.com/sebastianbergmann/type/tree/5.1.2" }, "funding": [ { @@ -3578,20 +3533,20 @@ "type": "github" } ], - "time": "2024-07-03T05:11:49+00:00" + "time": "2025-03-18T13:35:50+00:00" }, { "name": "sebastian/version", - "version": "5.0.1", + "version": "5.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "45c9debb7d039ce9b97de2f749c2cf5832a06ac4" + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/45c9debb7d039ce9b97de2f749c2cf5832a06ac4", - "reference": "45c9debb7d039ce9b97de2f749c2cf5832a06ac4", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c687e3387b99f5b03b6caa64c74b63e2936ff874", + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874", "shasum": "" }, "require": { @@ -3624,7 +3579,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/version/issues", "security": "https://github.com/sebastianbergmann/version/security/policy", - "source": "https://github.com/sebastianbergmann/version/tree/5.0.1" + "source": "https://github.com/sebastianbergmann/version/tree/5.0.2" }, "funding": [ { @@ -3632,7 +3587,7 @@ "type": "github" } ], - "time": "2024-07-03T05:13:08+00:00" + "time": "2024-10-09T05:16:32+00:00" }, { "name": "sj-i/php-cast", @@ -3682,6 +3637,58 @@ "time": "2020-08-17T00:29:37+00:00" }, { + "name": "staabm/side-effects-detector", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/staabm/side-effects-detector.git", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.6", + "phpunit/phpunit": "^9.6.21", + "symfony/var-dumper": "^5.4.43", + "tomasvotruba/type-coverage": "1.0.0", + "tomasvotruba/unused-public": "1.0.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "lib/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A static analysis tool to detect side effects in PHP code", + "keywords": [ + "static analysis" + ], + "support": { + "issues": "https://github.com/staabm/side-effects-detector/issues", + "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5" + }, + "funding": [ + { + "url": "https://github.com/staabm", + "type": "github" + } + ], + "time": "2024-10-20T05:08:20+00:00" + }, + { "name": "symfony/console", "version": "v6.3.8", "source": { @@ -3773,16 +3780,16 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", "shasum": "" }, "require": { @@ -3790,12 +3797,12 @@ }, "type": "library", "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, "branch-alias": { "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" } }, "autoload": { @@ -3820,7 +3827,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" }, "funding": [ { @@ -3836,24 +3843,24 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.30.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "0424dff1c58f028c451efff2045f5d92410bd540" + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/0424dff1c58f028c451efff2045f5d92410bd540", - "reference": "0424dff1c58f028c451efff2045f5d92410bd540", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "provide": { "ext-ctype": "*" @@ -3864,8 +3871,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -3899,7 +3906,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0" }, "funding": [ { @@ -3915,24 +3922,24 @@ "type": "tidelift" } ], - "time": "2024-05-31T15:07:36+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.30.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a" + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/64647a7c30b2283f5d49b874d84a18fc22054b7a", - "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" @@ -3940,8 +3947,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -3977,7 +3984,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0" }, "funding": [ { @@ -3993,24 +4000,24 @@ "type": "tidelift" } ], - "time": "2024-05-31T15:07:36+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.30.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb" + "reference": "3833d7255cc303546435cb650316bff708a1c75c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/a95281b0be0d9ab48050ebd988b967875cdb9fdb", - "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" @@ -4018,8 +4025,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4058,7 +4065,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0" }, "funding": [ { @@ -4074,24 +4081,24 @@ "type": "tidelift" } ], - "time": "2024-05-31T15:07:36+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.30.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c" + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fd22ab50000ef01661e2a31d850ebaa297f8e03c", - "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "provide": { "ext-mbstring": "*" @@ -4102,8 +4109,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4138,7 +4145,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" }, "funding": [ { @@ -4154,20 +4161,20 @@ "type": "tidelift" } ], - "time": "2024-06-19T12:30:46+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f" + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", - "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", "shasum": "" }, "require": { @@ -4180,12 +4187,12 @@ }, "type": "library", "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, "branch-alias": { "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" } }, "autoload": { @@ -4221,7 +4228,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.5.1" }, "funding": [ { @@ -4237,20 +4244,20 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/string", - "version": "v6.4.11", + "version": "v6.4.15", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "5bc3eb632cf9c8dbfd6529d89be9950d1518883b" + "reference": "73a5e66ea2e1677c98d4449177c5a9cf9d8b4c6f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/5bc3eb632cf9c8dbfd6529d89be9950d1518883b", - "reference": "5bc3eb632cf9c8dbfd6529d89be9950d1518883b", + "url": "https://api.github.com/repos/symfony/string/zipball/73a5e66ea2e1677c98d4449177c5a9cf9d8b4c6f", + "reference": "73a5e66ea2e1677c98d4449177c5a9cf9d8b4c6f", "shasum": "" }, "require": { @@ -4307,7 +4314,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.4.11" + "source": "https://github.com/symfony/string/tree/v6.4.15" }, "funding": [ { @@ -4323,20 +4330,20 @@ "type": "tidelift" } ], - "time": "2024-08-12T09:55:28+00:00" + "time": "2024-11-13T13:31:12+00:00" }, { "name": "symplify/easy-coding-standard", - "version": "12.3.5", + "version": "12.5.11", "source": { "type": "git", "url": "https://github.com/easy-coding-standard/easy-coding-standard.git", - "reference": "0d7c2cfee3debdf11c12135e90d69d1d9f4eef03" + "reference": "1fa356963594227d0d1a87ed0b2b419d3a42a5d8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/easy-coding-standard/easy-coding-standard/zipball/0d7c2cfee3debdf11c12135e90d69d1d9f4eef03", - "reference": "0d7c2cfee3debdf11c12135e90d69d1d9f4eef03", + "url": "https://api.github.com/repos/easy-coding-standard/easy-coding-standard/zipball/1fa356963594227d0d1a87ed0b2b419d3a42a5d8", + "reference": "1fa356963594227d0d1a87ed0b2b419d3a42a5d8", "shasum": "" }, "require": { @@ -4372,7 +4379,7 @@ ], "support": { "issues": "https://github.com/easy-coding-standard/easy-coding-standard/issues", - "source": "https://github.com/easy-coding-standard/easy-coding-standard/tree/12.3.5" + "source": "https://github.com/easy-coding-standard/easy-coding-standard/tree/12.5.11" }, "funding": [ { @@ -4384,7 +4391,7 @@ "type": "github" } ], - "time": "2024-08-08T08:43:50+00:00" + "time": "2025-03-25T10:01:37+00:00" }, { "name": "theseer/tokenizer", @@ -4502,7 +4509,7 @@ }, "prefer-stable": false, "prefer-lowest": false, - "platform": [], - "platform-dev": [], + "platform": {}, + "platform-dev": {}, "plugin-api-version": "2.6.0" } diff --git a/examples/compile-php-to-wasm/Dockerfile b/examples/compile-php-to-wasm/Dockerfile index db8dd0d..1e61133 100644 --- a/examples/compile-php-to-wasm/Dockerfile +++ b/examples/compile-php-to-wasm/Dockerfile @@ -1,6 +1,6 @@ -FROM emscripten/emsdk:3.1.62 +FROM emscripten/emsdk:3.1.74 -RUN git clone --depth=1 --branch=php-8.3.9 https://github.com/php/php-src +RUN git clone --depth=1 --branch=php-8.4.5 https://github.com/php/php-src RUN apt-get update && \ apt-get install -y --no-install-recommends \ diff --git a/examples/compile-php-to-wasm/php-wasm.js b/examples/compile-php-to-wasm/php-wasm.js index 264f7f9..e255611 100644 --- a/examples/compile-php-to-wasm/php-wasm.js +++ b/examples/compile-php-to-wasm/php-wasm.js @@ -48,10 +48,6 @@ var ENVIRONMENT_IS_WORKER = false; var ENVIRONMENT_IS_NODE = true; var ENVIRONMENT_IS_SHELL = false; -if (Module['ENVIRONMENT']) { - throw new Error('Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -sENVIRONMENT=web or -sENVIRONMENT=node)'); -} - if (ENVIRONMENT_IS_NODE) { // `require()` is no-op in an ESM module, use `createRequire()` to construct // the require()` function. This is only necessary for multi-environment @@ -108,27 +104,25 @@ if (ENVIRONMENT_IS_NODE) { // EXPORT_ES6 + ENVIRONMENT_IS_NODE always requires use of import.meta.url, // since there's no way getting the current absolute path of the module when // support for that is not available. - scriptDirectory = require('url').fileURLToPath(new URL('./', import.meta.url)); // includes trailing slash + if (!import.meta.url.startsWith('data:')) { + scriptDirectory = nodePath.dirname(require('url').fileURLToPath(import.meta.url)) + '/'; + } // include: node_shell_read.js readBinary = (filename) => { - // We need to re-wrap `file://` strings to URLs. Normalizing isn't - // necessary in that case, the path should already be absolute. - filename = isFileURI(filename) ? new URL(filename) : nodePath.normalize(filename); + // We need to re-wrap `file://` strings to URLs. + filename = isFileURI(filename) ? new URL(filename) : filename; var ret = fs.readFileSync(filename); - assert(ret.buffer); + assert(Buffer.isBuffer(ret)); return ret; }; -readAsync = (filename, binary = true) => { +readAsync = async (filename, binary = true) => { // See the comment in the `readBinary` function. - filename = isFileURI(filename) ? new URL(filename) : nodePath.normalize(filename); - return new Promise((resolve, reject) => { - fs.readFile(filename, binary ? undefined : 'utf8', (err, data) => { - if (err) reject(err); - else resolve(binary ? data.buffer : data); - }); - }); + filename = isFileURI(filename) ? new URL(filename) : filename; + var ret = fs.readFileSync(filename, binary ? undefined : 'utf8'); + assert(binary ? Buffer.isBuffer(ret) : typeof ret == 'string'); + return ret; }; // end include: node_shell_read.js if (!Module['thisProgram'] && process.argv.length > 1) { @@ -147,7 +141,7 @@ readAsync = (filename, binary = true) => { } else if (ENVIRONMENT_IS_SHELL) { - if ((typeof process == 'object' && typeof require === 'function') || typeof window == 'object' || typeof importScripts == 'function') throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)'); + if ((typeof process == 'object' && typeof require === 'function') || typeof window == 'object' || typeof WorkerGlobalScope != 'undefined') throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)'); } else @@ -177,8 +171,6 @@ if (Module['arguments']) arguments_ = Module['arguments'];legacyModuleProp('argu if (Module['thisProgram']) thisProgram = Module['thisProgram'];legacyModuleProp('thisProgram', 'thisProgram'); -if (Module['quit']) quit_ = Module['quit'];legacyModuleProp('quit', 'quit_'); - // perform assertions in shell.js after we set up out() and err(), as otherwise if an assertion fails it cannot print the message // Assertions on removed incoming Module JS APIs. assert(typeof Module['memoryInitializerPrefixURL'] == 'undefined', 'Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead'); @@ -223,8 +215,7 @@ assert(!ENVIRONMENT_IS_SHELL, 'shell environment detected but not enabled at bui // An online HTML version (which may be of a different version of Emscripten) // is up at http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html -var wasmBinary; -if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];legacyModuleProp('wasmBinary', 'wasmBinary'); +var wasmBinary = Module['wasmBinary'];legacyModuleProp('wasmBinary', 'wasmBinary'); if (typeof WebAssembly != 'object') { err('no native wasm support detected'); @@ -297,6 +288,7 @@ function updateMemoryViews() { Module['HEAPF32'] = HEAPF32 = new Float32Array(b); Module['HEAPF64'] = HEAPF64 = new Float64Array(b); } + // end include: runtime_shared.js assert(!Module['STACK_SIZE'], 'STACK_SIZE can no longer be set at runtime. Use -sSTACK_SIZE at link time') @@ -345,16 +337,6 @@ function checkStackCookie() { } } // end include: runtime_stack_check.js -// include: runtime_assertions.js -// Endianness check -(function() { - var h16 = new Int16Array(1); - var h8 = new Int8Array(h16.buffer); - h16[0] = 0x6373; - if (h8[0] !== 0x73 || h8[1] !== 0x63) throw 'Runtime error: expected the system to be little-endian! (Run with -sSUPPORT_BIG_ENDIAN to bypass)'; -})(); - -// end include: runtime_assertions.js var __ATPRERUN__ = []; // functions called before the runtime is initialized var __ATINIT__ = []; // functions called during startup var __ATEXIT__ = []; // functions called during shutdown @@ -379,7 +361,7 @@ function initRuntime() { checkStackCookie(); -if (!Module['noFSInit'] && !FS.init.initialized) +if (!Module['noFSInit'] && !FS.initialized) FS.init(); FS.ignorePermissions = false; @@ -439,9 +421,9 @@ assert(Math.trunc, 'This browser does not support Math.trunc(), build with LEGAC // it happens right before run - run will be postponed until // the dependencies are met. var runDependencies = 0; -var runDependencyWatcher = null; var dependenciesFulfilled = null; // overridden to take different actions when all run dependencies are fulfilled var runDependencyTracking = {}; +var runDependencyWatcher = null; function getUniqueRunDependency(id) { var orig = id; @@ -519,7 +501,6 @@ function abort(what) { err(what); ABORT = true; - EXITSTATUS = 1; // Use a wasm runtime error, because a JS error might be seen as a foreign // exception, which means we'd run destructors on it. We need the error to @@ -599,26 +580,29 @@ function getBinarySync(file) { throw 'both async and sync fetching of the wasm failed'; } -function getBinaryPromise(binaryFile) { +async function getWasmBinary(binaryFile) { // If we don't have the binary yet, load it asynchronously using readAsync. if (!wasmBinary ) { // Fetch the binary using readAsync - return readAsync(binaryFile).then( - (response) => new Uint8Array(/** @type{!ArrayBuffer} */(response)), - // Fall back to getBinarySync if readAsync fails - () => getBinarySync(binaryFile) - ); + try { + var response = await readAsync(binaryFile); + return new Uint8Array(response); + } catch { + // Fall back to getBinarySync below; + } } // Otherwise, getBinarySync should be able to get it synchronously - return Promise.resolve().then(() => getBinarySync(binaryFile)); + return getBinarySync(binaryFile); } -function instantiateArrayBuffer(binaryFile, imports, receiver) { - return getBinaryPromise(binaryFile).then((binary) => { - return WebAssembly.instantiate(binary, imports); - }).then(receiver, (reason) => { +async function instantiateArrayBuffer(binaryFile, imports) { + try { + var binary = await getWasmBinary(binaryFile); + var instance = await WebAssembly.instantiate(binary, imports); + return instance; + } catch (reason) { err(`failed to asynchronously prepare wasm: ${reason}`); // Warn on some common problems. @@ -626,10 +610,10 @@ function instantiateArrayBuffer(binaryFile, imports, receiver) { err(`warning: Loading from a file URI (${wasmBinaryFile}) is not supported in most browsers. See https://emscripten.org/docs/getting_started/FAQ.html#how-do-i-run-a-local-webserver-for-testing-why-does-my-program-stall-in-downloading-or-preparing`); } abort(reason); - }); + } } -function instantiateAsync(binary, binaryFile, imports, callback) { +async function instantiateAsync(binary, binaryFile, imports) { if (!binary && typeof WebAssembly.instantiateStreaming == 'function' && !isDataURI(binaryFile) && @@ -641,26 +625,19 @@ function instantiateAsync(binary, binaryFile, imports, callback) { // https://github.com/emscripten-core/emscripten/pull/16917 !ENVIRONMENT_IS_NODE && typeof fetch == 'function') { - return fetch(binaryFile, { credentials: 'same-origin' }).then((response) => { - // Suppress closure warning here since the upstream definition for - // instantiateStreaming only allows Promise<Repsponse> rather than - // an actual Response. - // TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure is fixed. - /** @suppress {checkTypes} */ - var result = WebAssembly.instantiateStreaming(response, imports); - - return result.then( - callback, - function(reason) { - // We expect the most common failure cause to be a bad MIME type for the binary, - // in which case falling back to ArrayBuffer instantiation should work. - err(`wasm streaming compile failed: ${reason}`); - err('falling back to ArrayBuffer instantiation'); - return instantiateArrayBuffer(binaryFile, imports, callback); - }); - }); + try { + var response = fetch(binaryFile, { credentials: 'same-origin' }); + var instantiationResult = await WebAssembly.instantiateStreaming(response, imports); + return instantiationResult; + } catch (reason) { + // We expect the most common failure cause to be a bad MIME type for the binary, + // in which case falling back to ArrayBuffer instantiation should work. + err(`wasm streaming compile failed: ${reason}`); + err('falling back to ArrayBuffer instantiation'); + // fall back of instantiateArrayBuffer below + }; } - return instantiateArrayBuffer(binaryFile, imports, callback); + return instantiateArrayBuffer(binaryFile, imports); } function getWasmImports() { @@ -673,8 +650,7 @@ function getWasmImports() { // Create the wasm instance. // Receives the wasm imports, returns the exports. -function createWasm() { - var info = getWasmImports(); +async function createWasm() { // Load the wasm module and create an instance of using native support in the JS engine. // handle a generated wasm instance, receiving its exports and // performing other necessary setup @@ -716,6 +692,8 @@ function createWasm() { receiveInstance(result['instance']); } + var info = getWasmImports(); + // User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback // to manually instantiate the Wasm module themselves. This allows pages to // run the instantiation parallel to any other async startup actions they are @@ -732,11 +710,17 @@ function createWasm() { } } - if (!wasmBinaryFile) wasmBinaryFile = findWasmBinary(); + wasmBinaryFile ??= findWasmBinary(); - // If instantiation fails, reject the module ready promise. - instantiateAsync(wasmBinary, wasmBinaryFile, info, receiveInstantiationResult).catch(readyPromiseReject); - return {}; // no exports yet; we'll fill them in later + try { + var result = await instantiateAsync(wasmBinary, wasmBinaryFile, info); + receiveInstantiationResult(result); + return result; + } catch (e) { + // If instantiation fails, reject the module ready promise. + readyPromiseReject(e); + return; + } } // Globals used by JS i64 conversions (see makeSetValue) @@ -744,6 +728,18 @@ var tempDouble; var tempI64; // include: runtime_debug.js +// Endianness check +(() => { + var h16 = new Int16Array(1); + var h8 = new Int8Array(h16.buffer); + h16[0] = 0x6373; + if (h8[0] !== 0x73 || h8[1] !== 0x63) throw 'Runtime error: expected the system to be little-endian! (Run with -sSUPPORT_BIG_ENDIAN to bypass)'; +})(); + +if (Module['ENVIRONMENT']) { + throw new Error('Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -sENVIRONMENT=web or -sENVIRONMENT=node)'); +} + function legacyModuleProp(prop, newName, incoming=true) { if (!Object.getOwnPropertyDescriptor(Module, prop)) { Object.defineProperty(Module, prop, { @@ -776,45 +772,51 @@ function isExportedByForceFilesystem(name) { name === 'removeRunDependency'; } -function missingGlobal(sym, msg) { - if (typeof globalThis != 'undefined') { +/** + * Intercept access to a global symbol. This enables us to give informative + * warnings/errors when folks attempt to use symbols they did not include in + * their build, or no symbols that no longer exist. + */ +function hookGlobalSymbolAccess(sym, func) { + if (typeof globalThis != 'undefined' && !Object.getOwnPropertyDescriptor(globalThis, sym)) { Object.defineProperty(globalThis, sym, { configurable: true, get() { - warnOnce(`\`${sym}\` is not longer defined by emscripten. ${msg}`); + func(); return undefined; } }); } } +function missingGlobal(sym, msg) { + hookGlobalSymbolAccess(sym, () => { + warnOnce(`\`${sym}\` is not longer defined by emscripten. ${msg}`); + }); +} + missingGlobal('buffer', 'Please use HEAP8.buffer or wasmMemory.buffer'); missingGlobal('asm', 'Please use wasmExports instead'); function missingLibrarySymbol(sym) { - if (typeof globalThis != 'undefined' && !Object.getOwnPropertyDescriptor(globalThis, sym)) { - Object.defineProperty(globalThis, sym, { - configurable: true, - get() { - // Can't `abort()` here because it would break code that does runtime - // checks. e.g. `if (typeof SDL === 'undefined')`. - var msg = `\`${sym}\` is a library symbol and not included by default; add it to your library.js __deps or to DEFAULT_LIBRARY_FUNCS_TO_INCLUDE on the command line`; - // DEFAULT_LIBRARY_FUNCS_TO_INCLUDE requires the name as it appears in - // library.js, which means $name for a JS name with no prefix, or name - // for a JS name like _name. - var librarySymbol = sym; - if (!librarySymbol.startsWith('_')) { - librarySymbol = '$' + sym; - } - msg += ` (e.g. -sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE='${librarySymbol}')`; - if (isExportedByForceFilesystem(sym)) { - msg += '. Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you'; - } - warnOnce(msg); - return undefined; - } - }); - } + hookGlobalSymbolAccess(sym, () => { + // Can't `abort()` here because it would break code that does runtime + // checks. e.g. `if (typeof SDL === 'undefined')`. + var msg = `\`${sym}\` is a library symbol and not included by default; add it to your library.js __deps or to DEFAULT_LIBRARY_FUNCS_TO_INCLUDE on the command line`; + // DEFAULT_LIBRARY_FUNCS_TO_INCLUDE requires the name as it appears in + // library.js, which means $name for a JS name with no prefix, or name + // for a JS name like _name. + var librarySymbol = sym; + if (!librarySymbol.startsWith('_')) { + librarySymbol = '$' + sym; + } + msg += ` (e.g. -sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE='${librarySymbol}')`; + if (isExportedByForceFilesystem(sym)) { + msg += '. Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you'; + } + warnOnce(msg); + }); + // Any symbol that is not included from the JS library is also (by definition) // not exported on the Module object. unexportedRuntimeSymbol(sym); @@ -846,11 +848,12 @@ function dbg(...args) { // end include: preamble.js - /** @constructor */ - function ExitStatus(status) { - this.name = 'ExitStatus'; - this.message = `Program terminated with exit(${status})`; - this.status = status; + class ExitStatus { + name = 'ExitStatus'; + constructor(status) { + this.message = `Program terminated with exit(${status})`; + this.status = status; + } } var callRuntimeCallbacks = (callbacks) => { @@ -930,18 +933,18 @@ function dbg(...args) { * array that contains uint8 values, returns a copy of that string as a * Javascript String object. * heapOrArray is either a regular array, or a JavaScript typed array view. - * @param {number} idx + * @param {number=} idx * @param {number=} maxBytesToRead * @return {string} */ - var UTF8ArrayToString = (heapOrArray, idx, maxBytesToRead) => { + var UTF8ArrayToString = (heapOrArray, idx = 0, maxBytesToRead = NaN) => { var endIdx = idx + maxBytesToRead; var endPtr = idx; // TextDecoder needs to know the byte length in advance, it doesn't stop on // null terminator by itself. Also, use the length info to avoid running tiny // strings through TextDecoder, since .subarray() allocates garbage. // (As a tiny code save trick, compare endPtr against endIdx using a negation, - // so that undefined means Infinity) + // so that undefined/NaN means Infinity) while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr; if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) { @@ -996,9 +999,8 @@ function dbg(...args) { assert(typeof ptr == 'number', `UTF8ToString expects a number (got ${typeof ptr})`); return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : ''; }; - var ___assert_fail = (condition, filename, line, func) => { + var ___assert_fail = (condition, filename, line, func) => abort(`Assertion failed: ${UTF8ToString(condition)}, at: ` + [filename ? UTF8ToString(filename) : 'unknown filename', line, func ? UTF8ToString(func) : 'unknown function']); - }; var wasmTableMirror = []; @@ -1008,8 +1010,10 @@ function dbg(...args) { var func = wasmTableMirror[funcPtr]; if (!func) { if (funcPtr >= wasmTableMirror.length) wasmTableMirror.length = funcPtr + 1; + /** @suppress {checkTypes} */ wasmTableMirror[funcPtr] = func = wasmTable.get(funcPtr); } + /** @suppress {checkTypes} */ assert(wasmTable.get(funcPtr) == func, 'JavaScript-side Wasm function table mirror is out of date!'); return func; }; @@ -1356,7 +1360,7 @@ function dbg(...args) { buffer[offset+i] = result; } if (bytesRead) { - stream.node.timestamp = Date.now(); + stream.node.atime = Date.now(); } return bytesRead; }, @@ -1372,7 +1376,7 @@ function dbg(...args) { throw new FS.ErrnoError(29); } if (length) { - stream.node.timestamp = Date.now(); + stream.node.mtime = stream.node.ctime = Date.now(); } return i; }, @@ -1383,7 +1387,7 @@ function dbg(...args) { }, put_char(tty, val) { if (val === null || val === 10) { - out(UTF8ArrayToString(tty.output, 0)); + out(UTF8ArrayToString(tty.output)); tty.output = []; } else { if (val != 0) tty.output.push(val); // val == 0 would cut text output off in the middle. @@ -1391,7 +1395,7 @@ function dbg(...args) { }, fsync(tty) { if (tty.output && tty.output.length > 0) { - out(UTF8ArrayToString(tty.output, 0)); + out(UTF8ArrayToString(tty.output)); tty.output = []; } }, @@ -1420,7 +1424,7 @@ function dbg(...args) { default_tty1_ops:{ put_char(tty, val) { if (val === null || val === 10) { - err(UTF8ArrayToString(tty.output, 0)); + err(UTF8ArrayToString(tty.output)); tty.output = []; } else { if (val != 0) tty.output.push(val); @@ -1428,7 +1432,7 @@ function dbg(...args) { }, fsync(tty) { if (tty.output && tty.output.length > 0) { - err(UTF8ArrayToString(tty.output, 0)); + err(UTF8ArrayToString(tty.output)); tty.output = []; } }, @@ -1438,7 +1442,6 @@ function dbg(...args) { var zeroMemory = (address, size) => { HEAPU8.fill(0, address, address + size); - return address; }; var alignMemory = (size, alignment) => { @@ -1448,13 +1451,13 @@ function dbg(...args) { var mmapAlloc = (size) => { size = alignMemory(size, 65536); var ptr = _emscripten_builtin_memalign(65536, size); - if (!ptr) return 0; - return zeroMemory(ptr, size); + if (ptr) zeroMemory(ptr, size); + return ptr; }; var MEMFS = { ops_table:null, mount(mount) { - return MEMFS.createNode(null, '/', 16384 | 511 /* 0777 */, 0); + return MEMFS.createNode(null, '/', 16895, 0); }, createNode(parent, name, mode, dev) { if (FS.isBlkdev(mode) || FS.isFIFO(mode)) { @@ -1528,11 +1531,11 @@ function dbg(...args) { node.node_ops = MEMFS.ops_table.chrdev.node; node.stream_ops = MEMFS.ops_table.chrdev.stream; } - node.timestamp = Date.now(); + node.atime = node.mtime = node.ctime = Date.now(); // add the new node to the parent if (parent) { parent.contents[name] = node; - parent.timestamp = node.timestamp; + parent.atime = parent.mtime = parent.ctime = node.atime; } return node; }, @@ -1588,9 +1591,9 @@ function dbg(...args) { } else { attr.size = 0; } - attr.atime = new Date(node.timestamp); - attr.mtime = new Date(node.timestamp); - attr.ctime = new Date(node.timestamp); + attr.atime = new Date(node.atime); + attr.mtime = new Date(node.mtime); + attr.ctime = new Date(node.ctime); // NOTE: In our implementation, st_blocks = Math.ceil(st_size/st_blksize), // but this is not required by the standard. attr.blksize = 4096; @@ -1598,46 +1601,44 @@ function dbg(...args) { return attr; }, setattr(node, attr) { - if (attr.mode !== undefined) { - node.mode = attr.mode; - } - if (attr.timestamp !== undefined) { - node.timestamp = attr.timestamp; + for (const key of ["mode", "atime", "mtime", "ctime"]) { + if (attr[key]) { + node[key] = attr[key]; + } } if (attr.size !== undefined) { MEMFS.resizeFileStorage(node, attr.size); } }, lookup(parent, name) { - throw FS.genericErrors[44]; + throw new FS.ErrnoError(44); }, mknod(parent, name, mode, dev) { return MEMFS.createNode(parent, name, mode, dev); }, rename(old_node, new_dir, new_name) { - // if we're overwriting a directory at new_name, make sure it's empty. - if (FS.isDir(old_node.mode)) { - var new_node; - try { - new_node = FS.lookupNode(new_dir, new_name); - } catch (e) { - } - if (new_node) { + var new_node; + try { + new_node = FS.lookupNode(new_dir, new_name); + } catch (e) {} + if (new_node) { + if (FS.isDir(old_node.mode)) { + // if we're overwriting a directory at new_name, make sure it's empty. for (var i in new_node.contents) { throw new FS.ErrnoError(55); } } + FS.hashRemoveNode(new_node); } // do the internal rewiring delete old_node.parent.contents[old_node.name]; - old_node.parent.timestamp = Date.now() - old_node.name = new_name; new_dir.contents[new_name] = old_node; - new_dir.timestamp = old_node.parent.timestamp; + old_node.name = new_name; + new_dir.ctime = new_dir.mtime = old_node.parent.ctime = old_node.parent.mtime = Date.now(); }, unlink(parent, name) { delete parent.contents[name]; - parent.timestamp = Date.now(); + parent.ctime = parent.mtime = Date.now(); }, rmdir(parent, name) { var node = FS.lookupNode(parent, name); @@ -1645,17 +1646,13 @@ function dbg(...args) { throw new FS.ErrnoError(55); } delete parent.contents[name]; - parent.timestamp = Date.now(); + parent.ctime = parent.mtime = Date.now(); }, readdir(node) { - var entries = ['.', '..']; - for (var key of Object.keys(node.contents)) { - entries.push(key); - } - return entries; + return ['.', '..', ...Object.keys(node.contents)]; }, symlink(parent, newname, oldpath) { - var node = MEMFS.createNode(parent, newname, 511 /* 0777 */ | 40960, 0); + var node = MEMFS.createNode(parent, newname, 0o777 | 40960, 0); node.link = oldpath; return node; }, @@ -1685,7 +1682,7 @@ function dbg(...args) { if (!length) return 0; var node = stream.node; - node.timestamp = Date.now(); + node.mtime = node.ctime = Date.now(); if (buffer.subarray && (!node.contents || node.contents.subarray)) { // This write is from a typed array to a typed array? if (canOwn) { @@ -1742,26 +1739,28 @@ function dbg(...args) { var allocated; var contents = stream.node.contents; // Only make a new copy when MAP_PRIVATE is specified. - if (!(flags & 2) && contents.buffer === HEAP8.buffer) { + if (!(flags & 2) && contents && contents.buffer === HEAP8.buffer) { // We can't emulate MAP_SHARED when the file is not backed by the // buffer we're mapping to (e.g. the HEAP buffer). allocated = false; ptr = contents.byteOffset; } else { - // Try to avoid unnecessary slices. - if (position > 0 || position + length < contents.length) { - if (contents.subarray) { - contents = contents.subarray(position, position + length); - } else { - contents = Array.prototype.slice.call(contents, position, position + length); - } - } allocated = true; ptr = mmapAlloc(length); if (!ptr) { throw new FS.ErrnoError(48); } - HEAP8.set(contents, ptr); + if (contents) { + // Try to avoid unnecessary slices. + if (position > 0 || position + length < contents.length) { + if (contents.subarray) { + contents = contents.subarray(position, position + length); + } else { + contents = Array.prototype.slice.call(contents, position, position + length); + } + } + HEAP8.set(contents, ptr); + } } return { ptr, allocated }; }, @@ -1773,24 +1772,10 @@ function dbg(...args) { }, }; - /** @param {boolean=} noRunDep */ - var asyncLoad = (url, onload, onerror, noRunDep) => { - var dep = !noRunDep ? getUniqueRunDependency(`al ${url}`) : ''; - readAsync(url).then( - (arrayBuffer) => { - assert(arrayBuffer, `Loading data file "${url}" failed (no arrayBuffer).`); - onload(new Uint8Array(arrayBuffer)); - if (dep) removeRunDependency(dep); - }, - (err) => { - if (onerror) { - onerror(); - } else { - throw `Loading data file "${url}" failed.`; - } - } - ); - if (dep) addRunDependency(dep); + var asyncLoad = async (url) => { + var arrayBuffer = await readAsync(url); + assert(arrayBuffer, `Loading data file "${url}" failed (no arrayBuffer).`); + return new Uint8Array(arrayBuffer); }; @@ -1837,7 +1822,7 @@ function dbg(...args) { } addRunDependency(dep); if (typeof url == 'string') { - asyncLoad(url, processData, onerror); + asyncLoad(url).then(processData, onerror); } else { processData(url); } @@ -1871,9 +1856,7 @@ function dbg(...args) { - var strError = (errno) => { - return UTF8ToString(_strerror(errno)); - }; + var strError = (errno) => UTF8ToString(_strerror(errno)); var ERRNO_CODES = { 'EPERM': 63, @@ -2010,6 +1993,7 @@ function dbg(...args) { initialized:false, ignorePermissions:true, ErrnoError:class extends Error { + name = 'ErrnoError'; // We set the `name` property to be able to identify `FS.ErrnoError` // - the `name` is a standard ECMA-262 property of error objects. Kind of good to have it anyway. // - when using PROXYFS, an error can come from an underlying FS @@ -2018,9 +2002,6 @@ function dbg(...args) { // we'll use the reliable test `err.name == "ErrnoError"` instead constructor(errno) { super(runtimeInitialized ? strError(errno) : ''); - // TODO(sbc): Use the inline member declaration syntax once we - // support it in acorn and closure. - this.name = 'ErrnoError'; this.errno = errno; for (var key in ERRNO_CODES) { if (ERRNO_CODES[key] === errno) { @@ -2030,16 +2011,12 @@ function dbg(...args) { } } }, - genericErrors:{ - }, filesystems:null, syncFSRequests:0, + readFiles:{ + }, FSStream:class { - constructor() { - // TODO(https://github.com/emscripten-core/emscripten/issues/21414): - // Use inline field declarations. - this.shared = {}; - } + shared = {}; get object() { return this.node; } @@ -2069,21 +2046,22 @@ function dbg(...args) { } }, FSNode:class { + node_ops = {}; + stream_ops = {}; + readMode = 292 | 73; + writeMode = 146; + mounted = null; constructor(parent, name, mode, rdev) { if (!parent) { parent = this; // root node sets parent to itself } this.parent = parent; this.mount = parent.mount; - this.mounted = null; this.id = FS.nextInode++; this.name = name; this.mode = mode; - this.node_ops = {}; - this.stream_ops = {}; this.rdev = rdev; - this.readMode = 292/*292*/ | 73/*73*/; - this.writeMode = 146/*146*/; + this.atime = this.mtime = this.ctime = Date.now(); } get read() { return (this.mode & this.readMode) === this.readMode; @@ -2105,63 +2083,70 @@ function dbg(...args) { } }, lookupPath(path, opts = {}) { - path = PATH_FS.resolve(path); - if (!path) return { path: '', node: null }; + opts.follow_mount ??= true - var defaults = { - follow_mount: true, - recurse_count: 0 - }; - opts = Object.assign(defaults, opts) - - if (opts.recurse_count > 8) { // max recursive lookup of 8 - throw new FS.ErrnoError(32); + if (!PATH.isAbs(path)) { + path = FS.cwd() + '/' + path; } - // split the absolute path - var parts = path.split('/').filter((p) => !!p); - - // start at the root - var current = FS.root; - var current_path = '/'; + // limit max consecutive symlinks to 40 (SYMLOOP_MAX). + linkloop: for (var nlinks = 0; nlinks < 40; nlinks++) { + // split the absolute path + var parts = path.split('/').filter((p) => !!p && (p !== '.')); - for (var i = 0; i < parts.length; i++) { - var islast = (i === parts.length-1); - if (islast && opts.parent) { - // stop resolving - break; - } + // start at the root + var current = FS.root; + var current_path = '/'; - current = FS.lookupNode(current, parts[i]); - current_path = PATH.join2(current_path, parts[i]); + for (var i = 0; i < parts.length; i++) { + var islast = (i === parts.length-1); + if (islast && opts.parent) { + // stop resolving + break; + } - // jump to the mount's root node if this is a mountpoint - if (FS.isMountpoint(current)) { - if (!islast || (islast && opts.follow_mount)) { - current = current.mounted.root; + if (parts[i] === '..') { + current_path = PATH.dirname(current_path); + current = current.parent; + continue; } - } - // by default, lookupPath will not follow a symlink if it is the final path component. - // setting opts.follow = true will override this behavior. - if (!islast || opts.follow) { - var count = 0; - while (FS.isLink(current.mode)) { - var link = FS.readlink(current_path); - current_path = PATH_FS.resolve(PATH.dirname(current_path), link); + current_path = PATH.join2(current_path, parts[i]); + try { + current = FS.lookupNode(current, parts[i]); + } catch (e) { + // if noent_okay is true, suppress a ENOENT in the last component + // and return an object with an undefined node. This is needed for + // resolving symlinks in the path when creating a file. + if ((e?.errno === 44) && islast && opts.noent_okay) { + return { path: current_path }; + } + throw e; + } - var lookup = FS.lookupPath(current_path, { recurse_count: opts.recurse_count + 1 }); - current = lookup.node; + // jump to the mount's root node if this is a mountpoint + if (FS.isMountpoint(current) && (!islast || opts.follow_mount)) { + current = current.mounted.root; + } - if (count++ > 40) { // limit max consecutive symlinks to 40 (SYMLOOP_MAX). - throw new FS.ErrnoError(32); + // by default, lookupPath will not follow a symlink if it is the final path component. + // setting opts.follow = true will override this behavior. + if (FS.isLink(current.mode) && (!islast || opts.follow)) { + if (!current.node_ops.readlink) { + throw new FS.ErrnoError(52); } + var link = current.node_ops.readlink(current); + if (!PATH.isAbs(link)) { + link = PATH.dirname(current_path) + '/' + link; + } + path = link + '/' + parts.slice(i + 1).join('/'); + continue linkloop; } } + return { path: current_path, node: current }; } - - return { path: current_path, node: current }; + throw new FS.ErrnoError(32); }, getPath(node) { var path; @@ -2285,6 +2270,9 @@ function dbg(...args) { return 0; }, mayCreate(dir, name) { + if (!FS.isDir(dir.mode)) { + return 54; + } try { var node = FS.lookupNode(dir, name); return 20; @@ -2549,14 +2537,35 @@ function dbg(...args) { } return parent.node_ops.mknod(parent, name, mode, dev); }, - create(path, mode) { - mode = mode !== undefined ? mode : 438 /* 0666 */; + statfs(path) { + + // NOTE: None of the defaults here are true. We're just returning safe and + // sane values. + var rtn = { + bsize: 4096, + frsize: 4096, + blocks: 1e6, + bfree: 5e5, + bavail: 5e5, + files: FS.nextInode, + ffree: FS.nextInode - 1, + fsid: 42, + flags: 2, + namelen: 255, + }; + + var parent = FS.lookupPath(path, {follow: true}).node; + if (parent?.node_ops.statfs) { + Object.assign(rtn, parent.node_ops.statfs(parent.mount.opts.root)); + } + return rtn; + }, + create(path, mode = 0o666) { mode &= 4095; mode |= 32768; return FS.mknod(path, mode, 0); }, - mkdir(path, mode) { - mode = mode !== undefined ? mode : 511 /* 0777 */; + mkdir(path, mode = 0o777) { mode &= 511 | 512; mode |= 16384; return FS.mknod(path, mode, 0); @@ -2577,7 +2586,7 @@ function dbg(...args) { mkdev(path, mode, dev) { if (typeof dev == 'undefined') { dev = mode; - mode = 438 /* 0666 */; + mode = 0o666; } mode |= 8192; return FS.mknod(path, mode, dev); @@ -2675,7 +2684,7 @@ function dbg(...args) { // do the underlying fs rename try { old_dir.node_ops.rename(old_node, new_dir, new_name); - // update old node (we do this here to avoid each backend + // update old node (we do this here to avoid each backend // needing to) old_node.parent = new_dir; } catch (e) { @@ -2745,7 +2754,7 @@ function dbg(...args) { if (!link.node_ops.readlink) { throw new FS.ErrnoError(28); } - return PATH_FS.resolve(FS.getPath(link.parent), link.node_ops.readlink(link)); + return link.node_ops.readlink(link); }, stat(path, dontFollow) { var lookup = FS.lookupPath(path, { follow: !dontFollow }); @@ -2774,7 +2783,7 @@ function dbg(...args) { } node.node_ops.setattr(node, { mode: (mode & 4095) | (node.mode & ~4095), - timestamp: Date.now() + ctime: Date.now() }); }, lchmod(path, mode) { @@ -2847,16 +2856,16 @@ function dbg(...args) { var lookup = FS.lookupPath(path, { follow: true }); var node = lookup.node; node.node_ops.setattr(node, { - timestamp: Math.max(atime, mtime) + atime: atime, + mtime: mtime }); }, - open(path, flags, mode) { + open(path, flags, mode = 0o666) { if (path === "") { throw new FS.ErrnoError(44); } flags = typeof flags == 'string' ? FS_modeStringToFlags(flags) : flags; if ((flags & 64)) { - mode = typeof mode == 'undefined' ? 438 /* 0666 */ : mode; mode = (mode & 4095) | 32768; } else { mode = 0; @@ -2865,15 +2874,15 @@ function dbg(...args) { if (typeof path == 'object') { node = path; } else { - path = PATH.normalize(path); - try { - var lookup = FS.lookupPath(path, { - follow: !(flags & 131072) - }); - node = lookup.node; - } catch (e) { - // ignore - } + // noent_okay makes it so that if the final component of the path + // doesn't exist, lookupPath returns `node: undefined`. `path` will be + // updated to point to the target of all symlinks. + var lookup = FS.lookupPath(path, { + follow: !(flags & 131072), + noent_okay: true + }); + node = lookup.node; + path = lookup.path; } // perhaps we need to create the node var created = false; @@ -2933,7 +2942,6 @@ function dbg(...args) { stream.stream_ops.open(stream); } if (Module['logReadFiles'] && !(flags & 1)) { - if (!FS.readFiles) FS.readFiles = {}; if (!(path in FS.readFiles)) { FS.readFiles[path] = 1; } @@ -3067,6 +3075,9 @@ function dbg(...args) { if (!stream.stream_ops.mmap) { throw new FS.ErrnoError(43); } + if (!length) { + throw new FS.ErrnoError(28); + } return stream.stream_ops.mmap(stream, length, position, prot, flags); }, msync(stream, buffer, offset, length, mmapFlags) { @@ -3095,7 +3106,7 @@ function dbg(...args) { var buf = new Uint8Array(length); FS.read(stream, buf, 0, length, 0); if (opts.encoding === 'utf8') { - ret = UTF8ArrayToString(buf, 0); + ret = UTF8ArrayToString(buf); } else if (opts.encoding === 'binary') { ret = buf; } @@ -3143,6 +3154,7 @@ function dbg(...args) { FS.registerDevice(FS.makedev(1, 3), { read: () => 0, write: (stream, buffer, offset, length, pos) => length, + llseek: () => 0, }); FS.mkdev('/dev/null', FS.makedev(1, 3)); // setup /dev/tty and /dev/tty1 @@ -3176,7 +3188,10 @@ function dbg(...args) { FS.mkdir('/proc/self/fd'); FS.mount({ mount() { - var node = FS.createNode(proc_self, 'fd', 16384 | 511 /* 0777 */, 73); + var node = FS.createNode(proc_self, 'fd', 16895, 73); + node.stream_ops = { + llseek: MEMFS.stream_ops.llseek, + }; node.node_ops = { lookup(parent, name) { var fd = +name; @@ -3185,16 +3200,22 @@ function dbg(...args) { parent: null, mount: { mountpoint: 'fake' }, node_ops: { readlink: () => stream.path }, + id: fd + 1, }; ret.parent = ret; // make it look like a simple root node return ret; + }, + readdir() { + return Array.from(FS.streams.entries()) + .filter(([k, v]) => v) + .map(([k, v]) => k.toString()); } }; return node; } }, {}, '/proc/self/fd'); }, - createStandardStreams() { + createStandardStreams(input, output, error) { // TODO deprecate the old functionality of a single // input / output callback and that utilizes FS.createDevice // and instead require a unique set of stream ops @@ -3203,18 +3224,18 @@ function dbg(...args) { // default tty devices. however, if the standard streams // have been overwritten we create a unique device for // them instead. - if (Module['stdin']) { - FS.createDevice('/dev', 'stdin', Module['stdin']); + if (input) { + FS.createDevice('/dev', 'stdin', input); } else { FS.symlink('/dev/tty', '/dev/stdin'); } - if (Module['stdout']) { - FS.createDevice('/dev', 'stdout', null, Module['stdout']); + if (output) { + FS.createDevice('/dev', 'stdout', null, output); } else { FS.symlink('/dev/tty', '/dev/stdout'); } - if (Module['stderr']) { - FS.createDevice('/dev', 'stderr', null, Module['stderr']); + if (error) { + FS.createDevice('/dev', 'stderr', null, error); } else { FS.symlink('/dev/tty1', '/dev/stderr'); } @@ -3228,12 +3249,6 @@ function dbg(...args) { assert(stderr.fd === 2, `invalid handle for stderr (${stderr.fd})`); }, staticInit() { - // Some errors may happen quite a bit, to avoid overhead we reuse them (and suffer a lack of stack info) - [44].forEach((code) => { - FS.genericErrors[code] = new FS.ErrnoError(code); - FS.genericErrors[code].stack = '<generic error, no stack>'; - }); - FS.nameTable = new Array(4096); FS.mount(MEMFS, {}, '/'); @@ -3247,18 +3262,18 @@ function dbg(...args) { }; }, init(input, output, error) { - assert(!FS.init.initialized, 'FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)'); - FS.init.initialized = true; + assert(!FS.initialized, 'FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)'); + FS.initialized = true; // Allow Module.stdin etc. to provide defaults, if none explicitly passed to us here - Module['stdin'] = input || Module['stdin']; - Module['stdout'] = output || Module['stdout']; - Module['stderr'] = error || Module['stderr']; + input ??= Module['stdin']; + output ??= Module['stdout']; + error ??= Module['stderr']; - FS.createStandardStreams(); + FS.createStandardStreams(input, output, error); }, quit() { - FS.init.initialized = false; + FS.initialized = false; // force-flush all streams, so we get musl std streams printed out _fflush(0); // close all of our streams @@ -3351,7 +3366,7 @@ function dbg(...args) { createDevice(parent, name, input, output) { var path = PATH.join2(typeof parent == 'string' ? parent : FS.getPath(parent), name); var mode = FS_getMode(!!input, !!output); - if (!FS.createDevice.major) FS.createDevice.major = 64; + FS.createDevice.major ??= 64; var dev = FS.makedev(FS.createDevice.major++, 0); // Create a fake device that a set of stream ops to emulate // the old behavior. @@ -3382,7 +3397,7 @@ function dbg(...args) { buffer[offset+i] = result; } if (bytesRead) { - stream.node.timestamp = Date.now(); + stream.node.atime = Date.now(); } return bytesRead; }, @@ -3395,7 +3410,7 @@ function dbg(...args) { } } if (length) { - stream.node.timestamp = Date.now(); + stream.node.mtime = stream.node.ctime = Date.now(); } return i; } @@ -3419,10 +3434,8 @@ function dbg(...args) { // Lazy chunked Uint8Array (implements get and length from Uint8Array). // Actual getting is abstracted away for eventual reuse. class LazyUint8Array { - constructor() { - this.lengthKnown = false; - this.chunks = []; // Loaded chunks. Index is the chunk number - } + lengthKnown = false; + chunks = []; // Loaded chunks. Index is the chunk number get(idx) { if (idx > this.length-1 || idx < 0) { return undefined; @@ -3619,7 +3632,7 @@ function dbg(...args) { } return dir; } - return PATH.join2(dir, path); + return dir + '/' + path; }, doStat(func, path, buf) { var stat = func(path); @@ -3636,11 +3649,11 @@ function dbg(...args) { var mtime = stat.mtime.getTime(); var ctime = stat.ctime.getTime(); (tempI64 = [Math.floor(atime / 1000)>>>0,(tempDouble = Math.floor(atime / 1000),(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(40))>>2)] = tempI64[0],HEAP32[(((buf)+(44))>>2)] = tempI64[1]); - HEAPU32[(((buf)+(48))>>2)] = (atime % 1000) * 1000; + HEAPU32[(((buf)+(48))>>2)] = (atime % 1000) * 1000 * 1000; (tempI64 = [Math.floor(mtime / 1000)>>>0,(tempDouble = Math.floor(mtime / 1000),(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(56))>>2)] = tempI64[0],HEAP32[(((buf)+(60))>>2)] = tempI64[1]); - HEAPU32[(((buf)+(64))>>2)] = (mtime % 1000) * 1000; + HEAPU32[(((buf)+(64))>>2)] = (mtime % 1000) * 1000 * 1000; (tempI64 = [Math.floor(ctime / 1000)>>>0,(tempDouble = Math.floor(ctime / 1000),(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(72))>>2)] = tempI64[0],HEAP32[(((buf)+(76))>>2)] = tempI64[1]); - HEAPU32[(((buf)+(80))>>2)] = (ctime % 1000) * 1000; + HEAPU32[(((buf)+(80))>>2)] = (ctime % 1000) * 1000 * 1000; (tempI64 = [stat.ino>>>0,(tempDouble = stat.ino,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(88))>>2)] = tempI64[0],HEAP32[(((buf)+(92))>>2)] = tempI64[1]); return 0; }, @@ -3665,7 +3678,7 @@ function dbg(...args) { return ret; }, }; - function ___syscall__newselect(nfds, readfds, writefds, exceptfds, timeout) { + var ___syscall__newselect = function (nfds, readfds, writefds, exceptfds, timeout) { try { // readfds are supported, @@ -3698,9 +3711,7 @@ function dbg(...args) { (writefds ? HEAP32[(((writefds)+(4))>>2)] : 0) | (exceptfds ? HEAP32[(((exceptfds)+(4))>>2)] : 0); - var check = function(fd, low, high, val) { - return (fd < 32 ? (low & val) : (high & val)); - }; + var check = (fd, low, high, val) => fd < 32 ? (low & val) : (high & val); for (var fd = 0; fd < nfds; fd++) { var mask = 1 << (fd % 32); @@ -3759,35 +3770,29 @@ function dbg(...args) { if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; return -e.errno; } - } + }; var SOCKFS = { + websocketArgs:{ + }, + callbacks:{ + }, + on(event, callback) { + SOCKFS.callbacks[event] = callback; + }, + emit(event, param) { + SOCKFS.callbacks[event]?.(param); + }, mount(mount) { - // If Module['websocket'] has already been defined (e.g. for configuring - // the subprotocol/url) use that, if not initialise it to a new object. - Module['websocket'] = (Module['websocket'] && - ('object' === typeof Module['websocket'])) ? Module['websocket'] : {}; - + // The incomming Module['websocket'] can be used for configuring + // configuring subprotocol/url, etc + SOCKFS.websocketArgs = Module['websocket'] || {}; // Add the Event registration mechanism to the exported websocket configuration // object so we can register network callbacks from native JavaScript too. // For more documentation see system/include/emscripten/emscripten.h - Module['websocket']._callbacks = {}; - Module['websocket']['on'] = /** @this{Object} */ function(event, callback) { - if ('function' === typeof callback) { - this._callbacks[event] = callback; - } - return this; - }; - - Module['websocket'].emit = /** @this{Object} */ function(event, param) { - if ('function' === typeof this._callbacks[event]) { - this._callbacks[event].call(this, param); - } - }; - - // If debug is enabled register simple default logging callbacks for each Event. + (Module['websocket'] ??= {})['on'] = SOCKFS.on; - return FS.createNode(null, '/', 16384 | 511 /* 0777 */, 0); + return FS.createNode(null, '/', 16895, 0); }, createSocket(family, type, protocol) { type &= ~526336; // Some applications may pass it; it makes no sense for a single process. @@ -3869,7 +3874,7 @@ function dbg(...args) { if (!SOCKFS.nextname.current) { SOCKFS.nextname.current = 0; } - return 'socket[' + (SOCKFS.nextname.current++) + ']'; + return `socket[${SOCKFS.nextname.current++}]`; }, websocket_sock_ops:{ createPeer(sock, addr, port) { @@ -3901,17 +3906,23 @@ function dbg(...args) { } else { // create the actual websocket object and connect try { - // runtimeConfig gets set to true if WebSocket runtime configuration is available. - var runtimeConfig = (Module['websocket'] && ('object' === typeof Module['websocket'])); - // The default value is 'ws://' the replace is needed because the compiler replaces '//' comments with '#' // comments without checking context, so we'd end up with ws:#, the replace swaps the '#' for '//' again. var url = 'ws:#'.replace('#', '//'); + // Make the WebSocket subprotocol (Sec-WebSocket-Protocol) default to binary if no configuration is set. + var subProtocols = 'binary'; // The default value is 'binary' + // The default WebSocket options + var opts = undefined; - if (runtimeConfig) { - if ('string' === typeof Module['websocket']['url']) { - url = Module['websocket']['url']; // Fetch runtime WebSocket URL config. - } + // Fetch runtime WebSocket URL config. + if (SOCKFS.websocketArgs['url']) { + url = SOCKFS.websocketArgs['url']; + } + // Fetch runtime WebSocket subprotocol config. + if (SOCKFS.websocketArgs['subprotocol']) { + subProtocols = SOCKFS.websocketArgs['subprotocol']; + } else if (SOCKFS.websocketArgs['subprotocol'] === null) { + subProtocols = 'null' } if (url === 'ws://' || url === 'wss://') { // Is the supplied URL config just a prefix, if so complete it. @@ -3919,18 +3930,6 @@ function dbg(...args) { url = url + parts[0] + ":" + port + "/" + parts.slice(1).join('/'); } - // Make the WebSocket subprotocol (Sec-WebSocket-Protocol) default to binary if no configuration is set. - var subProtocols = 'binary'; // The default value is 'binary' - - if (runtimeConfig) { - if ('string' === typeof Module['websocket']['subprotocol']) { - subProtocols = Module['websocket']['subprotocol']; // Fetch runtime WebSocket subprotocol config. - } - } - - // The default WebSocket options - var opts = undefined; - if (subProtocols !== 'null') { // The regex trims the string (removes spaces at the beginning and end, then splits the string by // <any space>,<any space> into an Array. Whitespace removal is important for Websockify and ws. @@ -3939,12 +3938,6 @@ function dbg(...args) { opts = subProtocols; } - // some webservers (azure) does not support subprotocol header - if (runtimeConfig && null === Module['websocket']['subprotocol']) { - subProtocols = 'null'; - opts = undefined; - } - // If node we use the ws library. var WebSocketConstructor; if (ENVIRONMENT_IS_NODE) { @@ -3964,7 +3957,7 @@ function dbg(...args) { addr, port, socket: ws, - dgram_send_queue: [] + msg_send_queue: [] }; SOCKFS.websocket_sock_ops.addPeer(sock, peer); @@ -3974,7 +3967,7 @@ function dbg(...args) { // us to override the ephemeral port reported to us by remotePort on the // remote end. if (sock.type === 2 && typeof sock.sport != 'undefined') { - peer.dgram_send_queue.push(new Uint8Array([ + peer.msg_send_queue.push(new Uint8Array([ 255, 255, 255, 255, 'p'.charCodeAt(0), 'o'.charCodeAt(0), 'r'.charCodeAt(0), 't'.charCodeAt(0), ((sock.sport & 0xff00) >> 8) , (sock.sport & 0xff) @@ -3997,13 +3990,14 @@ function dbg(...args) { var handleOpen = function () { - Module['websocket'].emit('open', sock.stream.fd); + sock.connecting = false; + SOCKFS.emit('open', sock.stream.fd); try { - var queued = peer.dgram_send_queue.shift(); + var queued = peer.msg_send_queue.shift(); while (queued) { peer.socket.send(queued); - queued = peer.dgram_send_queue.shift(); + queued = peer.msg_send_queue.shift(); } } catch (e) { // not much we can do here in the way of proper error handling as we've already @@ -4043,7 +4037,7 @@ function dbg(...args) { } sock.recv_queue.push({ addr: peer.addr, port: peer.port, data: data }); - Module['websocket'].emit('message', sock.stream.fd); + SOCKFS.emit('message', sock.stream.fd); }; if (ENVIRONMENT_IS_NODE) { @@ -4055,7 +4049,7 @@ function dbg(...args) { handleMessage((new Uint8Array(data)).buffer); // copy from node Buffer -> ArrayBuffer }); peer.socket.on('close', function() { - Module['websocket'].emit('close', sock.stream.fd); + SOCKFS.emit('close', sock.stream.fd); }); peer.socket.on('error', function(error) { // Although the ws library may pass errors that may be more descriptive than @@ -4063,13 +4057,13 @@ function dbg(...args) { // ENOTFOUND on getaddrinfo seems to be node.js specific, so using ECONNREFUSED // is still probably the most useful thing to do. sock.error = 14; // Used in getsockopt for SOL_SOCKET/SO_ERROR test. - Module['websocket'].emit('error', [sock.stream.fd, sock.error, 'ECONNREFUSED: Connection refused']); + SOCKFS.emit('error', [sock.stream.fd, sock.error, 'ECONNREFUSED: Connection refused']); // don't throw }); } else { peer.socket.onopen = handleOpen; peer.socket.onclose = function() { - Module['websocket'].emit('close', sock.stream.fd); + SOCKFS.emit('close', sock.stream.fd); }; peer.socket.onmessage = function peer_socket_onmessage(event) { handleMessage(event.data); @@ -4078,7 +4072,7 @@ function dbg(...args) { // The WebSocket spec only allows a 'simple event' to be thrown on error, // so we only really know as much as ECONNREFUSED. sock.error = 14; // Used in getsockopt for SOL_SOCKET/SO_ERROR test. - Module['websocket'].emit('error', [sock.stream.fd, sock.error, 'ECONNREFUSED: Connection refused']); + SOCKFS.emit('error', [sock.stream.fd, sock.error, 'ECONNREFUSED: Connection refused']); }; } }, @@ -4108,7 +4102,15 @@ function dbg(...args) { if ((dest && dest.socket.readyState === dest.socket.CLOSING) || (dest && dest.socket.readyState === dest.socket.CLOSED)) { - mask |= 16; + // When an non-blocking connect fails mark the socket as writable. + // Its up to the calling code to then use getsockopt with SO_ERROR to + // retrieve the error. + // See https://man7.org/linux/man-pages/man2/connect.2.html + if (sock.connecting) { + mask |= 4; + } else { + mask |= 16; + } } return mask; @@ -4199,8 +4201,10 @@ function dbg(...args) { sock.daddr = peer.addr; sock.dport = peer.port; - // always "fail" in non-blocking mode - throw new FS.ErrnoError(26); + // because we cannot synchronously block to wait for the WebSocket + // connection to complete, we return here pretending that the connection + // was a success. + sock.connecting = true; }, listen(sock, backlog) { if (!ENVIRONMENT_IS_NODE) { @@ -4216,7 +4220,7 @@ function dbg(...args) { port: sock.sport // TODO support backlog }); - Module['websocket'].emit('listen', sock.stream.fd); // Send Event with listen fd. + SOCKFS.emit('listen', sock.stream.fd); // Send Event with listen fd. sock.server.on('connection', function(ws) { if (sock.type === 1) { @@ -4229,17 +4233,17 @@ function dbg(...args) { // push to queue for accept to pick up sock.pending.push(newsock); - Module['websocket'].emit('connection', newsock.stream.fd); + SOCKFS.emit('connection', newsock.stream.fd); } else { // create a peer on the listen socket so calling sendto // with the listen socket and an address will resolve // to the correct client SOCKFS.websocket_sock_ops.createPeer(sock, ws); - Module['websocket'].emit('connection', sock.stream.fd); + SOCKFS.emit('connection', sock.stream.fd); } }); sock.server.on('close', function() { - Module['websocket'].emit('close', sock.stream.fd); + SOCKFS.emit('close', sock.stream.fd); sock.server = null; }); sock.server.on('error', function(error) { @@ -4250,7 +4254,7 @@ function dbg(...args) { // occur in a well written app as errors should get trapped in the compiled // app's own getaddrinfo call. sock.error = 23; // Used in getsockopt for SOL_SOCKET/SO_ERROR test. - Module['websocket'].emit('error', [sock.stream.fd, sock.error, 'EHOSTUNREACH: Host is unreachable']); + SOCKFS.emit('error', [sock.stream.fd, sock.error, 'EHOSTUNREACH: Host is unreachable']); // don't throw }); }, @@ -4303,8 +4307,6 @@ function dbg(...args) { if (sock.type === 1) { if (!dest || dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) { throw new FS.ErrnoError(53); - } else if (dest.socket.readyState === dest.socket.CONNECTING) { - throw new FS.ErrnoError(6); } } @@ -4316,21 +4318,20 @@ function dbg(...args) { buffer = buffer.buffer; } - var data; - data = buffer.slice(offset, offset + length); + var data = buffer.slice(offset, offset + length); - // if we're emulating a connection-less dgram socket and don't have - // a cached connection, queue the buffer to send upon connect and - // lie, saying the data was sent now. - if (sock.type === 2) { - if (!dest || dest.socket.readyState !== dest.socket.OPEN) { - // if we're not connected, open a new connection + // if we don't have a cached connectionless UDP datagram connection, or + // the TCP socket is still connecting, queue the message to be sent upon + // connect, and lie, saying the data was sent now. + if (!dest || dest.socket.readyState !== dest.socket.OPEN) { + // if we're not connected, open a new connection + if (sock.type === 2) { if (!dest || dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) { dest = SOCKFS.websocket_sock_ops.createPeer(sock, addr, port); } - dest.dgram_send_queue.push(data); - return length; } + dest.msg_send_queue.push(data); + return length; } try { @@ -4579,9 +4580,8 @@ function dbg(...args) { - var inetNtop4 = (addr) => { - return (addr & 0xff) + '.' + ((addr >> 8) & 0xff) + '.' + ((addr >> 16) & 0xff) + '.' + ((addr >> 24) & 0xff) - }; + var inetNtop4 = (addr) => + (addr & 0xff) + '.' + ((addr >> 8) & 0xff) + '.' + ((addr >> 16) & 0xff) + '.' + ((addr >> 24) & 0xff); var inetNtop6 = (ints) => { @@ -4715,9 +4715,7 @@ function dbg(...args) { }; - /** @param {boolean=} allowNull */ - var getSocketAddress = (addrp, addrlen, allowNull) => { - if (allowNull && addrp === 0) return null; + var getSocketAddress = (addrp, addrlen) => { var info = readSockaddr(addrp, addrlen); if (info.errno) throw new FS.ErrnoError(info.errno); info.addr = DNS.lookup_addr(info.addr) || info.addr; @@ -4789,7 +4787,7 @@ function dbg(...args) { try { path = SYSCALLS.getStr(path); - assert(flags === 0); + assert(flags === 0 || flags == 512); path = SYSCALLS.calculateAt(dirfd, path); if (amode & ~7) { // need a valid mode @@ -4831,13 +4829,13 @@ function dbg(...args) { } /** @suppress {duplicate } */ - function syscallGetVarargI() { + var syscallGetVarargI = () => { assert(SYSCALLS.varargs != undefined); // the `+` prepended here is necessary to convince the JSCompiler that varargs is indeed a number. var ret = HEAP32[((+SYSCALLS.varargs)>>2)]; SYSCALLS.varargs += 4; return ret; - } + }; var syscallGetVarargP = syscallGetVarargI; @@ -4961,9 +4959,9 @@ function dbg(...args) { var pos = 0; var off = FS.llseek(stream, 0, 1); - var idx = Math.floor(off / struct_size); - - while (idx < stream.getdents.length && pos + struct_size <= count) { + var startIdx = Math.floor(off / struct_size); + var endIdx = Math.min(stream.getdents.length, startIdx + Math.floor(count/struct_size)) + for (var idx = startIdx; idx < endIdx; idx++) { var id; var type; var name = stream.getdents[idx]; @@ -4977,7 +4975,17 @@ function dbg(...args) { type = 4; // DT_DIR } else { - var child = FS.lookupNode(stream.node, name); + var child; + try { + child = FS.lookupNode(stream.node, name); + } catch (e) { + // If the entry is not a directory, file, or symlink, nodefs + // lookupNode will raise EINVAL. Skip these and continue. + if (e?.errno === 28) { + continue; + } + throw e; + } id = child.id; type = FS.isChrdev(child.mode) ? 2 : // DT_CHR, character device. FS.isDir(child.mode) ? 4 : // DT_DIR, directory. @@ -4991,7 +4999,6 @@ function dbg(...args) { HEAP8[(dirp + pos)+(18)] = type; stringToUTF8(name, dirp + pos + 19, 256); pos += struct_size; - idx += 1; } FS.llseek(stream, idx * struct_size, 0); return pos; @@ -5180,10 +5187,6 @@ function dbg(...args) { path = SYSCALLS.getStr(path); path = SYSCALLS.calculateAt(dirfd, path); - // remove a trailing slash, if one - /a/b/ has basename of '', but - // we want to create b in the context of this function - path = PATH.normalize(path); - if (path[path.length-1] === '/') path = path.substr(0, path.length-1); FS.mkdir(path, mode, 0); return 0; } catch (e) { @@ -5228,7 +5231,7 @@ function dbg(...args) { mount(mount) { // Do not pollute the real root directory or its child nodes with pipes // Looks like it is OK to create another pseudo-root node not linked to the FS.root hierarchy this way - return FS.createNode(null, '/', 16384 | 511 /* 0777 */, 0); + return FS.createNode(null, '/', 16384 | 0o777, 0); }, createPipe() { var pipe = { @@ -5557,11 +5560,11 @@ function dbg(...args) { try { var sock = getSocketFromFD(fd); - var dest = getSocketAddress(addr, addr_len, true); - if (!dest) { + if (!addr) { // send, no address provided return FS.write(sock.stream, HEAP8, message, length); } + var dest = getSocketAddress(addr, addr_len); // sendto an address return sock.sock_ops.sendmsg(sock, HEAP8, message, length, dest.addr, dest.port); } catch (e) { @@ -5596,20 +5599,18 @@ function dbg(...args) { function ___syscall_statfs64(path, size, buf) { try { - path = SYSCALLS.getStr(path); assert(size === 64); - // NOTE: None of the constants here are true. We're just returning safe and - // sane values. - HEAP32[(((buf)+(4))>>2)] = 4096; - HEAP32[(((buf)+(40))>>2)] = 4096; - HEAP32[(((buf)+(8))>>2)] = 1000000; - HEAP32[(((buf)+(12))>>2)] = 500000; - HEAP32[(((buf)+(16))>>2)] = 500000; - HEAP32[(((buf)+(20))>>2)] = FS.nextInode; - HEAP32[(((buf)+(24))>>2)] = 1000000; - HEAP32[(((buf)+(28))>>2)] = 42; - HEAP32[(((buf)+(44))>>2)] = 2; // ST_NOSUID - HEAP32[(((buf)+(36))>>2)] = 255; + var stats = FS.statfs(SYSCALLS.getStr(path)); + HEAP32[(((buf)+(4))>>2)] = stats.bsize; + HEAP32[(((buf)+(40))>>2)] = stats.bsize; + HEAP32[(((buf)+(8))>>2)] = stats.blocks; + HEAP32[(((buf)+(12))>>2)] = stats.bfree; + HEAP32[(((buf)+(16))>>2)] = stats.bavail; + HEAP32[(((buf)+(20))>>2)] = stats.files; + HEAP32[(((buf)+(24))>>2)] = stats.ffree; + HEAP32[(((buf)+(28))>>2)] = stats.fsid; + HEAP32[(((buf)+(44))>>2)] = stats.flags; // ST_NOSUID + HEAP32[(((buf)+(36))>>2)] = stats.namelen; return 0; } catch (e) { if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; @@ -5617,11 +5618,12 @@ function dbg(...args) { } } - function ___syscall_symlink(target, linkpath) { + function ___syscall_symlinkat(target, dirfd, linkpath) { try { target = SYSCALLS.getStr(target); linkpath = SYSCALLS.getStr(linkpath); + linkpath = SYSCALLS.calculateAt(dirfd, linkpath); FS.symlink(target, linkpath); return 0; } catch (e) { @@ -5659,19 +5661,36 @@ function dbg(...args) { path = SYSCALLS.getStr(path); assert(flags === 0); path = SYSCALLS.calculateAt(dirfd, path, true); + var now = Date.now(), atime, mtime; if (!times) { - var atime = Date.now(); - var mtime = atime; + atime = now; + mtime = now; } else { var seconds = readI53FromI64(times); var nanoseconds = HEAP32[(((times)+(8))>>2)]; - atime = (seconds*1000) + (nanoseconds/(1000*1000)); + if (nanoseconds == 1073741823) { + atime = now; + } else if (nanoseconds == 1073741822) { + atime = null; + } else { + atime = (seconds*1000) + (nanoseconds/(1000*1000)); + } times += 16; seconds = readI53FromI64(times); nanoseconds = HEAP32[(((times)+(8))>>2)]; - mtime = (seconds*1000) + (nanoseconds/(1000*1000)); + if (nanoseconds == 1073741823) { + mtime = now; + } else if (nanoseconds == 1073741822) { + mtime = null; + } else { + mtime = (seconds*1000) + (nanoseconds/(1000*1000)); + } + } + // null here means UTIME_OMIT was passed. If both were set to UTIME_OMIT then + // we can skip the call completely. + if ((mtime ?? atime) !== null) { + FS.utime(path, atime, mtime); } - FS.utime(path, atime, mtime); return 0; } catch (e) { if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; @@ -5679,12 +5698,8 @@ function dbg(...args) { } } - var __abort_js = () => { + var __abort_js = () => abort('native code called abort()'); - }; - - var nowIsMonotonic = 1; - var __emscripten_get_now_is_monotonic = () => nowIsMonotonic; @@ -5697,6 +5712,7 @@ function dbg(...args) { var __emscripten_memcpy_js = (dest, src, num) => HEAPU8.copyWithin(dest, src, src + num); + var runtimeKeepaliveCounter = 0; var __emscripten_runtime_keepalive_clear = () => { noExitRuntime = false; runtimeKeepaliveCounter = 0; @@ -5884,7 +5900,6 @@ function dbg(...args) { }; - var runtimeKeepaliveCounter = 0; var keepRuntimeAlive = () => noExitRuntime || runtimeKeepaliveCounter > 0; var _proc_exit = (code) => { EXITSTATUS = code; @@ -5895,6 +5910,7 @@ function dbg(...args) { quit_(code, new ExitStatus(code)); }; + /** @suppress {duplicate } */ /** @param {boolean|number=} implicit */ var exitJS = (status, implicit) => { @@ -5937,12 +5953,7 @@ function dbg(...args) { }; - var _emscripten_get_now; - // Modern environment where performance.now() is supported: - // N.B. a shorter form "_emscripten_get_now = performance.now;" is - // unfortunately not allowed even in current browsers (e.g. FF Nightly 75). - _emscripten_get_now = () => performance.now(); - ; + var _emscripten_get_now = () => performance.now(); var __setitimer_js = (which, timeout_ms) => { // First, clear any existing timer. if (timers[which]) { @@ -5989,9 +6000,20 @@ function dbg(...args) { HEAP32[((daylight)>>2)] = Number(winterOffset != summerOffset); - var extractZone = (date) => date.toLocaleTimeString(undefined, {hour12:false, timeZoneName:'short'}).split(' ')[1]; - var winterName = extractZone(winter); - var summerName = extractZone(summer); + var extractZone = (timezoneOffset) => { + // Why inverse sign? + // Read here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTimezoneOffset + var sign = timezoneOffset >= 0 ? "-" : "+"; + + var absOffset = Math.abs(timezoneOffset) + var hours = String(Math.floor(absOffset / 60)).padStart(2, "0"); + var minutes = String(absOffset % 60).padStart(2, "0"); + + return `UTC${sign}${hours}${minutes}`; + } + + var winterName = extractZone(winterOffset); + var summerName = extractZone(summerOffset); assert(winterName); assert(summerName); assert(lengthBytesUTF8(winterName) <= 16, `timezone name truncated to fit in TZNAME_MAX (${winterName})`); @@ -6006,7 +6028,36 @@ function dbg(...args) { } }; + var _emscripten_date_now = () => Date.now(); + + var nowIsMonotonic = 1; + + var checkWasiClock = (clock_id) => clock_id >= 0 && clock_id <= 3; + + function _clock_time_get(clk_id,ignored_precision_low, ignored_precision_high,ptime) { + var ignored_precision = convertI32PairToI53Checked(ignored_precision_low, ignored_precision_high); + + + if (!checkWasiClock(clk_id)) { + return 28; + } + var now; + // all wasi clocks but realtime are monotonic + if (clk_id === 0) { + now = _emscripten_date_now(); + } else if (nowIsMonotonic) { + now = _emscripten_get_now(); + } else { + return 52; + } + // "now" is in ms, and wasi times are in ns. + var nsec = Math.round(now * 1000 * 1000); + (tempI64 = [nsec>>>0,(tempDouble = nsec,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[((ptime)>>2)] = tempI64[0],HEAP32[(((ptime)+(4))>>2)] = tempI64[1]); + return 0; + ; + } + var _emscripten_err = (str) => err(UTF8ToString(str)); @@ -6016,6 +6067,7 @@ function dbg(...args) { + var abortOnCannotGrowMemory = (requestedSize) => { abort(`Cannot enlarge memory arrays to size ${requestedSize} bytes (OOM). Either (1) compile with -sINITIAL_MEMORY=X with X higher than the current value ${HEAP8.length}, (2) compile with -sALLOW_MEMORY_GROWTH which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with -sABORTING_MALLOC=0`); }; @@ -6029,9 +6081,7 @@ function dbg(...args) { var ENV = { }; - var getExecutableName = () => { - return thisProgram || './this.program'; - }; + var getExecutableName = () => thisProgram || './this.program'; var getEnvStrings = () => { if (!getEnvStrings.strings) { // Default values. @@ -6205,6 +6255,10 @@ function dbg(...args) { var curr = FS.write(stream, HEAP8, ptr, len, offset); if (curr < 0) return -1; ret += curr; + if (curr < len) { + // No more space to write. + break; + } if (typeof offset != 'undefined') { offset += curr; } @@ -6343,7 +6397,7 @@ function dbg(...args) { if (family === 2) { addr = _htonl(2130706433); } else { - addr = [0, 0, 0, 1]; + addr = [0, 0, 0, _htonl(1)]; } } ai = allocaddrinfo(family, type, proto, null, addr, port); @@ -6895,7 +6949,6 @@ function dbg(...args) { 'string': (str) => { var ret = 0; if (str !== null && str !== undefined && str !== 0) { // null string - // at most 4 bytes per UTF-8 code point, +1 for the trailing '\0' ret = stringToUTF8OnStack(str); } return ret; @@ -6909,7 +6962,6 @@ function dbg(...args) { function convertReturnValue(ret) { if (returnType === 'string') { - return UTF8ToString(ret); } if (returnType === 'boolean') return Boolean(ret); @@ -6942,7 +6994,9 @@ function dbg(...args) { }; FS.createPreloadedFile = FS_createPreloadedFile; - FS.staticInit();; + FS.staticInit(); + // Set module methods based on EXPORTED_RUNTIME_METHODS + ; function checkIncomingModuleAPI() { ignoredModuleProp('fetchSettings'); } @@ -7020,7 +7074,7 @@ var wasmImports = { /** @export */ __syscall_statfs64: ___syscall_statfs64, /** @export */ - __syscall_symlink: ___syscall_symlink, + __syscall_symlinkat: ___syscall_symlinkat, /** @export */ __syscall_unlinkat: ___syscall_unlinkat, /** @export */ @@ -7028,8 +7082,6 @@ var wasmImports = { /** @export */ _abort_js: __abort_js, /** @export */ - _emscripten_get_now_is_monotonic: __emscripten_get_now_is_monotonic, - /** @export */ _emscripten_lookup_name: __emscripten_lookup_name, /** @export */ _emscripten_memcpy_js: __emscripten_memcpy_js, @@ -7052,6 +7104,8 @@ var wasmImports = { /** @export */ _tzset_js: __tzset_js, /** @export */ + clock_time_get: _clock_time_get, + /** @export */ emscripten_date_now: _emscripten_date_now, /** @export */ emscripten_err: _emscripten_err, @@ -7122,8 +7176,6 @@ var wasmImports = { /** @export */ invoke_viiiii, /** @export */ - invoke_viiiiii, - /** @export */ makecontext: _makecontext, /** @export */ posix_spawnp: _posix_spawnp, @@ -7134,7 +7186,8 @@ var wasmImports = { /** @export */ swapcontext: _swapcontext }; -var wasmExports = createWasm(); +var wasmExports; +createWasm(); var ___wasm_call_ctors = createExportWrapper('__wasm_call_ctors', 0); var _php_wasm_run = Module['_php_wasm_run'] = createExportWrapper('php_wasm_run', 1); var _fflush = createExportWrapper('fflush', 1); @@ -7154,8 +7207,6 @@ var _emscripten_stack_get_end = () => (_emscripten_stack_get_end = wasmExports[' var __emscripten_stack_restore = (a0) => (__emscripten_stack_restore = wasmExports['_emscripten_stack_restore'])(a0); var __emscripten_stack_alloc = (a0) => (__emscripten_stack_alloc = wasmExports['_emscripten_stack_alloc'])(a0); var _emscripten_stack_get_current = () => (_emscripten_stack_get_current = wasmExports['emscripten_stack_get_current'])(); -var dynCall_vij = Module['dynCall_vij'] = createExportWrapper('dynCall_vij', 4); -var dynCall_ji = Module['dynCall_ji'] = createExportWrapper('dynCall_ji', 2); var dynCall_jiji = Module['dynCall_jiji'] = createExportWrapper('dynCall_jiji', 5); function invoke_iii(index,a1,a2) { @@ -7323,17 +7374,6 @@ function invoke_viidii(index,a1,a2,a3,a4,a5) { } } -function invoke_viiiiii(index,a1,a2,a3,a4,a5,a6) { - var sp = stackSave(); - try { - getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6); - } catch(e) { - stackRestore(sp); - if (e !== e+0) throw e; - _setThrew(1, 0); - } -} - // include: postamble.js // === Auto-generated postamble setup entry stuff === @@ -7434,14 +7474,15 @@ var missingLibrarySymbols = [ 'jsStackTrace', 'getCallstack', 'convertPCtoSourceLocation', - 'checkWasiClock', 'wasiRightsToMuslOFlags', 'wasiOFlagsToMuslOFlags', - 'createDyncallWrapper', 'safeSetTimeout', 'setImmediateWrapped', + 'safeRequestAnimationFrame', 'clearImmediateWrapped', 'polyfillSetImmediate', + 'registerPostMainLoop', + 'registerPreMainLoop', 'getPromise', 'makePromise', 'idsToPromises', @@ -7449,7 +7490,6 @@ var missingLibrarySymbols = [ 'ExceptionInfo', 'findMatchingCatch', 'Browser_asyncPrepareDataCounter', - 'setMainLoop', 'FS_unlink', 'FS_mkdirTree', '_setNetworkCallback', @@ -7459,6 +7499,9 @@ var missingLibrarySymbols = [ 'webgl_enable_OES_vertex_array_object', 'webgl_enable_WEBGL_draw_buffers', 'webgl_enable_WEBGL_multi_draw', + 'webgl_enable_EXT_polygon_offset_clamp', + 'webgl_enable_EXT_clip_control', + 'webgl_enable_WEBGL_polygon_mode', 'emscriptenWebGLGet', 'computeUnpackAlignedImageSize', 'colorChannelsInGlTextureFormat', @@ -7512,14 +7555,6 @@ var unexportedSymbols = [ 'getHeapMax', 'abortOnCannotGrowMemory', 'ENV', - 'MONTH_DAYS_REGULAR', - 'MONTH_DAYS_LEAP', - 'MONTH_DAYS_REGULAR_CUMULATIVE', - 'MONTH_DAYS_LEAP_CUMULATIVE', - 'isLeapYear', - 'ydayFromDate', - 'arraySum', - 'addDays', 'ERRNO_CODES', 'strError', 'inetPton4', @@ -7531,8 +7566,6 @@ var unexportedSymbols = [ 'DNS', 'Protocols', 'Sockets', - 'initRandomFill', - 'randomFill', 'timers', 'warnOnce', 'readEmAsmArgsArray', @@ -7574,8 +7607,11 @@ var unexportedSymbols = [ 'UNWIND_CACHE', 'ExitStatus', 'getEnvStrings', + 'checkWasiClock', 'doReadv', 'doWritev', + 'initRandomFill', + 'randomFill', 'promiseMap', 'uncaughtExceptionCount', 'exceptionLast', @@ -7583,6 +7619,14 @@ var unexportedSymbols = [ 'Browser', 'getPreloadedImageData__data', 'wget', + 'MONTH_DAYS_REGULAR', + 'MONTH_DAYS_LEAP', + 'MONTH_DAYS_REGULAR_CUMULATIVE', + 'MONTH_DAYS_LEAP_CUMULATIVE', + 'isLeapYear', + 'ydayFromDate', + 'arraySum', + 'addDays', 'SYSCALLS', 'getSocketFromFD', 'getSocketAddress', @@ -7645,7 +7689,7 @@ function run() { return; } - stackCheckInit(); + stackCheckInit(); preRun(); @@ -7675,10 +7719,8 @@ function run() { if (Module['setStatus']) { Module['setStatus']('Running...'); - setTimeout(function() { - setTimeout(function() { - Module['setStatus'](''); - }, 1); + setTimeout(() => { + setTimeout(() => Module['setStatus'](''), 1); doRun(); }, 1); } else @@ -7709,7 +7751,7 @@ function checkUnflushedContent() { try { // it doesn't matter if it fails _fflush(0); // also flush in the JS FS layer - ['stdout', 'stderr'].forEach(function(name) { + ['stdout', 'stderr'].forEach((name) => { var info = FS.analyzePath('/dev/' + name); if (!info) return; var stream = info.object; diff --git a/examples/compile-php-to-wasm/php-wasm.wasm b/examples/compile-php-to-wasm/php-wasm.wasm Binary files differindex d3238d0..d214beb 100755 --- a/examples/compile-php-to-wasm/php-wasm.wasm +++ b/examples/compile-php-to-wasm/php-wasm.wasm diff --git a/examples/php-on-wasm/php-wasm.php b/examples/php-on-wasm/php-wasm.php index 2401985..6a07829 100644 --- a/examples/php-on-wasm/php-wasm.php +++ b/examples/php-on-wasm/php-wasm.php @@ -50,7 +50,6 @@ $imports = [ 'getprotobynumber' => makeHostFunc('(i32) -> (i32)', hostFunc__env__getprotobynumber(...)), 'strptime' => makeHostFunc('(i32, i32, i32) -> (i32)', hostFunc__env__strptime(...)), 'getnameinfo' => makeHostFunc('(i32, i32, i32, i32, i32, i32, i32) -> (i32)', hostFunc__env__getnameinfo(...)), - 'invoke_viiiiii' => makeHostFunc('(i32, i32, i32, i32, i32, i32, i32) -> ()', hostFunc__env__invoke_viiiiii(...)), 'invoke_viidii' => makeHostFunc('(i32, i32, i32, f64, i32, i32) -> ()', hostFunc__env__invoke_viidii(...)), 'getcontext' => makeHostFunc('(i32) -> (i32)', hostFunc__env__getcontext(...)), 'makecontext' => makeHostFunc('(i32, i32, i32, i32) -> ()', hostFunc__env__makecontext(...)), @@ -64,7 +63,6 @@ $imports = [ '__syscall_dup' => makeHostFunc('(i32) -> (i32)', hostFunc__env____syscall_dup(...)), '_emscripten_memcpy_js' => makeHostFunc('(i32, i32, i32) -> ()', hostFunc__env___emscripten_memcpy_js(...)), 'emscripten_date_now' => makeHostFunc('() -> (f64)', hostFunc__env__emscripten_date_now(...)), - '_emscripten_get_now_is_monotonic' => makeHostFunc('() -> (i32)', hostFunc__env___emscripten_get_now_is_monotonic(...)), 'emscripten_get_now' => makeHostFunc('() -> (f64)', hostFunc__env__emscripten_get_now(...)), '__syscall_fdatasync' => makeHostFunc('(i32) -> (i32)', hostFunc__env____syscall_fdatasync(...)), '__syscall_openat' => makeHostFunc('(i32, i32, i32, i32) -> (i32)', hostFunc__env____syscall_openat(...)), @@ -86,7 +84,7 @@ $imports = [ '__syscall__newselect' => makeHostFunc('(i32, i32, i32, i32, i32) -> (i32)', hostFunc__env____syscall__newselect(...)), '_setitimer_js' => makeHostFunc('(i32, f64) -> (i32)', hostFunc__env___setitimer_js(...)), '__syscall_statfs64' => makeHostFunc('(i32, i32, i32) -> (i32)', hostFunc__env____syscall_statfs64(...)), - '__syscall_symlink' => makeHostFunc('(i32, i32) -> (i32)', hostFunc__env____syscall_symlink(...)), + '__syscall_symlinkat' => makeHostFunc('(i32, i32, i32) -> (i32)', hostFunc__env____syscall_symlinkat(...)), 'emscripten_get_heap_max' => makeHostFunc('() -> (i32)', hostFunc__env__emscripten_get_heap_max(...)), '_tzset_js' => makeHostFunc('(i32, i32, i32) -> ()', hostFunc__env___tzset_js(...)), '__syscall_unlinkat' => makeHostFunc('(i32, i32, i32) -> (i32)', hostFunc__env____syscall_unlinkat(...)), @@ -120,6 +118,7 @@ $imports = [ 'proc_exit' => makeHostFunc('(i32) -> ()', hostFunc__wasi_snapshot_preview1__proc_exit(...)), 'fd_sync' => makeHostFunc('(i32) -> (i32)', hostFunc__wasi_snapshot_preview1__fd_sync(...)), 'fd_fdstat_get' => makeHostFunc('(i32, i32) -> (i32)', hostFunc__wasi_snapshot_preview1__fd_fdstat_get(...)), + 'clock_time_get' => makeHostFunc('(i32, i32, i32, i32) -> (i32)', hostFunc__wasi_snapshot_preview1__clock_time_get(...)), 'fd_seek' => makeHostFunc('(i32, i32, i32, i32, i32) -> (i32)', hostFunc__wasi_snapshot_preview1__fd_seek(...)), ], ]; @@ -481,20 +480,6 @@ function hostFunc__env__getnameinfo(Runtime $runtime): void throw new \RuntimeException('env::getnameinfo: not implemented'); } -// Type: (i32, i32, i32, i32, i32, i32, i32) -> () -function hostFunc__env__invoke_viiiiii(Runtime $runtime, int $index, int $a1, int $a2, int $a3, int $a4, int $a5, int $a6): void -{ - $sp = emscripten_stack_get_current($runtime); - $func = getWasmTableEntry($runtime, $index); - $runtime->stack->pushValue($a1); - $runtime->stack->pushValue($a2); - $runtime->stack->pushValue($a3); - $runtime->stack->pushValue($a4); - $runtime->stack->pushValue($a5); - $runtime->stack->pushValue($a6); - $runtime->invokeByFuncAddr($func); -} - // Type: (i32, i32, i32, f64, i32, i32) -> () function hostFunc__env__invoke_viidii(Runtime $runtime, int $index, int $a1, int $a2, float $a3, int $a4, int $a5): void { @@ -652,12 +637,6 @@ function hostFunc__env__emscripten_date_now(Runtime $runtime): float return round(microtime(true) * 1000); } -// Type: () -> (i32) -function hostFunc__env___emscripten_get_now_is_monotonic(Runtime $runtime): int -{ - return 1; -} - // Type: () -> (f64) function hostFunc__env__emscripten_get_now(Runtime $runtime): float { @@ -820,10 +799,10 @@ function hostFunc__env____syscall_statfs64(Runtime $runtime): void throw new \RuntimeException('env::__syscall_statfs64: not implemented'); } -// Type: (i32, i32) -> (i32) -function hostFunc__env____syscall_symlink(Runtime $runtime): void +// Type: (i32, i32, i32) -> (i32) +function hostFunc__env____syscall_symlinkat(Runtime $runtime): void { - throw new \RuntimeException('env::__syscall_symlink: not implemented'); + throw new \RuntimeException('env::__syscall_symlinkat: not implemented'); } // Type: () -> (i32) @@ -934,6 +913,27 @@ function hostFunc__env____syscall_ftruncate64(Runtime $runtime): void throw new \RuntimeException('env::__syscall_ftruncate64: not implemented'); } +// Type: (i32, i32, i32, i32) -> (i32) +function hostFunc__wasi_snapshot_preview1__clock_time_get(Runtime $runtime, int $clk_id, int $ignored_precision_low, int $ignored_precision_high, int $ptime): int +{ + if ($clk_id < 0 || 3 < $clk_id) { + return 28; + } + if ($clk_id === 0) { + $now = hostFunc__env__emscripten_date_now($runtime); + } else { + $now = hostFunc__env__emscripten_get_now($runtime); + } + $nsec = round($now * 1000 * 1000); + + $mem = $runtime->getExportedMemory('memory'); + \assert($mem !== null); + $mem->storeI32_s32($ptime, $nsec & 0xFFFFFFFF); + $mem->storeI32_s32($ptime + 4, $nsec >> 32); + + return 0; +} + // Type: (i32, i32, i32, i32, i32) -> (i32) function hostFunc__wasi_snapshot_preview1__fd_seek(Runtime $runtime): void { diff --git a/examples/rubyvm-on-php-on-wasm/php-wasm.php b/examples/rubyvm-on-php-on-wasm/php-wasm.php index 492d91e..ef8408d 100644 --- a/examples/rubyvm-on-php-on-wasm/php-wasm.php +++ b/examples/rubyvm-on-php-on-wasm/php-wasm.php @@ -50,7 +50,6 @@ $imports = [ 'getprotobynumber' => makeHostFunc('(i32) -> (i32)', hostFunc__env__getprotobynumber(...)), 'strptime' => makeHostFunc('(i32, i32, i32) -> (i32)', hostFunc__env__strptime(...)), 'getnameinfo' => makeHostFunc('(i32, i32, i32, i32, i32, i32, i32) -> (i32)', hostFunc__env__getnameinfo(...)), - 'invoke_viiiiii' => makeHostFunc('(i32, i32, i32, i32, i32, i32, i32) -> ()', hostFunc__env__invoke_viiiiii(...)), 'invoke_viidii' => makeHostFunc('(i32, i32, i32, f64, i32, i32) -> ()', hostFunc__env__invoke_viidii(...)), 'getcontext' => makeHostFunc('(i32) -> (i32)', hostFunc__env__getcontext(...)), 'makecontext' => makeHostFunc('(i32, i32, i32, i32) -> ()', hostFunc__env__makecontext(...)), @@ -64,7 +63,6 @@ $imports = [ '__syscall_dup' => makeHostFunc('(i32) -> (i32)', hostFunc__env____syscall_dup(...)), '_emscripten_memcpy_js' => makeHostFunc('(i32, i32, i32) -> ()', hostFunc__env___emscripten_memcpy_js(...)), 'emscripten_date_now' => makeHostFunc('() -> (f64)', hostFunc__env__emscripten_date_now(...)), - '_emscripten_get_now_is_monotonic' => makeHostFunc('() -> (i32)', hostFunc__env___emscripten_get_now_is_monotonic(...)), 'emscripten_get_now' => makeHostFunc('() -> (f64)', hostFunc__env__emscripten_get_now(...)), '__syscall_fdatasync' => makeHostFunc('(i32) -> (i32)', hostFunc__env____syscall_fdatasync(...)), '__syscall_openat' => makeHostFunc('(i32, i32, i32, i32) -> (i32)', hostFunc__env____syscall_openat(...)), @@ -86,7 +84,7 @@ $imports = [ '__syscall__newselect' => makeHostFunc('(i32, i32, i32, i32, i32) -> (i32)', hostFunc__env____syscall__newselect(...)), '_setitimer_js' => makeHostFunc('(i32, f64) -> (i32)', hostFunc__env___setitimer_js(...)), '__syscall_statfs64' => makeHostFunc('(i32, i32, i32) -> (i32)', hostFunc__env____syscall_statfs64(...)), - '__syscall_symlink' => makeHostFunc('(i32, i32) -> (i32)', hostFunc__env____syscall_symlink(...)), + '__syscall_symlinkat' => makeHostFunc('(i32, i32, i32) -> (i32)', hostFunc__env____syscall_symlinkat(...)), 'emscripten_get_heap_max' => makeHostFunc('() -> (i32)', hostFunc__env__emscripten_get_heap_max(...)), '_tzset_js' => makeHostFunc('(i32, i32, i32) -> ()', hostFunc__env___tzset_js(...)), '__syscall_unlinkat' => makeHostFunc('(i32, i32, i32) -> (i32)', hostFunc__env____syscall_unlinkat(...)), @@ -120,6 +118,7 @@ $imports = [ 'proc_exit' => makeHostFunc('(i32) -> ()', hostFunc__wasi_snapshot_preview1__proc_exit(...)), 'fd_sync' => makeHostFunc('(i32) -> (i32)', hostFunc__wasi_snapshot_preview1__fd_sync(...)), 'fd_fdstat_get' => makeHostFunc('(i32, i32) -> (i32)', hostFunc__wasi_snapshot_preview1__fd_fdstat_get(...)), + 'clock_time_get' => makeHostFunc('(i32, i32, i32, i32) -> (i32)', hostFunc__wasi_snapshot_preview1__clock_time_get(...)), 'fd_seek' => makeHostFunc('(i32, i32, i32, i32, i32) -> (i32)', hostFunc__wasi_snapshot_preview1__fd_seek(...)), ], ]; @@ -826,20 +825,6 @@ function hostFunc__env__getnameinfo(Runtime $runtime): void throw new \RuntimeException('env::getnameinfo: not implemented'); } -// Type: (i32, i32, i32, i32, i32, i32, i32) -> () -function hostFunc__env__invoke_viiiiii(Runtime $runtime, int $index, int $a1, int $a2, int $a3, int $a4, int $a5, int $a6): void -{ - $sp = emscripten_stack_get_current($runtime); - $func = getWasmTableEntry($runtime, $index); - $runtime->stack->pushValue($a1); - $runtime->stack->pushValue($a2); - $runtime->stack->pushValue($a3); - $runtime->stack->pushValue($a4); - $runtime->stack->pushValue($a5); - $runtime->stack->pushValue($a6); - $runtime->invokeByFuncAddr($func); -} - // Type: (i32, i32, i32, f64, i32, i32) -> () function hostFunc__env__invoke_viidii(Runtime $runtime, int $index, int $a1, int $a2, float $a3, int $a4, int $a5): void { @@ -1069,12 +1054,6 @@ function hostFunc__env__emscripten_date_now(Runtime $runtime): float return round(microtime(true) * 1000); } -// Type: () -> (i32) -function hostFunc__env___emscripten_get_now_is_monotonic(Runtime $runtime): int -{ - return 1; -} - // Type: () -> (f64) function hostFunc__env__emscripten_get_now(Runtime $runtime): float { @@ -1285,10 +1264,10 @@ function hostFunc__env____syscall_statfs64(Runtime $runtime): void throw new \RuntimeException('env::__syscall_statfs64: not implemented'); } -// Type: (i32, i32) -> (i32) -function hostFunc__env____syscall_symlink(Runtime $runtime): void +// Type: (i32, i32, i32) -> (i32) +function hostFunc__env____syscall_symlinkat(Runtime $runtime): void { - throw new \RuntimeException('env::__syscall_symlink: not implemented'); + throw new \RuntimeException('env::__syscall_symlinkat: not implemented'); } // Type: () -> (i32) @@ -1399,6 +1378,27 @@ function hostFunc__env____syscall_ftruncate64(Runtime $runtime): void throw new \RuntimeException('env::__syscall_ftruncate64: not implemented'); } +// Type: (i32, i32, i32, i32) -> (i32) +function hostFunc__wasi_snapshot_preview1__clock_time_get(Runtime $runtime, int $clk_id, int $ignored_precision_low, int $ignored_precision_high, int $ptime): int +{ + if ($clk_id < 0 || 3 < $clk_id) { + return 28; + } + if ($clk_id === 0) { + $now = hostFunc__env__emscripten_date_now($runtime); + } else { + $now = hostFunc__env__emscripten_get_now($runtime); + } + $nsec = round($now * 1000 * 1000); + + $mem = $runtime->getExportedMemory('memory'); + \assert($mem !== null); + $mem->storeI32_s32($ptime, $nsec & 0xFFFFFFFF); + $mem->storeI32_s32($ptime + 4, $nsec >> 32); + + return 0; +} + // Type: (i32, i32, i32, i32, i32) -> (i32) function hostFunc__wasi_snapshot_preview1__fd_seek(Runtime $runtime, int $fd, int $offset_low, int $offset_high, int $whence, int $newOffset): int { diff --git a/src/WebAssembly/BinaryFormat/Decoder.php b/src/WebAssembly/BinaryFormat/Decoder.php index 2e59df4..e64fac8 100644 --- a/src/WebAssembly/BinaryFormat/Decoder.php +++ b/src/WebAssembly/BinaryFormat/Decoder.php @@ -78,6 +78,8 @@ final class Decoder $codes = $this->decodeSection(SectionId::Code, $this->decodeCodeSecRest(...)) ?? []; $datas = $this->decodeSection(SectionId::Data, $this->decodeDataSecRest(...)) ?? []; + $this->skipCustomSections(); + if (!$this->stream->eof()) { throw new InvalidBinaryFormatException("eof"); } diff --git a/src/WebAssembly/Execution/MemInst.php b/src/WebAssembly/Execution/MemInst.php index deaa6ba..94d57cf 100644 --- a/src/WebAssembly/Execution/MemInst.php +++ b/src/WebAssembly/Execution/MemInst.php @@ -100,7 +100,6 @@ final class MemInst $originalSize = $this->size(); // @phpstan-ignore-next-line $originalData = $this->ffi->new("uint8_t[$originalSize+8]"); - assert($originalData !== null); FFI::memcpy($originalData, $this->dataU8, $originalSize); $this->initInternalMemory($len); @@ -133,76 +132,43 @@ final class MemInst $this->ffi->cast("uint8_t[$this->dataSize+8]", $this->dataU8 + $offset), ); - // @phpstan-ignore-next-line $this->dataU16_0 = $castInt(16, false, 0); - // @phpstan-ignore-next-line $this->dataU16_1 = $castInt(16, false, 1); - // @phpstan-ignore-next-line $this->dataS16_0 = $castInt(16, true, 0); - // @phpstan-ignore-next-line $this->dataS16_1 = $castInt(16, true, 1); - // @phpstan-ignore-next-line $this->dataU32_0 = $castInt(32, false, 0); - // @phpstan-ignore-next-line $this->dataU32_1 = $castInt(32, false, 1); - // @phpstan-ignore-next-line $this->dataU32_2 = $castInt(32, false, 2); - // @phpstan-ignore-next-line $this->dataU32_3 = $castInt(32, false, 3); - // @phpstan-ignore-next-line $this->dataS32_0 = $castInt(32, true, 0); - // @phpstan-ignore-next-line $this->dataS32_1 = $castInt(32, true, 1); - // @phpstan-ignore-next-line $this->dataS32_2 = $castInt(32, true, 2); - // @phpstan-ignore-next-line $this->dataS32_3 = $castInt(32, true, 3); - // @phpstan-ignore-next-line $this->dataS64_0 = $castInt(64, true, 0); - // @phpstan-ignore-next-line $this->dataS64_1 = $castInt(64, true, 1); - // @phpstan-ignore-next-line $this->dataS64_2 = $castInt(64, true, 2); - // @phpstan-ignore-next-line $this->dataS64_3 = $castInt(64, true, 3); - // @phpstan-ignore-next-line $this->dataS64_4 = $castInt(64, true, 4); - // @phpstan-ignore-next-line $this->dataS64_5 = $castInt(64, true, 5); - // @phpstan-ignore-next-line $this->dataS64_6 = $castInt(64, true, 6); - // @phpstan-ignore-next-line $this->dataS64_7 = $castInt(64, true, 7); - // @phpstan-ignore-next-line $this->dataF32_0 = $castFloat(32, 0); - // @phpstan-ignore-next-line $this->dataF32_1 = $castFloat(32, 1); - // @phpstan-ignore-next-line $this->dataF32_2 = $castFloat(32, 2); - // @phpstan-ignore-next-line $this->dataF32_3 = $castFloat(32, 3); - // @phpstan-ignore-next-line $this->dataF64_0 = $castFloat(64, 0); - // @phpstan-ignore-next-line $this->dataF64_1 = $castFloat(64, 1); - // @phpstan-ignore-next-line $this->dataF64_2 = $castFloat(64, 2); - // @phpstan-ignore-next-line $this->dataF64_3 = $castFloat(64, 3); - // @phpstan-ignore-next-line $this->dataF64_4 = $castFloat(64, 4); - // @phpstan-ignore-next-line $this->dataF64_5 = $castFloat(64, 5); - // @phpstan-ignore-next-line $this->dataF64_6 = $castFloat(64, 6); - // @phpstan-ignore-next-line $this->dataF64_7 = $castFloat(64, 7); - // @phpstan-ignore-next-line FFI::memset($this->dataU8, 0, $this->dataSize); } @@ -258,7 +224,6 @@ final class MemInst if ($this->size() < $ptr + 1) { return null; } - // @phpstan-ignore-next-line $c = $this->dataS8[$ptr]; assert(-0x80 <= $c && $c <= 0x7F, "$c"); return $c; @@ -272,7 +237,6 @@ final class MemInst if ($this->size() < $ptr + 1) { return null; } - // @phpstan-ignore-next-line $c = $this->dataU8[$ptr]; assert(0 <= $c && $c <= 0xFF, "$c"); return $c; @@ -286,7 +250,6 @@ final class MemInst if ($this->size() < $ptr + 2) { return null; } - // @phpstan-ignore-next-line $c = $this->dataS16($ptr)[$ptr >> 1]; assert(-0x8000 <= $c && $c <= 0x7FFF, "$c"); return $c; @@ -300,7 +263,6 @@ final class MemInst if ($this->size() < $ptr + 2) { return null; } - // @phpstan-ignore-next-line $c = $this->dataU16($ptr)[$ptr >> 1]; assert(0 <= $c && $c <= 0xFFFF, "$c"); return $c; @@ -314,7 +276,6 @@ final class MemInst if ($this->size() < $ptr + 4) { return null; } - // @phpstan-ignore-next-line $c = $this->dataS32($ptr)[$ptr >> 2]; assert(-0x80000000 <= $c && $c <= 0x7FFFFFFF, "$c"); return $c; @@ -328,7 +289,6 @@ final class MemInst if ($this->size() < $ptr + 1) { return null; } - // @phpstan-ignore-next-line $c = $this->dataS8[$ptr]; assert(-0x80 <= $c && $c <= 0x7F, "$c"); return $c; @@ -342,7 +302,6 @@ final class MemInst if ($this->size() < $ptr + 1) { return null; } - // @phpstan-ignore-next-line $c = $this->dataU8[$ptr]; assert(0 <= $c && $c <= 0xFF, "$c"); return $c; @@ -356,7 +315,6 @@ final class MemInst if ($this->size() < $ptr + 2) { return null; } - // @phpstan-ignore-next-line $c = $this->dataS16($ptr)[$ptr >> 1]; assert(-0x8000 <= $c && $c <= 0x7FFF, "$c"); return $c; @@ -370,7 +328,6 @@ final class MemInst if ($this->size() < $ptr + 2) { return null; } - // @phpstan-ignore-next-line $c = $this->dataU16($ptr)[$ptr >> 1]; assert(0 <= $c && $c <= 0xFFFF, "$c"); return $c; @@ -384,7 +341,6 @@ final class MemInst if ($this->size() < $ptr + 4) { return null; } - // @phpstan-ignore-next-line $c = $this->dataS32($ptr)[$ptr >> 2]; assert(-0x80000000 <= $c && $c <= 0x7FFFFFFF, "$c"); return $c; @@ -398,7 +354,6 @@ final class MemInst if ($this->size() < $ptr + 4) { return null; } - // @phpstan-ignore-next-line $c = $this->dataU32($ptr)[$ptr >> 2]; assert(0 <= $c && $c <= 0xFFFFFFFF, "$c"); return $c; @@ -412,7 +367,6 @@ final class MemInst if ($this->size() < $ptr + 8) { return null; } - // @phpstan-ignore-next-line $c = $this->dataS64($ptr)[$ptr >> 3]; assert(-0x8000000000000000 <= $c && $c <= 0x7FFFFFFFFFFFFFFF, "$c"); return $c; @@ -426,7 +380,6 @@ final class MemInst if ($this->size() < $ptr + 4) { return null; } - // @phpstan-ignore-next-line return $this->dataF32($ptr)[$ptr >> 2]; } @@ -438,7 +391,6 @@ final class MemInst if ($this->size() < $ptr + 8) { return null; } - // @phpstan-ignore-next-line return $this->dataF64($ptr)[$ptr >> 3]; } @@ -450,7 +402,6 @@ final class MemInst if ($this->size() < $ptr + 1) { return null; } - // @phpstan-ignore-next-line return $this->dataU8[$ptr]; } @@ -462,7 +413,6 @@ final class MemInst if ($this->size() < $ptr + 1) { return false; } - // @phpstan-ignore-next-line $this->dataU8[$ptr] = $c; return true; } @@ -476,7 +426,6 @@ final class MemInst if ($this->size() < $ptr + 1) { return false; } - // @phpstan-ignore-next-line $this->dataS8[$ptr] = $c; return true; } @@ -490,7 +439,6 @@ final class MemInst if ($this->size() < $ptr + 2) { return false; } - // @phpstan-ignore-next-line $this->dataS16($ptr)[$ptr >> 1] = $c; return true; } @@ -504,7 +452,6 @@ final class MemInst if ($this->size() < $ptr + 4) { return false; } - // @phpstan-ignore-next-line $this->dataS32($ptr)[$ptr >> 2] = $c; return true; } @@ -518,7 +465,6 @@ final class MemInst if ($this->size() < $ptr + 1) { return false; } - // @phpstan-ignore-next-line $this->dataS8[$ptr] = $c; return true; } @@ -532,7 +478,6 @@ final class MemInst if ($this->size() < $ptr + 2) { return false; } - // @phpstan-ignore-next-line $this->dataS16($ptr)[$ptr >> 1] = $c; return true; } @@ -546,7 +491,6 @@ final class MemInst if ($this->size() < $ptr + 4) { return false; } - // @phpstan-ignore-next-line $this->dataS32($ptr)[$ptr >> 2] = $c; return true; } @@ -560,7 +504,6 @@ final class MemInst if ($this->size() < $ptr + 8) { return false; } - // @phpstan-ignore-next-line $this->dataS64($ptr)[$ptr >> 3] = $c; return true; } @@ -574,7 +517,6 @@ final class MemInst if ($this->size() < $ptr + 4) { return false; } - // @phpstan-ignore-next-line $this->dataF32($ptr)[$ptr >> 2] = $c; return true; } @@ -588,7 +530,6 @@ final class MemInst if ($this->size() < $ptr + 8) { return false; } - // @phpstan-ignore-next-line $this->dataF64($ptr)[$ptr >> 3] = $c; return true; } diff --git a/src/WebAssembly/Execution/StackOverflowException.php b/src/WebAssembly/Execution/StackOverflowException.php index c5ff3a4..4a18aa7 100644 --- a/src/WebAssembly/Execution/StackOverflowException.php +++ b/src/WebAssembly/Execution/StackOverflowException.php @@ -12,7 +12,7 @@ final class StackOverflowException extends RuntimeException public function __construct( string $message = 'Stack overflow', int $code = 0, - Throwable $previous = null, + ?Throwable $previous = null, ) { parent::__construct($message, $code, $previous); } |
