Disallow non-element params to service getters#16328
Disallow non-element params to service getters#16328dreamofabear merged 10 commits intoampproject:masterfrom
Conversation
jridgewell
left a comment
There was a problem hiding this comment.
Why can't we just have it accept a Document?
src/service.js
Outdated
| // If a node is passed, try to resolve via this node. | ||
| const win = toWin(/** @type {!Document} */ ( | ||
| nodeOrDoc.ownerDocument || nodeOrDoc).defaultView); | ||
| elementOrAmpDoc.ownerDocument || elementOrAmpDoc).defaultView); |
There was a problem hiding this comment.
This change is incorrect. Element does not have a defaultView.
There was a problem hiding this comment.
Oh man, nice catch. Thanks.
src/element-service.js
Outdated
| if (elementOrAmpDoc.nodeType) { | ||
| const win = toWin(/** @type {!Document} */ ( | ||
| nodeOrDoc.ownerDocument || nodeOrDoc).defaultView); | ||
| elementOrAmpDoc.ownerDocument || elementOrAmpDoc).defaultView); |
src/service/navigation.js
Outdated
| */ | ||
| parseUrl_(url) { | ||
| return Services.urlForDoc(this.rootNode_).parse(url); | ||
| return Services.urlForDoc(this.ampdoc).parse(url); |
There was a problem hiding this comment.
I don't think this change is correct. rootNode is in the document scope, while ampdoc is the root scope.
There was a problem hiding this comment.
I considered that, but I don't think local scope is important for URL parsing. Line 168 already grabs the URL service from this.ampdoc.
There was a problem hiding this comment.
For FIEs, it's critical. FIE have a <base> element that changes where their relative URLs resolve from.
There was a problem hiding this comment.
TIL, good call. I think I was too aggressive here -- reverted APIs for FIE-scope services.
It would only work for single docs since shadow AMPs don't have a Document, and I want to prevent misuse. Part of the problem is Document vs. AmpDoc conflation e.g. |
|
/cc @dvoytenko FYI |
| /** | ||
| * `nodeOrDoc` must be passed for correct behavior in shadow AMP (PWA) case. | ||
| * @param {!Window} win | ||
| * @param {!Node|!../../../src/service/ampdoc-impl.AmpDoc} nodeOrDoc |
There was a problem hiding this comment.
!../../../src/service/ampdoc-impl.AmpDoc makes me 😢
src/service/navigation.js
Outdated
| */ | ||
| parseUrl_(url) { | ||
| return Services.urlForDoc(this.rootNode_).parse(url); | ||
| return Services.urlForDoc(this.ampdoc).parse(url); |
There was a problem hiding this comment.
For FIEs, it's critical. FIE have a <base> element that changes where their relative URLs resolve from.
f1f8ed8 to
5f1d6ab
Compare
|
@jridgewell Friendly ping. |
src/service.js
Outdated
| * Unlike most service getters, passing `Node` is necessary for some FIE-scope | ||
| * services since sometimes we only have the FIE Document for context. | ||
| * | ||
| * @param {!Node|!./service/ampdoc-impl.AmpDoc} nodeOrAmpDoc |
There was a problem hiding this comment.
Could we change this to !Element|!ShadowRoot|!AmpDoc? That we we fix the core bug here (passing in a Document) but still allow ShadowRoots?
There was a problem hiding this comment.
The problem isn't shadow roots, it's FIE.
In PWA context, callers typically can pass in the AmpDoc or elements in the shadow DOM. But in FIE, sometimes we only have access to the iframe's contentWindow. This is because of how FIE services are set up:
amphtml/src/service/extensions-impl.js
Lines 661 to 669 in b6d49e4
Maybe we can refactor this but it'll be a large change. Another idea is to have privileged and non-privileged getters, one that takes !Node and another that takes !Element.
| * Unlike most service getters, passing `Node` is necessary for some FIE-scope | ||
| * services since sometimes we only have the FIE Document for context. | ||
| * | ||
| * @param {!Node|!./service/ampdoc-impl.AmpDoc} nodeOrDoc |
There was a problem hiding this comment.
Could we change this to !Element|!ShadowRoot|!AmpDoc? That we we fix the core bug here (passing in a Document) but still allow ShadowRoots?
Partial for #16322. Goal is to prevent bugs like #16043 in the future.
window.documentbeing passed to service getters.!Elementinstead of!Nodeto prevent future bugs.getServiceForDocDeprecated(nodeOrDoc, id)to keep a few remaining usages (startup services) for follow-up fix./to @jridgewell @danielrozenberg /cc @jpettitt @aghassemi