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

fix: vNext fast-router templates not attaching on safari 16+ #6537

Closed
KingOfTac opened this issue Nov 22, 2022 · 17 comments · Fixed by #6566
Closed

fix: vNext fast-router templates not attaching on safari 16+ #6537

KingOfTac opened this issue Nov 22, 2022 · 17 comments · Fixed by #6566
Assignees
Labels
area:fast-element Pertains to fast-element area:fast-router Pertains to fast-router bug A bug status:needs-author-input The PR needs input from the author status:needs-investigation Needs additional investigation

Comments

@KingOfTac
Copy link
Collaborator

KingOfTac commented Nov 22, 2022

🐛 Bug Report

There appears to be an issue with the latest version of webkit that is causing Router to not get a template. Currently not aware if this is an issue with the vCurrent version of Router.

💻 Repro or Code Sample

Working on a repro.

Simple repro steps would be to create a new project using the latest FAST prerelease versions and add router with a few routes and a default layout.

🤔 Expected Behavior

Apps that use Router should be loading properly

😯 Current Behavior

After safari 16 was released, Router no longer gets a template attached either on initial page load or on route changes. Other FAST components built using the vNext libraries function normally.

💁 Possible Solution

Needs investigation

🌍 Your Environment

Safari on IOS 16.1
Epiphany Browser using webkit 16 on WSL Ubuntu-latest in windows 11

@KingOfTac KingOfTac added the status:triage New Issue - needs triage label Nov 22, 2022
@KingOfTac
Copy link
Collaborator Author

@EisenbergEffect I think I discovered the issue here, but not sure if it is an indication of a larger issue.

I noticed in my debugging that the DefaultRouter's config setter was not getting called in safari16. In the web component template that hosts the router element, I am binding the route config through a property binding: <fast-router :config=${x => x.config}>. I moved the setting of Router's config to the parent component's connectedCallback and things started working normally. What is really confusing is that the issue is only happening in Safari16+, all other browsers including Safari<16 are working fine with setting the router's config through a property binding in the template.

@EisenbergEffect
Copy link
Contributor

That's very strange. Can you isolate the issue to a simple component without the router?

@EisenbergEffect EisenbergEffect added bug A bug status:needs-investigation Needs additional investigation area:fast-element Pertains to fast-element status:needs-author-input The PR needs input from the author area:fast-router Pertains to fast-router labels Nov 23, 2022
@EisenbergEffect EisenbergEffect added this to the FAST Element 2.0 milestone Nov 23, 2022
@EisenbergEffect EisenbergEffect removed the status:triage New Issue - needs triage label Nov 23, 2022
@KingOfTac
Copy link
Collaborator Author

That's very strange. Can you isolate the issue to a simple component without the router?

I've been working on isolating, but no luck yet. It may also be a combination of things since I am using the inject decorator to inject the router config into the router's parent component.

@KingOfTac
Copy link
Collaborator Author

@EisenbergEffect I haven't been able to create a reliable repro yet, but seems like something changed in webkit16+ that is causing DI to break in some scenarios. I no longer think that this is an issue with Router, and instead it is in DI. I also don't think it is an issue with FAST at all but a bug introduced in Webkit since prior to 16 everything worked fine.

@bigopon
Copy link

bigopon commented Nov 28, 2022

Recently Aurelia has also been hit by some issues from webkit 16+. The issue is at aurelia/framework#1003

There's a breaking change in the spec at whatwg/dom#754, @jded76 and I have been trying to get a spec revert, and are waiting for some responses. You can join the discussion at whatwg/dom#819 (comment)

@EisenbergEffect
Copy link
Contributor

@bigopon and @KingOfTac Thanks for helping to look into this. I have a couple of questions:

Is the primary issue that document.adoptNode(...) doesn't return the adopted node anymore? If so, could that code just be changed to use the original template.content?

If not, does using document.importNode(...) solve the problem universally?

If not, is there an issue with the View moving elements back to the fragment when a view is removed?

I'm trying to figure out if it's one issue or a combination of issues. I'll need to make these fixes in both fast-element 1.0 and 2.0, so I'm trying to do the simplest one-time fix possible.

Any additional information you have is helpful. Again, thanks for looking into this!

@EisenbergEffect EisenbergEffect self-assigned this Nov 28, 2022
@jded76
Copy link

jded76 commented Nov 28, 2022

Is the primary issue that document.adoptNode(...) doesn't return the adopted node anymore? If so, could that code just be changed to use the original template.content?

It returns a node as usual, but this node doesn't have an owner document (it's still an empty document) because adoptNode returns early.

@KingOfTac
Copy link
Collaborator Author

The primary issue I have been facing is that dependencies injected into a component using either the inject decorator or the dependency as a decorator itself, are not available in the template for bindings on the initial render anymore. It sounds like the DI issue may just be a side effect of the above though it's just speculation at this point.

@bigopon
Copy link

bigopon commented Nov 29, 2022

The change in the behavior can be roughly summarized via the following pseudo code

document.adoptNode = function(node) {
  
+  if (node is Fragment && node.host) {
+    return
+  }
}

@EisenbergEffect
Copy link
Contributor

Ew. Thanks @bigopon. That's definitely a problem.

@EisenbergEffect
Copy link
Contributor

I started by trying to reproduce this with the Todo sample app. That app seems to work fine. I added some conditional template logic to see if adding/removing views dynamically was an issue. I can't seem to reproduce it with 16.1 (18614.2.9.1.12).

I'll try this with the router next. Seems like if it's a core problem it should be reproducible with basic templating though.

@KingOfTac
Copy link
Collaborator Author

I started by trying to reproduce this with the Todo sample app. That app seems to work fine. I added some conditional template logic to see if adding/removing views dynamically was an issue. I can't seem to reproduce it with 16.1 (18614.2.9.1.12).

I'll try this with the router next. Seems like if it's a core problem it should be reproducible with basic templating though.

I'll be able to circle back to creating a repro this evening, but in the meantime these are the rough steps that I think will repro with Router.

  1. Create a router config extending RouterConfiguration
  2. Create an App using the @customElement decorator with fast-router in the template.
  3. Inject a DI container and the router config as dependencies.
  4. In the connectedCallback, before calling super.connectedCallback register the default route recognizer with the container as a singleton.
  5. In the template pass the config to fast-router via a property binding :config=${x => x.routerConfig}

In all other browsers and Webkit <16 this pattern was working perfectly on the latest prerelease versions of FAST. With Webkit16+ this stopped working and I had to introduce a workaround where instead of passing the router config to fast-router through a property binding in the template, I now have to get a ref to the router element and pass the config after calling super.connectedCallback.

I have also observed this happening in other DI scenarios where you want to bind properties from an injected dependency directly into the component's template.

I haven't tested it yet, but I suspect that constructor injection will show similar behavior. I'm not privy to exactly how and when DI resolution and template binding happens, but my gut feeling is something isn't happening at the same time it was prior to Webkit 16

@EisenbergEffect
Copy link
Contributor

Template binding happens in the connectedCallback of FASTElement. The DI resolution happens "lazily" when the injected property is first accessed. So, that should happen while the template is being first rendered. I'm starting to wonder...what if Safari is invoking the connectedCallback before the parent property is set. That would cause DI resolution to fail...

@EisenbergEffect
Copy link
Contributor

Or rather, what if something is going wrong with events fired during the connectedCallback. The Context protocol that DI is based on uses an event to find the container. If that event is not propagating properly, then the container location will fail.

@EisenbergEffect
Copy link
Contributor

You could take DI out of the picture and just use straight context to see if that works.

@KingOfTac
Copy link
Collaborator Author

You could take DI out of the picture and just use straight context to see if that works.

I'm pretty sure this does work. I have a few services that are just using context and injected into components and it all works. It's the DI portion that fails.

@EisenbergEffect
Copy link
Contributor

EisenbergEffect commented Dec 2, 2022

Just going bit by bit. I updated my todo test to use DI instead of Context and it all works fine. So, next I'll add the router.

@EisenbergEffect EisenbergEffect removed their assignment Dec 7, 2022
@EisenbergEffect EisenbergEffect moved this from Triage to In Progress in FAST Architecture Roadmap Dec 13, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:fast-element Pertains to fast-element area:fast-router Pertains to fast-router bug A bug status:needs-author-input The PR needs input from the author status:needs-investigation Needs additional investigation
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

4 participants