elm / virtual-dom

The foundation of HTML and SVG in Elm.
https://package.elm-lang.org/packages/elm/virtual-dom/latest
BSD 3-Clause "New" or "Revised" License
208 stars 80 forks source link

Elm update fails when using 1Password X Chrome extension #147

Open alvinlindstam opened 5 years ago

alvinlindstam commented 5 years ago

This was previously reported in https://github.com/elm/compiler/issues/1735, and noted to probably be fixed in 0.19.0.

I'm running elm 0.19.0 and get that error when running https://github.com/evancz/elm-architecture-tutorial/blob/bbe9e3f76a2415734349583f562465e45c1c6f46/examples/03-form.elm with two minor modifications:

System information: OS: Mac OS X 10.13.6 Browser: Version 70.0.3538.77 (Official Build) - current release Interfering extension: 1Password X - Password manager, version 1.12.2 (current release). The error does not happen when the extension is deactivated.

What would be expected: Interacting with the password fields (such as typing) should work, even when a common browser extension injected extra markup (not a simple thing, I know).

What happens:

  1. Page renders correctly
  2. I write into the name field (not a password field), no updates occur, no errors
  3. I write into the first password field, and there are no changes to the field, but the name field is filled with the last character typed when I filled that field before and the error below appears in the console
  4. I type into the second password field, and the first password field displays having a single character and the seconds is filled with the data I type but we do get another error for each input event (propable for each re-render?).

Exception:

03-form.elm:3672 Uncaught TypeError: Cannot read property 'replaceData' of undefined
    at _VirtualDom_applyPatch (03-form.elm:3672)
    at _VirtualDom_applyPatchesHelp (03-form.elm:3651)
    at _VirtualDom_applyPatches (03-form.elm:3642)
    at 03-form.elm:3897
    at 03-form.elm:3974
    at sendToApp (03-form.elm:1879)
    at HTMLInputElement.callback (03-form.elm:2950)

The compiled file: 03-form.elm.txt

As noted in the other issue, 1Password injects some markup into password fields, which for me was:

<com-1password-op-button id="com-1password-op-button" data-op-target="0" data-state="active" class="op-small" style="
        margin-left: 113px !important;
        margin-top: 3.5px !important;
        background-image: url(chrome-extension://aeblfdkhhhdcdjpifhhbdiojplfjncoa/images/icons/app_icon-light_bg-color-unlocked-12.svg) !important;
        "></com-1password-op-button>

The first password field also got the attribute data-op-id="0"

craiglyons commented 5 years ago

I can confirm this also in Firefox w/ 1Password. Wrapping inputs in a span a la #148 fixes this for me:

viewInput : String -> String -> String -> (String -> msg) -> Html msg
viewInput t p v toMsg =
  span [] [ input [ type_ t, placeholder p, value v, onInput toMsg ] [] ]

I'm happy to PR this on the docs as I could see this being a deal-breaker for newcomers.

alvinlindstam commented 5 years ago

I don't know much about how the virtual-DOM-renderer operates, but it would be nice to understand why wrapping it in a span fixes it. Would it be possible for the renderer to detect these scenarios and still work (I noticed that sometimes it falls back to recreating the instead of updating elements?).

Carlsson87 commented 5 years ago

I just encountered this problem as well. Here is how I am working around it at the moment. It might be useful to someone else.

replaceData is a DOM-api that is used to replace strings in textnodes. It only appears once in my compiled output, and that is in the dom diffing code. So if I can make changes to my view code such that virtual-dom never have to compare text nodes I can avoid this problem entirely. In my case I can do this by using Html.Keyed and using the same string that would be compared as a key. This results in the two different nodes never being compared, virtual-dom just replaces the node (?).

craiglyons commented 5 years ago

@alvinlindstam Agreed, and I believe this issue should remain open even if my PRs are merged. @Carlsson87 interesting. Seems hard to document or enforce, but may be good info for a real fix.

Also worth noting I see a different error message.

TypeError: domNode is undefined[Learn More] 4 03-form.elm:3685:4
    _VirtualDom_applyPatch http://localhost:8000/examples/03-form.elm:3685:4
    _VirtualDom_applyPatchesHelp http://localhost:8000/examples/03-form.elm:3664:17
    _VirtualDom_applyPatches http://localhost:8000/examples/03-form.elm:3655:9
    _Browser_element</</< http://localhost:8000/examples/03-form.elm:3909:15
    _Browser_makeAnimator/< http://localhost:8000/examples/03-form.elm:3981:8
    sendToApp http://localhost:8000/examples/03-form.elm:1895:3
    callback http://localhost:8000/examples/03-form.elm:2966:3
edouardmenayde commented 5 years ago

Same issue on my side

nicholastmosher commented 5 years ago

I'm also experiencing the same issue. Following the guide at https://guide.elm-lang.org/architecture/forms.html and using Firefox with 1password, the rendered input fields do not respond to keyboard input correctly. Disabling the 1password extension restores expected behavior.