-
Notifications
You must be signed in to change notification settings - Fork 14
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
Delay require.js startup until conditions are satisfied #764
Comments
Commit tagged above. @ariel-phet I'd highly recommend this to be code reviewed (@samreid perhaps?), and I'm going to create a QA issue for some more specific testing. |
Adapted HTML from @jessegreenberg's minimal reproducible example at phetsims/tasks#1002 (comment): <!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hidden Sim test</title>
</head>
<body>
<div hidden id="container">
<iframe width="800" height="600" src="https://phet-dev.colorado.edu/html/charges-and-fields/1.1.0-dev.7/phet/charges-and-fields_en_phet.html" id="iframe" allowfullscreen scrolling="no" title="Some Title"></iframe>
</div>
<button id="testButton">Toggle Hidden</button>
</body>
<script type="text/javascript">
const container = document.getElementById( 'container' );
const button = document.getElementById( 'testButton' );
button.addEventListener( 'click', ( event ) => {
if ( container.hidden ) {
container.removeAttribute( 'hidden' );
}
else {
container.hidden = true;
}
} );
</script>
</html> |
QA issue tagged above. Once things look good (QA/review done), this seems like a candidate for maintenance releasing (potentially with @chrisklus tagging along). @ariel-phet does that sound like a plan? |
Is #764 (comment) expected to error out, or is dev.7 patched? It's not showing symptoms that I can see in Mac/Chrome. How many platforms does the "Can't GetBBox of SVG when hidden" affect? UPDATE: Also, should the setTimeout be changed to setInterval+clearInterval, so it will check more than once? |
I can reproduce the issues if I check out the 1.0 branch of masses-and-springs-basics, replace the URL in the HTML template to point to the non-assert require.js form (http://localhost/masses-and-springs-basics/masses-and-springs-basics_en.html?brand=phet for me), and patch Sim.js' resize() with Then the result of un-hiding the sim shows the buggy (unpatched) state: This is happening in the latest Chrome on Mac (Chrome 75).
It looks like this could also be used, but wouldn't save much (the check to see if we should add a timeout would be replaced with one to clear the interval). |
I did patch things and then deploy dev.7, so that should be the fixed behavior. |
@jonathanolson yes, agreed should be code reviewed (unclear if that already happened, but yes please have @samreid hop in on that). Also agreed it is good for a maintenance release. |
I won't be able to get to this right away, so @ariel-phet asked me to reassign to him to find another reviewer. UPDATE: I projected an 80% chance I could get to this by the end of Friday, so @ariel-phet asked me to go for it. |
I followed the steps in #764 (comment) and additionally discovered that you have to wait some 5-10 seconds before pressing "Toggle Hidden" in order to trigger the problem case. |
Review notes: I tested that the proposed solution works nicely! Nice work! Some comments: (1) Once (2) Does chipper-startup.js run during requirejs mode? It appears that it doesn't. Do we want our build to deviate from requirejs mode in this way? (3) requireBuild.js (4) I'm having trouble tracking down requirejs (5) Is it important to use (6) It looks like there is a little interference between the // We can call this anytime to attempt to start things (if they haven't been started already).
function attemptStart() {
if ( !started && isReady() ) {
started = true;
timeoutStillRunning && clearTimeout();
windowListenerStillRunning && removeWindowListener();
phet.chipper.runRequireJS();
}
} For instance, with this patch: Index: templates/chipper-startup.js
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- templates/chipper-startup.js (revision 0e1cf7b7f51776bca20379e777bc36200b9b3757)
+++ templates/chipper-startup.js (date 1562348254000)
@@ -62,7 +62,10 @@
// We can call this anytime to attempt to start things (if they haven't been started already).
function attemptStart() {
+ console.log( 'attempt start' );
if ( !started && isReady() ) {
+
+ console.log( 'started' );
started = true;
phet.chipper.runRequireJS();
@@ -71,6 +74,7 @@
// Attempt to start based on timeouts (in case other methods don't work). This will call attemptStart() at least once.
( function timeoutListener() {
+ console.log( 'timeoutListener' );
attemptStart();
if ( !started ) {
@@ -82,10 +86,12 @@
// Attempt to start on window resizes
window.addEventListener( 'resize', function resizeListener() {
+ console.log( 'resize' );
attemptStart();
if ( started ) {
window.removeEventListener( 'resize', resizeListener );
+ console.log( 'resize.started' );
}
} );
}
I saw this console.log trace:
Notice that even after resize and started, there is still another attempt to start. (7) The current implementation requires that chipper-startup.js be loaded last, right? Should that be documented as such? What code could be safely added after this point without disrupting things? (8) Is there a way to get (almost all of) chipper-startup.js to run as a standard preload, referenced from const startupJS = grunt.file.read( '../chipper/templates/chipper-startup.js' );
const productionStartupJS = minify( startupJS, minifyOptions );
const debugStartupJS = minify( startupJS, debugMinifyOptions ); Moving toward this strategy may help us reach the goal of running this new code in requirejs + built mode? (9) I don't know if this is attainable with await isReady();
phet.chipper.runRequireJS() (10) The signature of (11) Here and in TextBounds.js, why does the container have a width, height of 2x2? Is it important? It should be documented. (12) . What would have to happen in order to factor out the duplicated code between TextBounds.js and chipper-startup.js? Even if we can't easily factor out 100% of the duplicated code, could we factor out 80% of the code into a preload? |
No, we might be waiting on images to load also.
I tested this, and a timeout of 20ms between displaying and hiding again was able to produce this problem. I don't see any good way of handling this effectively, but I think it's unlikely to be encountered in the wild. Probably the only good way of handling this would be to switch to a different method of acquiring text bounds, but it's highly likely there is another way that gives the same results (so we may see a shift in spacing for text). It's a can of worms that requires a ton of browser testing, but if this becomes more of a problem, it could be looked into.
I don't think we ever plan to give require.js versions out to be embedded, and it would require a different solution. I have no problem with things differing, do you have a different opinion?
I'm open to naming suggestions. I fixed the string replacement (so the string value is used) and documented it in the above commit.
Added in a comment to the general section, but https://github.com/requirejs/r.js/blob/master/build/example.build.js documents all of the options we have at our disposal.
That looks like it could potentially be cleaner. I'm a little hesitant to change things too much from the scenery implementation (since it would require more testing). What are your thoughts?
It seems like more effort to independently track the state of all listeners to be able to clear them. Is there an advantage?
Not necessarily, there could conceivably be things in the future that we would want to run after the require.js step (say, if we ever wanted to move analytics code there, although it's currently a preload because there is no concept of "postload"). Should we document all of the order dependencies for the script order? For instance,
There is definitely opportunity for simplification (I'm including some cleanup in the above commit). We independently minify the four of these in both production and debug ways:
Yes, although async/await was added to browsers after Promises. That will be a nice day when that's possible!
The documentation says it converts non-strings to strings. Maybe this is similar to scenery's Text, where it converts them? This is potentially a change for a lot of scenery code (and maybe we should open a separate issue if changes are recommended).
IIRC, non-empty and it seems to work? Not sure, and I should have documented it at the time.
This seems like a big maintainability issue to factor it out. They are used in very different places, and have different use cases. I prefer mentioning the other usages, and not attempting to factor things out. |
I'll create separate issues for the ideas that need further discussion. |
I created issues for follow-up discussion or work. The proposed solution in master is an improvement over the previous status quo and seems stable enough to take simulations to RC. In my opinion, the blocks-publication label can be removed from this issue or this issue can be closed. None of the follow-up issues seem to be inherently blocking, unless we are concerned that addressing them over time will create complication for maintenance releases. Reassigning to @jonathanolson and @ariel-phet to see if this issue can be closed or changed to non-blocking. |
I've removed the blocks-publication label, but I want to keep this issue open to be the "master" issue for handling the maintenance release. |
In phetsims/tasks#1002, it was noticed that when the simulation is loaded in a hidden iframe, our SVG text bounds method does not work. Other minor things (like zero width/height for the window) also happen.
I'm going to add a way where we wait until the simulation is ready to load (checking window resizes for now, with setTimeout as a backup method (in case we for some reason don't get window resizes).
The text was updated successfully, but these errors were encountered: