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

[BUG] Polyfill fails if a <link> fails to load or returns non-CSS content #255

Closed
rkh opened this issue Oct 3, 2024 · 9 comments · Fixed by #258
Closed

[BUG] Polyfill fails if a <link> fails to load or returns non-CSS content #255

rkh opened this issue Oct 3, 2024 · 9 comments · Fixed by #258
Assignees
Labels
bug Something isn't working

Comments

@rkh
Copy link

rkh commented Oct 3, 2024

Great work on the polyfill! Haven't gotten it working yet, but hopefully I'll manage to.

Describe the bug
It is impossible for me to apply the polyfill. Getting the same error (different stack trace depending on the method used) when applying via Vite in dev mode, Vite bundle, or loading from unpkg (not my preference, as I don't want to add that to the CSP for production).

Example stacktrace:

Uncaught (in promise) TypeError: e.children is undefined
    ir utils.ts:70
    Tm parse.ts:306
    h create.js:169
    Xr create.js:108
    h create.js:180
    k create.js:195
    reduce List.js:174
    Xr create.js:103
    h create.js:180
    l create.js:239
    Tm parse.ts:304
    B @oddbird_css-anchor-positioning_fn.js:34
    B @oddbird_css-anchor-positioning_fn.js:20
    Tm parse.ts:294
    qm polyfill.ts:460
    o @oddbird_css-anchor-positioning_fn.js:23
    promise callback*c @oddbird_css-anchor-positioning_fn.js:33
    o @oddbird_css-anchor-positioning_fn.js:23
    promise callback*c @oddbird_css-anchor-positioning_fn.js:33
    o @oddbird_css-anchor-positioning_fn.js:23
    promise callback*c @oddbird_css-anchor-positioning_fn.js:33
    B @oddbird_css-anchor-positioning_fn.js:34
    B @oddbird_css-anchor-positioning_fn.js:20
    qm polyfill.ts:446
    setTimeout handler* application.ts:42
    onReady shim.ts:13
    async* application.ts:34

This happens no matter if I load the Polyfill before or after initializing the rest of the app, no matter if any CSS rules actually specify any anchor properties.

The line numbers seem to be a little off (possibly a sourcemap issue?). I assume the line in question is line 72.

FYI the example page is working for me.

To Reproduce
It's a fairly complex app; I'll look into creating an example repo in the coming days, but I wanted to see if, maybe, from the stack trace, this is already something you can spot.

Code I'm using:

import polyfill from '@oddbird/css-anchor-positioning/fn'
if (!("anchorName" in document.documentElement.style)) {
  if (document.readyState !== 'complete') window.addEventListener('load', () => { polyfill() })
  else polyfill()
}

Example I'm trying to get working:

<template>
  <li>
    <Avatar :userId class="avatar focusable" :popovertarget="id" />
    <div :id class="dropdown" popover="auto">This is the dropdown!</div>
  </li>
</template>

<style scoped lang="scss">
.avatar {
  anchor-name: v-bind(anchorName);
}

.dropdown {
  padding: 10px;
  left: unset;
  bottom: unset;
  top: anchor(v-bind(anchorName) bottom);
  right: anchor(v-bind(anchorName) right);
}
</style>

<script setup lang="ts">
import { userIdRef } from '@/pinto'
const userId     = computed(() => userIdRef.value)
const id         = useId()
const anchorName = useAnchorName(id)
</script>

Expected behavior
Polyfill to be applied.

Screenshots

Firefox:
image

Safari:
image

Browsers tested on
Firefox 130, Safari 18.1

@rkh rkh added the bug Something isn't working label Oct 3, 2024
@rkh
Copy link
Author

rkh commented Oct 4, 2024

It is, unfortunately, more complicated than I thought. I was unable to reproduce it in a simple Vite app.

@rkh
Copy link
Author

rkh commented Oct 4, 2024

Debugging further:

Vite with vite-ruby generates a link tag in the main template that looks like this:

<link rel="stylesheet" href="/vite-dev/entrypoints/application.scss" data-turbo-track="reload" />

However, the content served by vite-dev is neither CSS nor SCSS, but JavaScript instead (for HMR), and looks somewhat like this:

import { createHotContext as __vite__createHotContext } from "/vite-dev/@vite/client";import.meta.hot = __vite__createHotContext("/entrypoints/application.scss");import { updateStyle as __vite__updateStyle, removeStyle as __vite__removeStyle } from "/vite-dev/@vite/client"
const __vite__id = "/Users/konstantin/Workspace/good-beans/pinto/app/frontend/entrypoints/application.scss"
const __vite__css = "... ACTUAL CSS HERE ..."
__vite__updateStyle(__vite__id, __vite__css)
import.meta.hot.accept()
import.meta.hot.prune(() => __vite__removeStyle(__vite__id))

I assume this then gets added somewhere else so just a guard might help?
Seeing if I can work it out.

Update:

Just guarding against the lack of children (i.e. if (!rule || !rule.children) return []; instead of if (!rule) return [];) does not work, though it does obviously make the error go away.

@rkh
Copy link
Author

rkh commented Oct 4, 2024

I have not managed to reproduce this without vite-ruby, but I did manage to do so with it and a basic Rails app, no Vue needed at all.

Example repo: https://github.com/rkh/vite-rails-example

Reproduce:

  • Prerequisites: Recent Ruby, recent Node.js
  • Run bundle install && npm install to install dependencies
  • Run bin/vite dev to start the Vite dev server, run bin rails/server to run the Rails server
  • Open http://localhost:3000/ in Firefox

@jamesnw
Copy link
Contributor

jamesnw commented Oct 4, 2024

@rkh Thanks for the repo!

Is application.scss loading correctly for you? In the demo app, I am getting a 404, which means that the polyfill is trying to parse the 404 content, which is HTML. (I had to make some tweaks to get it running in my local Ruby environment, and I may have messed something up). However, this gives the same outcome as if it were JS, in that the parser can't parse the content, and it ends up erroring.

I think one task is for the polyfill to better handle <link>s that don't actually contain CSS.

Also, I would expect the polyfill to not work well with HMR- it currently only is applied once- see #91.

Does the polyfill still work as expected in the built app?

@rkh
Copy link
Author

rkh commented Oct 5, 2024

Yes, sorry, also getting the 404, only checked that it was the same error trace.

I only tested it on non-dynamic elements, so I assume it won't work in the built app, either (can confirm that for you if you want).

Feel free to close this issue if it is out of scope for you. I ended up not using the polyfill at all.

Off topic: What I ended up doing.

Unfortunately, relative positioning of popovers behaves differently between Firefox/Safari on the one hand and Chrome on the other, and thus I needed two different ways to implement this:

$avatar-size: 32px;
$offset-x: 0px;
$offset-y: 2px;

@supports (anchor-name: --example) {
  .avatar {
    anchor-name: v-bind(anchorName);
  }

  .dropdown {
    left: unset;
    bottom: unset;
    top: calc(anchor(v-bind(anchorName) bottom) + size($offset-y));
    right: calc(anchor(v-bind(anchorName) right) + size($offset-x));
  }
}

@supports not (anchor-name: --example) {
  .dropdown {
    position: relative;
    align-self: start;

    left: unset;
    bottom: unset;
    top: unset;
    right: unset;

    transform: translate(calc(size($avatar-size + $offset-x) - 100%), size($avatar-size + $offset-y));
  }
}

@jamesnw
Copy link
Contributor

jamesnw commented Oct 5, 2024

@rkh I would be interested in hearing if the polyfill works in a built vite rails app. I would expect it to work if the css file is served as CSS- confirmation would help us narrow down where this is an issue. Thanks!

@jamesnw
Copy link
Contributor

jamesnw commented Oct 5, 2024

The 404 issue can be reproduced in the demo app by adding <link rel="stylesheet" href="/fake.css" /> to the header.

@rkh
Copy link
Author

rkh commented Oct 5, 2024

@rkh I would be interested in hearing if the polyfill works in a built vite rails app. I would expect it to work if the css file is served as CSS- confirmation would help us narrow down where this is an issue. Thanks!

I can confirm the following for @oddbird/css-anchor-positioning 0.2.0 on Rails 7.1.4 with Vite 5.4.7:

  • The error does not happen when running a normal build (ie development without HMR, or production mode)
  • The polyfill is not applied to dynamically added Vue components, but works otherwise

Keep in mind that using Vite and Vue is not the standard Rails way. Instead the recommended approach is using Hotwire. This can result in HTML elements sometimes being dynamically added, and sometimes being included in the original HTML/CSS, so I'd suspect the polyfill would be unreliable in that scenario.

@jamesnw jamesnw changed the title [BUG] Polyfill function fails with an error in Vite/Vue 3 app [BUG] Polyfill fails if a <link> fails to load or returns non-CSS content Oct 10, 2024
This was referenced Oct 10, 2024
@jgerigmeyer jgerigmeyer linked a pull request Oct 11, 2024 that will close this issue
@jgerigmeyer
Copy link
Member

This is released in v0.3.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants