Skip to content
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

Add support for ShadyDOM on-demand patching #5585

Draft
wants to merge 23 commits into
base: legacy-undefined-noBatch
Choose a base branch
from

Conversation

sorvell
Copy link
Contributor

@sorvell sorvell commented Aug 27, 2019

Do not merge until on webcomponents/polyfills#189.

Steven Orvell added 4 commits August 29, 2019 14:17
This is a polyfill optimization which defers class generation until first instance.
…fine` when the `Polymer` function is used.
@kevinpschaaf kevinpschaaf changed the base branch from master to legacy-undefined-noBatch September 4, 2019 23:58
Copy link
Member

@kevinpschaaf kevinpschaaf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved, only a couple minor nits which I think are nbd.

@@ -347,11 +347,11 @@ export class DomRepeat extends domRepeatBase {
/** @type {!HTMLElement} */ (this));
let template = this.template = thisAsTemplate._templateInfo ?
thisAsTemplate :
/** @type {!HTMLTemplateElement} */ (this.querySelector('template'));
/** @type {!HTMLTemplateElement} */ (wrap(this).querySelector('template'));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nbd, but nothing should ever be in a dom-repeat or dom-if except for a template (i.e. no nested elements with SR's that would need to be filtered out), so this is basically fine to always be native qs

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dome

} else {
const replace = n.__polymerReplaced__;
if (replace) {
wrap(wrap(replace).parentNode).replaceChild(n, replace);
wrap(wrapIfNeeded(replace).parentNode).replaceChild(n, replace);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not totally clear why the outer wrap can't be wrapIfNeeded. Adding a <slot> to any random spot in a shadow root obviously wouldn't be automatically on-demand patched, but this is only putting a <slot> back into a node that already had it (which I think means it is guaranteed to be patched)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -926,7 +926,7 @@ function setupCompoundStorage(node, binding) {
// We may also want to consider doing this for `textContent` and
// `innerHTML`.
if (target === 'className') {
node = wrap(node);
node = wrapIfNeeded(node);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like setting className on an otherwise uninteresting element in a SR (i.e. didn't need to have inside/outside patched) needs to always be wrapped so we don't lose scoping (note _setUnmanagedPropertyToNode below has similar code).

Might explain the test failure here? https://travis-ci.org/Polymer/polymer/builds/580988656#L780 (although unclear why this would only fail on Chrome 41?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. The issue is that patch needs to be the fallback to wrapping so that this works when instance patching is required.

@@ -22,3 +22,7 @@ export const wrap = (window['ShadyDOM'] && window['ShadyDOM']['noPatch'] && wind
window['ShadyDOM']['wrap'] :
(window['ShadyDOM'] ? (n) => ShadyDOM['patch'](n) : (n) => n);

// Wrapping a local operation (e.g. appendChild) is only needed iff noPatch is
// explicitly true, and on-demand patching is not used.
export const wrapIfNeeded = (window['ShadyDOM'] && window['ShadyDOM']['noPatch'] === true && window['ShadyDOM']['wrap']) ?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add comment to list known cases where wrap and not wrapIfNeeded is required:

  • When moving (appendChild/insertBefore) a node without an explicit removeChild to an unpatched location: in this case it needs to be unlinked from logical tree, have its className unscoped, trigger slotchange and, trigger distribution if it was a <slot>
  • When setting className to an unpatched node: if it was in a SR it needs to go through ShadyCSS to avoid losing its scoping class
  • When calling querySelector on an unpatched node: it won't return scoped results
  • When getting textContent or innerHTML on an unpatched node: it won't return scoped results

Also, now wondering if wrap and wrapAlways might be better naming (and less annoying to boot)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.

* when setting `textContent` or `innerHTML`.
*/
export const wrapIfNeeded = window['ShadyDOM'] && window['ShadyDOM']['wrapIfNeeded'] ?
window['ShadyDOM']['wrapIfNeeded'] : n => n;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fall back to wrap?


test('Polymer function does not return class when lazy define is used', function() {
assert.notOk(window.XLazyDeclarative);
assert.notOk(window.XLazyImperative);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

window.XLazyImperative was never assigned above

assert.ok(e.root.querySelector('span'));
});

test('imperatively generated elements upgrade and customElements.get works after instance created', function() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a test for something like

Polymer.telemetry.registrations.filter(r => r.is == 'x-lazy-imperative').length === 0

?

@stale
Copy link

stale bot commented Oct 14, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Oct 14, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants