{"_id":"@alganet/phasm","_rev":"9-3696525f9ea98d5a79a830ae342d08e8","name":"@alganet/phasm","dist-tags":{"latest":"0.6.0"},"versions":{"0.1.0":{"name":"@alganet/phasm","version":"0.1.0","keywords":["php","wasm","webassembly"],"author":{"name":"Alexandre Gomes Gaigalas","email":"alganet@gmail.com"},"license":"ISC","_id":"@alganet/phasm@0.1.0","maintainers":[{"name":"alganet","email":"alganet@gmail.com"}],"homepage":"https://github.com/alganet/phasm#readme","bugs":{"url":"https://github.com/alganet/phasm/issues"},"dist":{"shasum":"95b53cec0f2017f38389389486ec474ea7a5877e","tarball":"https://registry.npmjs.org/@alganet/phasm/-/phasm-0.1.0.tgz","fileCount":6,"integrity":"sha512-JtvBihnsPGYVYho74dvssbmpQS01qu6YHooDVcvcIj0pZdVYFZgsMQyDibYg73YAz3Uml3f+Dsy4tQ9pPm+xrA==","signatures":[{"sig":"MEUCIQCylTn6Wd+16nasAKHbTdrC5QuJdx6U9p7KUN6epjD3CQIgVQ0ewL57L1ck9O5Zb2e7K85ad83kngZHLEWItFZLQYs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":29651305},"main":"dist/php.js","types":"dist/php.d.ts","module":"dist/php.js","exports":{".":{"import":"./dist/php.js","default":"./dist/php.js"},"./wasm":"./dist/php.wasm"},"gitHead":"4cc1b01ce302294fc9ffa0601e2db42501e3e082","_npmUser":{"name":"alganet","email":"alganet@gmail.com"},"repository":{"url":"git+https://github.com/alganet/phasm.git","type":"git"},"_npmVersion":"10.9.4","description":"PHP 8.5 compiled to WebAssembly","directories":{},"_nodeVersion":"22.21.1","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/phasm_0.1.0_1770689329802_0.6072734041582659","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@alganet/phasm","version":"0.1.1","keywords":["php","wasm","webassembly"],"author":{"name":"Alexandre Gomes Gaigalas","email":"alganet@gmail.com"},"license":"ISC","_id":"@alganet/phasm@0.1.1","maintainers":[{"name":"alganet","email":"alganet@gmail.com"}],"homepage":"https://github.com/alganet/phasm#readme","bugs":{"url":"https://github.com/alganet/phasm/issues"},"dist":{"shasum":"0421b0ce16a4a68690014b2dd1922d6351fcc893","tarball":"https://registry.npmjs.org/@alganet/phasm/-/phasm-0.1.1.tgz","fileCount":6,"integrity":"sha512-+Qw7rDvu1n3rAy3t8ZH43wenqTxj9cC0CinQVQKvWcX0svnkTnQPxbS48W/OJe58f8x6Q5grgNEeK5EjSxsUCA==","signatures":[{"sig":"MEUCIQCMgSg16REhzsuU6E1VgqgXNRS077y+r00+0gxO1V0/DAIgexWDJZ8FSo0vQ800cR6a6oKxZ24QUBtaQy3YoExVTzc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":30940665},"main":"dist/php.js","types":"dist/php.d.ts","module":"dist/php.js","exports":{".":{"import":"./dist/php.js","default":"./dist/php.js"},"./wasm":"./dist/php.wasm"},"gitHead":"21f5e4babf3829bd5c1b711ff51801c4df2e9728","_npmUser":{"name":"alganet","email":"alganet@gmail.com"},"repository":{"url":"git+https://github.com/alganet/phasm.git","type":"git"},"_npmVersion":"10.9.4","description":"PHP 8.5 compiled to WebAssembly","directories":{},"_nodeVersion":"22.21.1","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/phasm_0.1.1_1770761852077_0.059338532412688716","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@alganet/phasm","version":"0.1.2","keywords":["php","wasm","webassembly"],"author":{"name":"Alexandre Gomes Gaigalas","email":"alganet@gmail.com"},"license":"ISC","_id":"@alganet/phasm@0.1.2","maintainers":[{"name":"alganet","email":"alganet@gmail.com"}],"homepage":"https://github.com/alganet/phasm#readme","bugs":{"url":"https://github.com/alganet/phasm/issues"},"dist":{"shasum":"74917cdce51023969cdd934bb60df9a2834a1027","tarball":"https://registry.npmjs.org/@alganet/phasm/-/phasm-0.1.2.tgz","fileCount":5,"integrity":"sha512-MPsqWOumwLApG92i3MNRT3X3b7AStec42+zohKFNzMKNQiRLz1nkEW9AJEoOkOpPL7BedhNi0/ob1zd0g+t2zw==","signatures":[{"sig":"MEQCIDkh12HXqblo8Qxe+65V61w0aQov+ABcL38Qhgb7966IAiAEbI6bz5CmXVgx2TeUBzJxK4FdNG83oNErDe/6Sztl3A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":35249382},"main":"dist/php.js","types":"dist/php.d.ts","module":"dist/php.js","exports":{".":{"import":"./dist/php.js","default":"./dist/php.js"},"./wasm":"./dist/php.wasm"},"gitHead":"55514d13a9b6c79dd1b4773ffa21502f475e0f4f","_npmUser":{"name":"alganet","email":"alganet@gmail.com"},"repository":{"url":"git+https://github.com/alganet/phasm.git","type":"git"},"_npmVersion":"11.9.0","description":"PHP 8.5 compiled to WebAssembly","directories":{},"_nodeVersion":"24.14.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/phasm_0.1.2_1772815426485_0.39765810921965006","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"@alganet/phasm","version":"0.1.3","keywords":["php","wasm","webassembly"],"author":{"name":"Alexandre Gomes Gaigalas","email":"alganet@gmail.com"},"license":"ISC","_id":"@alganet/phasm@0.1.3","maintainers":[{"name":"alganet","email":"alganet@gmail.com"}],"homepage":"https://github.com/alganet/phasm#readme","bugs":{"url":"https://github.com/alganet/phasm/issues"},"dist":{"shasum":"2a45972a7a4cb9e6d376fb56b863d8e0905eb09f","tarball":"https://registry.npmjs.org/@alganet/phasm/-/phasm-0.1.3.tgz","fileCount":6,"integrity":"sha512-eeDpJ6Y6TvkXRs9yUtSpNLvBy+GxvbY71sHO4mGIWF9cpGY1sBxE5SyUw2a1fr5vjML0IvZlqF4/PS5rm6jDrQ==","signatures":[{"sig":"MEQCIA4x1dBXdh7Vw5Zu9Xef5zyIOH1rzNtDKdn20BXrh4IlAiAzRQV62ihoWirSa8PWmU3uDvW5WDKoPD+ZrAYWAD0KNg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@alganet%2fphasm@0.1.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":36198814},"main":"dist/php.js","types":"dist/php.d.ts","module":"dist/php.js","exports":{".":{"types":"./dist/php.d.ts","import":"./dist/php.js","default":"./dist/php.js"},"./wasm":"./dist/php.wasm","./package.json":"./package.json"},"gitHead":"dee1860c38b325462207130b8997aa8ed53602a3","scripts":{"test":"node --test test/*.test.mjs"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:53fef854-22ab-41ce-b956-5e74cabad874"}},"repository":{"url":"git+https://github.com/alganet/phasm.git","type":"git"},"_npmVersion":"12.0.2","description":"PHP 8.5 compiled to WebAssembly","directories":{},"_nodeVersion":"24.19.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/phasm_0.1.3_1786653642034_0.46429485203453935","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@alganet/phasm","version":"0.2.0","keywords":["php","wasm","webassembly"],"author":{"name":"Alexandre Gomes Gaigalas","email":"alganet@gmail.com"},"license":"ISC","_id":"@alganet/phasm@0.2.0","maintainers":[{"name":"alganet","email":"alganet@gmail.com"}],"homepage":"https://github.com/alganet/phasm#readme","bugs":{"url":"https://github.com/alganet/phasm/issues"},"dist":{"shasum":"9fa47d8a2cc8fd44c9a404804052a126f89200d1","tarball":"https://registry.npmjs.org/@alganet/phasm/-/phasm-0.2.0.tgz","fileCount":8,"integrity":"sha512-QEqnL4km4CVmcstVZV9/l3c+AyYtWD3QZQXiLkymmzi6LouYvdfjXm7wMf5uAEQtP1quzT/gnIix+J0z2UGRgw==","signatures":[{"sig":"MEQCIB+v0GJumW3T4oJ5tse6cgYQ8lGmi6+UjVaQXPHTiVsjAiAdQeGvV75E+Mwa0eTNErJ6HyCluGIOq3fOgPk1QuBPlA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@alganet%2fphasm@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":13032001},"main":"dist/php.js","types":"dist/php.d.ts","module":"dist/php.js","exports":{".":{"types":"./dist/php.d.ts","import":"./dist/php.js","default":"./dist/php.js"},"./wasm":"./dist/php.wasm","./mount":{"types":"./dist/mount.d.ts","import":"./dist/mount.mjs","default":"./dist/mount.mjs"},"./package.json":"./package.json"},"gitHead":"7ecbe5594a27c00a5fa967bac20becbcf95fc56f","scripts":{"test":"node --test test/*.test.mjs"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:53fef854-22ab-41ce-b956-5e74cabad874"}},"repository":{"url":"git+https://github.com/alganet/phasm.git","type":"git"},"_npmVersion":"12.0.2","description":"PHP 8.5 compiled to WebAssembly","directories":{},"_nodeVersion":"24.19.0","_hasShrinkwrap":false,"devDependencies":{"wasi-sh":"0.2.1","@zenfs/core":"2.6.3","@zenfs/emscripten":"1.0.7"},"peerDependencies":{"@zenfs/core":">=2.4.2","@zenfs/emscripten":">=1.0.7"},"peerDependenciesMeta":{"@zenfs/core":{"optional":true},"@zenfs/emscripten":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/phasm_0.2.0_1788290651328_0.6477638116766644","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@alganet/phasm","version":"0.3.0","keywords":["php","wasm","webassembly"],"author":{"name":"Alexandre Gomes Gaigalas","email":"alganet@gmail.com"},"license":"ISC","_id":"@alganet/phasm@0.3.0","maintainers":[{"name":"alganet","email":"alganet@gmail.com"}],"homepage":"https://github.com/alganet/phasm#readme","bugs":{"url":"https://github.com/alganet/phasm/issues"},"dist":{"shasum":"b4253010dbffbf6700fa6b150534cc889b34d238","tarball":"https://registry.npmjs.org/@alganet/phasm/-/phasm-0.3.0.tgz","fileCount":8,"integrity":"sha512-SGSj2+/G95L13fByU/iCGXCnBXSRRZFkzxke/8cYBuTdER5R9X/xVLDNVYMRNePbINHZi7zaMAHICF9Il56z9A==","signatures":[{"sig":"MEQCIFevQM5hp4rBx9NipPVGJZI3CArJln3ErX5bQW1hV1soAiBkIzjjrw//+1ZVVtt2iokYkl/jKJkFT8KtSwr6i43rzA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@alganet%2fphasm@0.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":13032001},"main":"dist/php.js","types":"dist/php.d.ts","module":"dist/php.js","exports":{".":{"types":"./dist/php.d.ts","import":"./dist/php.js","default":"./dist/php.js"},"./wasm":"./dist/php.wasm","./mount":{"types":"./dist/mount.d.ts","import":"./dist/mount.mjs","default":"./dist/mount.mjs"},"./package.json":"./package.json"},"gitHead":"14324b7f78a83464b62516b9cab9334cec9df3e5","scripts":{"test":"node --test test/*.test.mjs"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:53fef854-22ab-41ce-b956-5e74cabad874"}},"repository":{"url":"git+https://github.com/alganet/phasm.git","type":"git"},"_npmVersion":"12.0.2","description":"PHP 8.5 compiled to WebAssembly","directories":{},"_nodeVersion":"24.19.0","_hasShrinkwrap":false,"devDependencies":{"wasi-sh":"0.5.0","@zenfs/core":"2.6.3","@zenfs/emscripten":"1.0.7"},"peerDependencies":{"@zenfs/core":">=2.4.2","@zenfs/emscripten":">=1.0.7"},"peerDependenciesMeta":{"@zenfs/core":{"optional":true},"@zenfs/emscripten":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/phasm_0.3.0_1788299117319_0.7107869251196974","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@alganet/phasm","version":"0.4.0","keywords":["php","wasm","webassembly"],"author":{"name":"Alexandre Gomes Gaigalas","email":"alganet@gmail.com"},"license":"ISC","_id":"@alganet/phasm@0.4.0","maintainers":[{"name":"alganet","email":"alganet@gmail.com"}],"homepage":"https://github.com/alganet/phasm#readme","bugs":{"url":"https://github.com/alganet/phasm/issues"},"dist":{"shasum":"0413388beb65bbd487301c2c6a75e43a05998ca7","tarball":"https://registry.npmjs.org/@alganet/phasm/-/phasm-0.4.0.tgz","fileCount":8,"integrity":"sha512-P9LZzVh9cDtfVWn9nH2IChmPAGkLP0SIveQ3RBFmsEm9MZirLMKWlmOcK6bpEAbKYp8UOEkZj8tQTkn7qs0YwQ==","signatures":[{"sig":"MEUCICJyXSBXUWmb3NDBJbc4lY4ckd9S+qR2BlFepxUd07aXAiEA3CtYpvaT2XFHSWcX8jZEkwC3TJcHuiZvtWf8LK2sUkc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@alganet%2fphasm@0.4.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":13036767},"main":"dist/php.js","types":"dist/php.d.ts","module":"dist/php.js","exports":{".":{"types":"./dist/php.d.ts","import":"./dist/php.js","default":"./dist/php.js"},"./wasm":"./dist/php.wasm","./mount":{"types":"./dist/mount.d.ts","import":"./dist/mount.mjs","default":"./dist/mount.mjs"},"./package.json":"./package.json"},"gitHead":"2b0cab311f794762066973f9dd735488f31fe65e","scripts":{"test":"node --test test/*.test.mjs"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:53fef854-22ab-41ce-b956-5e74cabad874"}},"repository":{"url":"git+https://github.com/alganet/phasm.git","type":"git"},"_npmVersion":"12.0.2","description":"PHP 8.5 compiled to WebAssembly","directories":{},"_nodeVersion":"24.20.0","_hasShrinkwrap":false,"devDependencies":{"wasi-sh":"0.6.0","@zenfs/core":"2.6.3","@zenfs/emscripten":"1.0.7"},"peerDependencies":{"@zenfs/core":">=2.4.2","@zenfs/emscripten":">=1.0.7"},"peerDependenciesMeta":{"@zenfs/core":{"optional":true},"@zenfs/emscripten":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/phasm_0.4.0_1788520763634_0.8037752948825707","host":"s3://npm-registry-packages-npm-production"}},"0.5.0":{"name":"@alganet/phasm","version":"0.5.0","keywords":["php","wasm","webassembly"],"author":{"name":"Alexandre Gomes Gaigalas","email":"alganet@gmail.com"},"license":"ISC","_id":"@alganet/phasm@0.5.0","maintainers":[{"name":"alganet","email":"alganet@gmail.com"}],"homepage":"https://github.com/alganet/phasm#readme","bugs":{"url":"https://github.com/alganet/phasm/issues"},"dist":{"shasum":"189678045fe76990474858a1bdb3db63c786805b","tarball":"https://registry.npmjs.org/@alganet/phasm/-/phasm-0.5.0.tgz","fileCount":8,"integrity":"sha512-oEB4o7oHLkvGXzIVCu34bmG6K2GytqJKIbpz0fdIaNQ5Txmr/brNXA6bt5gQRo0ZZoIpMDfKhIJhyBIqMgAy2g==","signatures":[{"sig":"MEUCIQDj7V2SysfdjvasSAZtVmTIZxFju8vSi3rXxIcdSVFCwQIgPCQvJcAEzkIr6gLDG1ETTj0eMz8qGq54x31unHiYOe8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@alganet%2fphasm@0.5.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":13040716},"main":"dist/php.js","types":"dist/php.d.ts","module":"dist/php.js","exports":{".":{"types":"./dist/php.d.ts","import":"./dist/php.js","default":"./dist/php.js"},"./wasm":"./dist/php.wasm","./mount":{"types":"./dist/mount.d.ts","import":"./dist/mount.mjs","default":"./dist/mount.mjs"},"./package.json":"./package.json"},"gitHead":"1d833bfef36723bcb6adc7a611e06ea33add1f3d","scripts":{"test":"node --test test/*.test.mjs"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:53fef854-22ab-41ce-b956-5e74cabad874"}},"repository":{"url":"git+https://github.com/alganet/phasm.git","type":"git"},"_npmVersion":"12.0.2","description":"PHP 8.5 compiled to WebAssembly","directories":{},"_nodeVersion":"24.20.0","_hasShrinkwrap":false,"devDependencies":{"wasi-sh":"0.6.0","@zenfs/core":"2.6.3","@zenfs/emscripten":"1.0.7"},"peerDependencies":{"@zenfs/core":">=2.4.2","@zenfs/emscripten":">=1.0.7"},"peerDependenciesMeta":{"@zenfs/core":{"optional":true},"@zenfs/emscripten":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/phasm_0.5.0_1788524817072_0.8164855177126427","host":"s3://npm-registry-packages-npm-production"}},"0.6.0":{"name":"@alganet/phasm","version":"0.6.0","description":"PHP 8.5 compiled to WebAssembly","main":"dist/php.js","module":"dist/php.js","types":"dist/php.d.ts","exports":{".":{"types":"./dist/php.d.ts","import":"./dist/php.js","default":"./dist/php.js"},"./mount":{"types":"./dist/mount.d.ts","import":"./dist/mount.mjs","default":"./dist/mount.mjs"},"./wasm":"./dist/php.wasm","./package.json":"./package.json"},"scripts":{"test":"node --test test/*.test.mjs"},"repository":{"type":"git","url":"git+https://github.com/alganet/phasm.git"},"keywords":["php","wasm","webassembly"],"author":{"name":"Alexandre Gomes Gaigalas","email":"alganet@gmail.com"},"license":"ISC","peerDependencies":{"@zenfs/core":">=2.4.2","@zenfs/emscripten":">=1.0.7"},"peerDependenciesMeta":{"@zenfs/core":{"optional":true},"@zenfs/emscripten":{"optional":true}},"devDependencies":{"@zenfs/core":"2.6.3","@zenfs/emscripten":"1.0.7","wasi-sh":"0.10.0"},"gitHead":"3afac25539ce25f0179aac0b1c36f8609f935add","_id":"@alganet/phasm@0.6.0","bugs":{"url":"https://github.com/alganet/phasm/issues"},"homepage":"https://github.com/alganet/phasm#readme","_nodeVersion":"24.20.0","_npmVersion":"12.0.2","dist":{"integrity":"sha512-YKHM9HDC1i5EOBUHF8fkdh4MJYUJbqzEpH2fH8sp2Mq5jpQiA0Kui6ef8CHoigiQMskKaDSbu7XDV7ko8l6gZQ==","shasum":"42c881e9e8e41c51219c7c95680cf26e2c96a837","tarball":"https://registry.npmjs.org/@alganet/phasm/-/phasm-0.6.0.tgz","fileCount":8,"unpackedSize":15251566,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@alganet%2fphasm@0.6.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQC73DC6KQM4pA0IKGFYqm84yaO+xZQ6zKWtSaSDjfllgAIhAMiYwd8rsx6oxxbvPfo/iMizIDHDOx/M07yFgDhfENOw"}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:53fef854-22ab-41ce-b956-5e74cabad874"}},"directories":{},"maintainers":[{"name":"alganet","email":"alganet@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/phasm_0.6.0_1788529673231_0.4607408590466282"},"_hasShrinkwrap":false}},"time":{"created":"2026-02-10T02:08:49.713Z","modified":"2026-09-04T13:47:54.004Z","0.1.0":"2026-02-10T02:08:50.320Z","0.1.1":"2026-02-10T22:17:32.536Z","0.1.2":"2026-03-06T16:43:46.942Z","0.1.3":"2026-08-13T20:40:42.484Z","0.2.0":"2026-09-01T19:24:11.610Z","0.3.0":"2026-09-01T21:45:17.550Z","0.4.0":"2026-09-04T11:19:23.873Z","0.5.0":"2026-09-04T12:26:57.346Z","0.6.0":"2026-09-04T13:47:53.489Z"},"bugs":{"url":"https://github.com/alganet/phasm/issues"},"author":{"name":"Alexandre Gomes Gaigalas","email":"alganet@gmail.com"},"license":"ISC","homepage":"https://github.com/alganet/phasm#readme","keywords":["php","wasm","webassembly"],"repository":{"type":"git","url":"git+https://github.com/alganet/phasm.git"},"description":"PHP 8.5 compiled to WebAssembly","maintainers":[{"name":"alganet","email":"alganet@gmail.com"}],"readme":"<!--\nSPDX-FileCopyrightText: 2026 Alexandre Gomes Gaigalas <alganet@gmail.com>\n\nSPDX-License-Identifier: ISC\n-->\n\n# phasm\n\nPHP 8.5 compiled to WebAssembly. Run PHP in the browser or in Node.js.\n\n    npm install @alganet/phasm\n\n## Included Extensions\n\ncalendar, ctype, dom, fileinfo, filter, iconv, libxml, mbstring, opcache,\nopenssl, pcntl, pdo, pdo_sqlite, phar, session, simplexml, sqlite3, tokenizer,\nxml, xmlwriter, zip, zlib.\n\nPlus PHP's always-on core: Core, date, hash, json, lexbor, pcre, random,\nReflection, SPL, standard, uri.\n\n`get_loaded_extensions()` is the authority; `npm test` asserts this list matches\nwhat the binary actually links, so it cannot drift again.\n\n**`openssl` is the crypto, not the network.** `openssl_encrypt`, the digest and\nHMAC surface, RSA and EC keys, signing, X.509, PKCS#7 and PKCS#12 all work, and\nso does `openssl_random_pseudo_bytes` — seeded from `/dev/urandom`, which is\n`crypto.getRandomValues()` in a browser and `randomBytes()` under Node. The\n`ssl://` and `tls://` transports register and their stream contexts parse, but\nthis target has no sockets for them to sit on, so nothing dials out. Use `fetch`\nfrom the host for that.\n\nTrimmed to what a browser build can reach: no legacy provider (so no RC4), no\nengines or loadable modules, no QUIC, no kernel TLS, no compression, no argon2.\n\n## Node.js\n\n```js\nimport Phasm from \"@alganet/phasm\";\n\nconst php = await Phasm();\n\nconst { stdout, stderr, exitCode } = php.run({\n  script: `<?php echo \"Hello from PHP!\\\\n\";`,\n});\n```\n\n## Browser\n\n```html\n<script src=\"https://unpkg.com/@alganet/phasm/dist/php.js\"></script>\n<pre id=\"output\"></pre>\n<script>\n  Phasm().then((php) => {\n    const { stdout } = php.run({ code: 'echo \"Hello from PHP!\";' });\n    document.getElementById(\"output\").textContent = stdout;\n  });\n</script>\n```\n\n## TypeScript\n\nTypes ship with the package — `Phasm`, `PhasmOptions`, `PhasmModule`, `PhasmFS`,\n`PhasmRunOptions`, `PhasmRunResult`, `PhasmRequest` and `PhasmResponse` are all\ndeclared, no `@types` package needed. The subpaths carry their own: `Store` and\n`MountOptions` on `@alganet/phasm/mount`.\n\n```ts\nimport Phasm, { type PhasmModule, type PhasmRunResult } from \"@alganet/phasm\";\n\nconst php: PhasmModule = await Phasm();\nconst result: PhasmRunResult = php.run({ code: \"echo 1;\" });\n```\n\n## Running PHP\n\n`run()` takes one call's worth of everything and gives back what it produced:\n\n```js\nconst { stdout, stderr, exitCode } = php.run({\n  args: [\"app.php\", \"--verbose\"],\n  files: { \"/project/app.php\": '<?php echo getenv(\"APP_ENV\"), $argv[1];' },\n  stdin: \"piped in\",\n  cwd: \"/project\",\n  env: { APP_ENV: \"dev\" },\n});\n```\n\n| Option       | Description                                                          |\n|--------------|----------------------------------------------------------------------|\n| `args`       | argv after argv[0]. Wins over `code` and `script`.                   |\n| `code`       | A snippet, as `-r` — no `<?php` tag.                                 |\n| `script`     | PHP source, mounted at `/main.php` and run.                          |\n| `files`      | Written first; missing directories are created.                      |\n| `stdin`      | Text, bytes, or a function pulled from as PHP reads.                 |\n| `cwd`, `env` | This call only.                                                      |\n| `onOutput`   | `(bytes, channel)` as output happens, for streaming.                 |\n| `collect`    | `false` to skip buffering when `onOutput` already has the bytes.     |\n\n`onOutput` gets each chunk exactly once, and throwing from it is how a sink\nrefuses: the write fails for PHP, which normally ends the call, and the error\ncomes back out of `run()` rather than as a bare non-zero status. That is the\npath a shell builtin is on — writing to a device that refuses it — so the\nrefusal reaches the script instead of looking like output nobody read.\n\nEverything there is per call: `cwd` and `env` are gone by the next one, output\nbelongs to this call alone, stdin is refilled. The filesystem, the instance and\nits ini survive. The options and the `{stdout, stderr, exitCode}` result are\n[wasi-sh](https://github.com/alganet/wasi-sh)'s, so a shell run and a PHP run\ncompose without an adapter between them.\n\n**One instance, many runs.** phasm builds its own SAPI (`sapi/phasm`) rather\nthan the stock CLI, so each call is a full request without ever exiting the\nprocess: the exit status is per call, errors go to stderr, and a fatal error or\n`exit()` leaves the module usable. Booting PHP costs ~70 ms and a warm call\n~1 ms, so reuse the instance.\n\n**Runaway recursion is a PHP error, not a crash.** Recursion inside the engine\nand its extensions — `json_encode()`, `serialize()`, `var_dump()`, the compiler\n— is C recursion, and deep enough it reaches a limit belonging to the JS engine\nrather than to PHP. phasm builds PHP with its own `zend.max_allowed_stack_size`\nguard, `512K` by default, so those stop with the error each of them already\nraises for the case — `json_encode()` returns `false` with `JSON_ERROR_DEPTH`,\n`serialize()` throws — instead of the call ending from outside PHP. That budget\nis a few hundred levels of nesting, far past what real data carries. Raise it,\nor pass `-1` to switch the guard off, through\n`phasmStartup(\"zend.max_allowed_stack_size=…\")`.\n\nOrdinary PHP recursion is not affected: a function calling itself runs in the\nVM, not on the C stack, and goes hundreds of thousands deep.\n\nThe guard covers what PHP itself guards, which is not everything — `unserialize()`\nwith its `max_depth` disabled still gets there, and so does recursion that runs\nthe module out of memory. Exhausting the stack is the one failure that is not an\nexit status: there is no PHP error left to raise, so the call **throws** rather\nthan returning. Catch it if the call site cares — the instance itself survives,\nbecause the abandoned request is finished before the error reaches you.\n\n**A script that will not stop can be stopped from outside.** Pass an\n`interrupted` callback and PHP polls it while the script runs; answering `true`\nends the call with a fatal and an exit status of **130**, the status a shell\nreports for a ^C:\n\n```js\nconst started = Date.now();\nconst r = php.run({\n  code: \"while (true) {}\",\n  interrupted: () => Date.now() - started > 5000,\n});\nr.exitCode; // 130 — and the instance, its filesystem and its opcache are intact\n```\n\nNothing else can be running to interrupt a script — one wasm guest owns its\nthread for as long as it runs — so PHP asks for itself, at the safe points its\nVM already checks, about one opcode in a few hundred. Keep the callback cheap.\nWhat it does not reach is a loop with no PHP opcode in it: catastrophic\nbacktracking inside `preg_match`, a huge `str_repeat`, `usleep()`. Those stop\nwhen the function returns. Passing nothing installs no polling at all, and a\ncall with no `interrupted` cannot be stopped — the only honest default for work\nthat never opted in. `phasmHandleRequest()` takes the same option, and a\nrequest stopped that way still answers, with a 500.\n\nUnderneath, `phasmRun(args, opts)` returns the status and leaves output wherever\nthe module's stdio points — reach for it when you are routing stdio yourself,\nand for anything else `phasmCapture(fn)` collects around a call `run()` does not\ncover. `callMain()` is still there and still one-shot: it re-enters the CLI's\n`main()`, which ends in `exit()`. Pick one entry point per module; they cannot\nbe mixed, and each refuses the call rather than leaving you with a dead\ninstance.\n\n## Configuration\n\n`Phasm()` is a factory function that accepts standard [Emscripten Module](https://emscripten.org/docs/api_reference/module.html)\noptions and returns a promise that resolves to the initialized module:\n\n| Option           | Description                                             |\n|------------------|---------------------------------------------------------|\n| `arguments`      | Default CLI arguments for a bare `callMain()`.          |\n| `print(text)`    | Callback for stdout produced outside `run()`.           |\n| `printErr(text)` | Callback for stderr produced outside `run()`.           |\n| `stdin()`        | Callback to provide stdin input. Return `null` for EOF. |\n\nThe module owns its standard streams, which is what lets `run()` return one\ncall's output rather than a global stream: `print`, `printErr` and `stdin` are\nconsulted whenever no `run()` is in flight, so they keep behaving as they always\ndid. Installing your own `FS.init()` sinks still works and still wins — `run()`\nthen says it cannot capture, rather than reporting that PHP printed nothing.\n\n## Caching compiled scripts\n\nopcache is built in and does nothing until you name a directory for it to cache\ninto. Two settings, both required, and the directory has to exist before PHP\nstarts:\n\n```js\nconst php = await Phasm();\nphp.FS.mkdir(\"/cache\");\nphp.phasmStartup(\"opcache.file_cache=/cache\\nopcache.file_cache_only=1\");\n```\n\n`file_cache_only` is not optional here. opcache normally caches into shared\nmemory and treats the file cache as a second tier; wasm has no shared memory to\noffer it, so without this the accelerator finds no backend and switches itself\noff. A file cache is the only mode this build has.\n\nWhat it buys, over 80 files of ~500 KiB: **first run 31 ms → 10 ms, and every\nrun after ~13 ms → ~5 ms.** Compiled scripts are ordinary files, so a cache\ndirectory in a [shared or persistent store](#sharing-a-filesystem) survives the\ninstance that filled it — that is what makes the first number a cold page load\nrather than a warm one. Budget for the size: the cache runs several times larger\nthan the source it was compiled from (3.3 MiB for that 510 KiB).\n\nEntries are keyed by a build id, so a cache is only ever read back by the exact\n`php.wasm` that wrote it; a cache built against an older release is ignored, not\nmis-read. Sources are validated by timestamp, so **the store has to keep real\nmtimes** — against one that reports `0` for everything, nothing is ever cached\nand nothing says so. A file is cacheable from the second after it was written,\nwhich is what keeps an edit from being shadowed by the entry compiled from the\nversion before it; set `opcache.validate_timestamps=0` if a project is genuinely\nread-only and you want that check gone.\n\n## As a shell command\n\n`run()` is what a shell needs, and it is deliberately not PHP's own vocabulary —\nits options and its result are [wasi-sh](https://github.com/alganet/wasi-sh)'s,\nwhich is why the two compose with almost nothing between them:\n\n```js\nconst { stdout, stderr, exitCode } = php.run({\n  args: [\"-r\", 'echo getenv(\"HOME\");'],\n  cwd: \"/site\",\n  env: { HOME: \"/site\" },\n  collect: false,\n  onOutput: (bytes, channel) => channel === \"stdout\" ? out(bytes) : err(bytes),\n});\n```\n\nA host builtin over that is about thirty lines, and it comes with pipes,\nredirects, `$(…)` and `$?` already working, because by dispatch time the shell\nhas installed the redirections. What cannot work is anything needing a\n*process* — `php &`, `(php x)`, `exec php`, `find -exec php` — because a builtin\nis not one. Both guests must share one filesystem: paths are passed through as\ntyped and nothing is copied. The [shared filesystem](#sharing-a-filesystem)\nis one more call.\n\n**^C works, and this is the option that makes it work.** `interrupted` is a\nclosure the embedder passes; PHP samples it at the VM safe points it already\nruns, so a runaway `php -r 'while (true);'` comes back in milliseconds with\n`130` in `$?` and the instance, its filesystem and its warm opcache intact.\nWithout it the only way out of that command is `terminate()`, which takes all\nthree. `test/interrupt.test.mjs` proves it over real shared memory, which is the\nonly place it can be proved.\n## Serving HTTP\n\n`phasmHandleRequest()` runs a real PHP request rather than a command, so\n`header()`, status codes and the superglobals work as they do under any other\nweb SAPI — because PHP's own request machinery produces them, rather than them\nbeing filled in afterwards:\n\n```js\nconst res = php.phasmHandleRequest({\n  method: \"POST\",\n  url: \"/blog/?page=2\",\n  headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n  body: new TextEncoder().encode(\"title=hello\"),\n  docroot: \"/site\",\n});\n// { status, headers, body } — body is bytes, so images survive\n```\n\nThe path resolves under `docroot`, a directory resolves to its `index.php`, and\na missing one is a 404. A status of **0** means the path is not a PHP script:\nthat is a decline rather than an error, and the caller should serve the file\nitself — PHP has no business deciding that a `.css` file is `text/css`.\n\nA path that continues past a script is split the way CGI splits it, so\n`/index.php/users/1` runs `index.php` with `PATH_INFO=/users/1` — the\nno-rewrite front controller, which is the one routing shape a project can rely\non with nothing configured anywhere. `SCRIPT_NAME` is the script, `PHP_SELF`\ncarries the path info too, and `PATH_TRANSLATED` is the path info resolved\nagainst the docroot. The deepest script that exists wins, and a prefix that is\na file but not a script is a 404 rather than a decline.\n\nThere is still no front-controller *rewrite*: `/users/1`, with no script in it\nanywhere, is a 404 and not `/index.php`. That is the caller's decision to make,\nthe same way declining a `.css` file is — a framework that wants every request\nto reach one script asks for it directly:\n\n```js\nlet res = php.phasmHandleRequest({ url, docroot: \"/site\" });\nif (res.status === 404) {\n  res = php.phasmHandleRequest({ url: `/index.php?${query}`, docroot: \"/site\" });\n}\n```\n\nThe shape is the web platform's on purpose, so a service worker can pass a\n`Request` almost straight in and build a `Response` almost straight out —\n`headers` comes back as `[name, value]` pairs, which `new Headers()` accepts and\nwhich keeps repeated `Set-Cookie` headers intact. Requests and `phasmRun()`\ncommands share one instance and one filesystem.\n\nOne inherited default worth knowing: phasm takes the CLI's `output_buffering=0`,\nso the headers are committed as soon as a script echoes anything, and a\n`register_shutdown_function()` that calls `header()` after that is too late.\nPass `phasmStartup(\"output_buffering=4096\")` before the first call for the\nbehaviour php-fpm gives you.\n\n## Virtual Filesystem\n\nPhasm uses Emscripten's virtual filesystem. `run({ files })` writes into it, and\n`FS` is there for everything else — it outlives the call, so a script can leave\nsomething behind for the next one:\n\n```js\nphp.run({ files: { \"/data.json\": JSON.stringify({ key: \"value\" }) } });\nphp.run({ code: 'file_put_contents(\"/out.txt\", file_get_contents(\"/data.json\"));' });\n\nphp.FS.readFile(\"/out.txt\", { encoding: \"utf8\" });\n```\n\nSee the [Emscripten File System API](https://emscripten.org/docs/api_reference/Filesystem-API.html) for the full reference.\n\n## Sharing a filesystem\n\nThat filesystem is phasm's own, which stops being enough the moment something\nelse — a shell, an editor, a service worker — has to see the same project.\n`mountStore()` hands ownership over: the store stays outside and JS-owned, and\nPHP reads and writes through it.\n\n```js\nimport Phasm from \"@alganet/phasm\";\nimport { mountStore } from \"@alganet/phasm/mount\";\nimport { memoryFs } from \"wasi-sh/fs\";\n\nconst store = memoryFs({ \"/app/index.php\": '<?php echo \"hi\";' });\nconst php = await Phasm();\nawait mountStore(php, store, { path: \"/app\" });\n\nphp.run({ args: [\"/app/index.php\"] }).stdout; // 'hi'\n```\n\nA store is any object carrying the twelve synchronous, path-addressed methods of\nZenFS's `FileSystem` — which is also\n[wasi-sh](https://github.com/alganet/wasi-sh)'s `fs` contract, so a shell's\nstore, a `@zenfs/core` filesystem and a persistent OPFS-backed one are all the\nsame argument here. Nothing is copied in at mount time or flushed out at the\nend: a file the shell just wrote is the file PHP opens, an edit made outside is\nthe code the next request runs, and a database PHP writes is a file the page\nstill has after a reload.\n\n`path` is where the store appears in PHP's filesystem; `root` is the directory\n*of the store* that lands there, and it defaults to `path`. That default is the\none to keep — it makes the mount an identity mapping, so `/app` in the shell is\n`/app` in PHP, which is what a shell typing `php app/index.php` depends on.\nMounting at `/` is not possible: Emscripten's root is already in memory and\n`/dev`, `/tmp` and `/proc` have to stay there. Mount the directories the project\nlives in, one call each.\n\n`@zenfs/core` and `@zenfs/emscripten` are optional peer dependencies — the\nEmscripten-side translation is theirs, and embedding PHP in a page without\nmounting anything installs neither:\n\n```sh\nnpm install @zenfs/core @zenfs/emscripten\n```\n\n## Live Demo\n\n[alganet.github.io/phasm](https://alganet.github.io/phasm/) — one file, one Run\nbutton. The smallest thing that shows PHP running in a page: no build step in\nsight, `php.wasm` fetched and `run()` called.\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for build instructions and development\nguidelines.\n\n## Acknowledgements\n\n`mountStore()` is built on **ZenFS** — [`@zenfs/core`](https://github.com/zen-fs/core)\nand [`@zenfs/emscripten`](https://github.com/zen-fs/emscripten), LGPL-3.0-or-later\nwith a web-application exception, used unmodified.\n\nThe binary statically links [**OpenSSL**](https://github.com/openssl/openssl)\n(Apache-2.0, unmodified, pinned to a version and a SHA-256 in\n[`scripts/env.sh`](scripts/env.sh)) and carries upstream's own `apps/openssl.cnf`\nverbatim at `/usr/local/ssl/openssl.cnf` inside the module's filesystem —\n`ext/openssl` cannot generate a key without one.\n\n## License\n\n[ISC](LICENSE)\n","readmeFilename":"README.md"}