-
Notifications
You must be signed in to change notification settings - Fork 549
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Run examples with php wasm #1097
Conversation
🚀 Regression report for commit 837e36b is at https://web-php-regression-report-pr-1097.preview.thephp.foundation |
🚀 Preview for commit 837e36b can be found at https://web-php-pr-1097.preview.thephp.foundation |
321a169
to
0dedf8e
Compare
This comment was marked as duplicate.
This comment was marked as duplicate.
js/interactive-examples.js
Outdated
|
||
async function main() { | ||
const buffer = []; | ||
const {ccall} = await phpBinary({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const {ccall} = await phpBinary({ | |
const {ccall} = await phpBinary({ |
(mixed tabs and spaces)
js/interactive-examples.js
Outdated
document.querySelectorAll('.example').forEach((example) => { | ||
const button = document.createElement('button'); | ||
const phpcode = example.querySelector('.phpcode'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
document.querySelectorAll('.example').forEach((example) => { | |
const button = document.createElement('button'); | |
const phpcode = example.querySelector('.phpcode'); | |
document.querySelectorAll('.example').forEach((example) => { | |
const button = document.createElement('button'); | |
const phpcode = example.querySelector('.phpcode'); |
js/interactive-examples.js
Outdated
button.innerText = 'Run code'; | ||
button.onclick = function() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
button.innerText = 'Run code'; | |
button.onclick = function() { | |
button.innerText = 'Run code'; | |
button.onclick = function() { |
js/interactive-examples.js
Outdated
}; | ||
|
||
phpcode.parentNode.insertBefore(button, phpcode); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
}; | |
phpcode.parentNode.insertBefore(button, phpcode); | |
}); | |
}; | |
phpcode.parentNode.insertBefore(button, phpcode); | |
}); |
js/interactive-examples.js
Outdated
const container = document.createElement('div'); | ||
container.classList.add('screen', 'example-contents'); | ||
const title = document.createElement('p'); | ||
title.innerText = 'Output: '; | ||
container.appendChild(title) | ||
const div = document.createElement('div'); | ||
div.classList.add('examplescode'); | ||
container.appendChild(div); | ||
const pre = document.createElement('pre'); | ||
pre.classList.add('examplescode'); | ||
pre.innerText = output; | ||
div.appendChild(pre) | ||
return container; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const container = document.createElement('div'); | |
container.classList.add('screen', 'example-contents'); | |
const title = document.createElement('p'); | |
title.innerText = 'Output: '; | |
container.appendChild(title) | |
const div = document.createElement('div'); | |
div.classList.add('examplescode'); | |
container.appendChild(div); | |
const pre = document.createElement('pre'); | |
pre.classList.add('examplescode'); | |
pre.innerText = output; | |
div.appendChild(pre) | |
return container; | |
const container = document.createElement('div'); | |
container.classList.add('screen', 'example-contents'); | |
const title = document.createElement('p'); | |
title.innerText = 'Output: '; | |
container.appendChild(title); | |
const div = document.createElement('div'); | |
div.classList.add('examplescode'); | |
container.appendChild(div); | |
const pre = document.createElement('pre'); | |
pre.classList.add('examplescode'); | |
pre.innerText = output; | |
div.appendChild(pre); | |
return container; |
CS
js/interactive-examples.js
Outdated
button.innerText = 'Run code'; | ||
button.onclick = function() { | ||
if (lastOutput && lastOutput.parentNode) { | ||
lastOutput.parentNode.removeChild(lastOutput) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
much simpler: lastOutput.remove()
(there is no reason to care about unmaintained browsers not supporting the remove
method when you are adding a feature requiring WebAssembly to work)
js/interactive-examples.js
Outdated
let lastOutput = null | ||
|
||
document.querySelectorAll('.example').forEach((example) => { | ||
const button = document.createElement('button'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the created button should use the button
type instead of the default submit
type, to avoid issues in case this ends up being used in a place being inside a form.
js/interactive-examples.js
Outdated
lastOutput.parentNode.removeChild(lastOutput) | ||
} | ||
|
||
ccall("phpw_run", null, ["string"], ['?>' + phpcode.innerText]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this use .innerText
or .textContent
here ? innerText
is impacted by the styles of the page
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no idea 🤷
js/interactive-examples.js
Outdated
buffer.length = 0; | ||
}; | ||
|
||
phpcode.parentNode.insertBefore(button, phpcode); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use phpcode.before()
instead
Disabling many extensions as you did in soyuka/php-wasm#7 is likely to make many examples non working though (in your build, even JSON functions are not available) |
Definitely, there are a few things to discuss, I can enable most extensions, some will require additional libraries (for example dom or xml require libxml) and it'll add weight to the build (now it's "only" 3.6 MB). |
$path = dirname(__DIR__) . '/js/' . $filename; | ||
echo '<script type="module" src="/cached.php?t=' . @filemtime($path) . '&f=/js/' . $filename . '"></script>' . "\n"; | ||
} | ||
?> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe that this deserves only one line?
As I understand, php binary is always loaded now, right? If yes, does it make sense to load it only when the user clicks "Run" for the first time? |
done |
Note that we should use brotli or gzip though, I'm unfamiliar with the server architecture behind the php docs website, should I add this directly to the cached.php file? |
@derickr is likely the person that would know this. |
It looks like php.net isn't particularly well set-up for encoding content. You can see how CSS/JS/etc is served up by the I'm not sure how much of the encoding happens on our server vs. what Myra does on the edge, but there's probably room for improvement there even outside of encoding the WASM bundle appropriately. The current web configuration isn't in the systems repo yet, though. |
If the modified code can still be highlighted, that would be even better. |
@lwlwilliam this would require bringing an actual code editor (Codemirror or Monaco) instead of just using |
@lwlwilliam, @stof, it makes sense for sure, but perhaps as step two in a separate PR? Just to keep this one smaller and delivered sooner. I'm pretty sure some unforeseen bugs will be discovered when this is deployed, and it'll be easier to fix them with smaller steps. |
@soyuka, what do you think about adding the PHP version in the output label? |
Myra already caches
I can ask whether they can do on the fly-compression, but I am not sure whether they do. To answer @jimwins, the config isn't in the systems repo, as nothing on php-web4 has been "php-ified" yet. I think Sascha set it up with nginx in his own way. There is no I believe adding it to |
I gave a trydiff --git a/cached.php b/cached.php
index 766afb2e..c8055ef7 100644
--- a/cached.php
+++ b/cached.php
@@ -46,6 +46,14 @@
header("Content-Type: application/javascript");
} elseif (substr($abs, -4) == ".css") {
header("Content-Type: text/css");
+} elseif (substr($abs, -4) == ".wasm") {
+ header("Content-Type: application/wasm");
+}
+
+$gzipped = $abs . '.gz';
+if (file_exists($gzipped) && isset($_SERVER['HTTP_ACCEPT_ENCODING']) && false !== strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')) {
+ $abs = $gzipped;
+ header("Content-Encoding: gzip");
}
readfile($abs); But as the Javascript is requiring the @pronskiy added version: |
Co-authored-by: lwlinux <[email protected]>
I don't quite understand whether your "try" was succesful or not. I can only see an image. The javascript should surely be calling And we deploy on nginx, so you should test with that, and not with something else. I have just added the nginx configuration to the systems repository: https://github.com/php/systems/tree/master/php-web4/nginx |
Should there be only one version or all of the supported in a dropdown/select? |
@shaedrich, for the sake of simplicity of this first step, it's better to stick to just one version. The dropdown sounds like a good idea for the next step. |
Probably want to add js/php-web.wasm filter=lfs diff=lfs merge=lfs binary to |
@derickr, @saundefined, @sy-records, folks, do you think this is ready to merge? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am getting failures when I try to check out this branch:
remote: Enumerating objects: 31, done.
remote: Counting objects: 100% (31/31), done.
remote: Compressing objects: 100% (15/15), done.
remote: Total 31 (delta 17), reused 27 (delta 16), pack-reused 0 (from 0)
Unpacking objects: 100% (31/31), 1.20 MiB | 1.79 MiB/s, done.
From https://github.com/php/web-php
* [new ref] refs/pull/1097/head -> pr/1097
M distributions
Switched to branch 'pr/1097'
Encountered 1 file that should have been a pointer, but wasn't:
js/php-web.wasm
error: cannot rebase: You have unstaged changes.
error: Please commit or stash them.
It is perhaps because something is on LFS, or not? The file just looked checked in here, so what is the deal with adding lfs
to .gitattributes
?
If it is LFS, then you need to provide instructions as to how to check it out properly.
0708497
to
2e50fbc
Compare
@derickr I reverted the change on gitattributes, may you try again? |
Merged, thanks so much! It should be live in the next hour or so. |
@soyuka Now that is merged, could you create an article on the wiki with very succinct steps as to how to rebuild the needed assets? |
hey guys, the WASM file doesn't appear to be compressed by the server? Edit: from reading the discussion I thought it should have been served compressed. |
@derickr to what script may I add the
Would php/systems#67 work? IMO we should get rid of |
I meant to comment on this before it got merged, but removing it from LFS was not the way to go. Running a git clone/pull now needs to download an additional 3.6 MB for this commit alone, and that will increase every time the wasm file is updated. By placing it in LFS, only the version tied to the commit would have ever need to be fetched. I think a simple |
@cookieguru We don't want to use LFS just yet - it's probably better to not have the WASM file in the repo at some point, but that causes problems too for deployment. |
Let's continue this discussion in php/systems#67 (only). |
What do you think to add selector with active PHP versions (e.g. 8.1-8.4)? if the code behavior differs between versions, we display these differences in the documentation, I suppose this way we can do away with |
@saundefined, it totally makes sense to me. For example if the dropdown defaults to PHP 8.4, I hit Run, and it shows the 8.4 output. Then I switch the dropdown to 8.3 and hit Run again. Would it replace the output or show the diff somehow? |
On Wed, 11 Dec 2024, Roman Pronskiy wrote:
For example if the dropdown defaults to PHP 8.4, I hit Run, and it
shows the 8.4 output. Then I switch the dropdown to 8.3 and hit Run
again. Would it replace the output or show the diff somehow?
Having multiple versions also means you need to have users download the
wasm binary multiple times. I really don't think we should focus on
that.
Having all examples do something when you press "Run code" so that no
Output blocks are needed seems to be more useful to me. But that does
mean having to go through all the examples.
|
I suggested the same thing:
so, I'd love to have that as well. Maybe, now is the right time to implement it, now that the initial implementation is merged After that, we might even have a feature to compare outputs of two different versions 🤔 🤯 |
@derickr, not necessarily. Any version of Wasm should be downloaded only when the user clicks “Run” for the first time. For example:
|
Adds a PHP Wasm binary to run documentation examples in the browser. We discussed this with @pronskiy (
fixes php/doc-en#3259).
php-doc-2.mp4
I've builtin
PHP wasm 8.4.0-dev
and I'm not sure what would be preferred to keep this up to date. If you want to reproduce the build see:soyuka/php-wasm#7
Clone that branch and execute:
Work sponsored by Les-Tilleuls.coop inline with what we built at the API Platform Playground more informations on a blog post