-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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
PWA: VIewer as an ampdoc service #5300
Conversation
98f7c59
to
4dbab6a
Compare
/to @erwinmombay @aghassemi for review. This change caused a big ripple effect, so please review thoroughly. |
d88809b
to
23549d0
Compare
@dvoytenko LGTM, is the overlay code completely gone or has the mechanism moved somewhere? |
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.
nothing major except a possible race in canAnimate_
of vsyn since viewerService is initialized asynchronously there.
@@ -41,8 +42,10 @@ const INTERNAL_BRANCHES = { | |||
describe('a4a_config', () => { | |||
let sandbox; | |||
let win; | |||
let ampdoc; |
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 don't see this actually used outside of beforeEach
, maybe inline as installViewerServiceForDoc(ampdocService.getAmpDoc());
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.
Done
events = {}; | ||
installPlatformService(win); | ||
documentStateFor(win); | ||
const attrs = {}; | ||
element = { |
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.
This element is mocked but the one used above isn't. Can we use the same approach for both?
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.
Yes. This is unfortunate. I'm independently working on test rules to avoid this discrepancy. But it's out of scope for this PR.
const ampdocService = ampdocServiceFor(doc.defaultView); | ||
return ampdocService.getAmpDoc(element); | ||
}; | ||
doc.body.appendChild(element); |
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.
does it need to be appended? If so, probably should remove it in afterEach
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.
This is tested inside of a hermetic doc. The whole document is thrown out so this is ok.
@@ -466,6 +466,18 @@ function prepareAndAttachShadowDoc(global, extensions, hostElement, doc, url) { | |||
// Instal doc services. | |||
installAmpdocServices(ampdoc); | |||
|
|||
const viewer = viewerForDoc(ampdoc); |
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 think this and the same code in adopt
can be refactored to adoptShared
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. This part is executed independently and currently is rather different.
*/ | ||
constructor(win) { | ||
constructor(win, ampdoc) { |
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.
why both? can we do ampdoc.win and remove win param?
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 wanted to highlight that win
is the main argument. ampdoc
is a less important thing thing here for now. ampdoc
is only used to fix an iOS bug. So as soon as that code gets cleaned up, I will remove it.
/** @private @const {!./ampdoc-impl.AmpDocService} */ | ||
this.ampdocService_ = ampdocServiceFor(this.win); | ||
|
||
/** @const {!../document-state.DocumentState} */ |
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.
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.
Done
this.forceSchedule_(); | ||
} | ||
}); | ||
const boundOnVisibilityChanged = this.onVisibilityChanged_.bind(this); |
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.
This is confusing me. I was thrown off by docState
being a window-level state and not a per-doc state, but that aside, I don't understand why viewer.onVisibilityChanged
is more efficient than docState_.onVisibilityChanged
in the singleDoc mode.
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.
Basically, when window == ampdoc, viewer's visibility property can be used to determine visibility for both. In this case it's more efficient to disable animations when ampdoc is not visible. In multi-doc mode, we can only use window signal.
return false; | ||
} | ||
|
||
// Single doc: animations allowed when single doc is visible. |
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.
This may have race issue since singleDocViewer_ is initialized asynchronously so it may or may not be null based on timing. Is it guaranteed to have viewerService instantiated by this point? if not, this may either return true
or fail if there is a contextNode and viewerForDoc returns null because viewerService is not instantiated yet. If we are guaranteed to have a viewerService instance by this point, can we simplify the code to:
if (this.docState_.isHidden()) {
return false;
}
// getAmpDoc() handles opt_contextNode and caching the singleDoc just fine itself.
const ampdoc = this.ampdocService_.getAmpDoc(opt_contextNode);
// is there really a need to cache the viewer instance for single viewer case? I assume `viewerForDoc` and therefore `getServiceForDoc` do proper caching of instances anyway.
return viewerForDoc(ampdoc).isVisible();
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.
This will be fine. When doc is available, the viewer
is guaranteed to be available. The risk condition is ok as well - it will simply yield the same instance in this case. The only place where viewer might not be available is the constructor
above.
@erwinmombay The overlay code as used to be defined in |
23549d0
to
4cf76eb
Compare
LGTM! |
* Make Viewer an ampdoc service * review fixes * lints
* Make Viewer an ampdoc service * review fixes * lints
* Make Viewer an ampdoc service * review fixes * lints
* Make Viewer an ampdoc service * review fixes * lints
Partial for #3742.
Closes #3406.