vuejs / core

đź–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
https://vuejs.org/
MIT License
46.86k stars 8.22k forks source link

Inject prioritizes current component over RunWithContext app #11488

Closed Bertie2011 closed 1 month ago

Bertie2011 commented 1 month ago

Vue version

3.4.35

Link to minimal reproduction

https://play.vuejs.org/#eNqNVFFr2zAQ/itXvzgFz2F0e+ncwFoKzWDd2Mb6YhiufY3V2ZKR5DQl+L/vTopdNevSgR8s6bu77777pG30sevSdY/RaZSZUovOgkHbd4tcirZT2sIWNN4l0Gm1FhXCAHdatRBTTPxhAl3Uoql2J+ncrTgrI3JZKmkstGYFZ5xrFl9h0yi4UbqpjuJjh9mln8WbOIG4wg5lhbJ8BCFBK2Wh6DoHzeaeJhGkhcW2awqLtALI6reL7dYVGoZsTiu369jM6T+bB/AoiawhZndild4bJUmALcPzqFRtJxrUXzoriHkenYI74bOCiD98cntW95iM+2WN5e8X9u/Nhvfy6KtGg3qNeTSd2UKv0Prjy+/XuKH/6bBVVd8Q+sDhNzSq6Zmjh533siLaAc6xXboJCbn6YS43FqUZm2KijBwcPo9oXhcHWn+ie5K+c3G5HEjFadgHLCTkPZY2gVIjqU+WS0DJz6qXFquEPfGyq67REGCylV/u+6rk+ktXgPzlK7GN2CweIV3cBGELetNNHGazYzhb+F6DrESU8BPpmSfAsQTbAdJDzvWVJ+8GUS0XnlWq7FuUNiVlLxvk3/PHZTWLfeAbr3l87IPDPtJ10fTI7MaMupc3wtYXihra2F1HgRycY3jtBlVi7X4ArkQCthYG6Ct8FZKG5iKZr8dkt3qxhBXdTl8Hq1PIBN3BYCZ8E8Uup8cXjVE0hJWgbjSrA89FszUGwgWlrtQDrlEn8FCjhCUZ+JGKAynkYoIszjG2LsbZc6KEIghKDG+JYaglU7z1/c9HAbjeqAiI6iyPno0kj3YthVH778uTXw+9rl66/Xd19O4o7M+i+cvd/zfIZcxShJIevTK9oObT9P7V5C+aCD8p1CK9C+nJ+2j4A8zyJHQ=

Steps to reproduce

Try building a nested vue app instance in a component and fetching a dependency from it.

What is expected?

When I do app.runWithContext I expect that any inject() inside will use the specified app, no matter what.

What is actually happening?

After some digging I discovered the method prioritizes the current component (or the appContext of the component) over the specified instance. See this line

I would suggest the order of precedence to be: specified app if different from component appContext -> component context -> component appContext.

Or even, it might be considered a feature if it would just look at the specified app and skip the component dependencies entirely.

System Info

No response

Any additional comments?

I'm building an application with multiple navigable windows, so multiple router instances and multiple vue app in order to make it work nicely. So naturally, there has to be some small interface layer between the root and nested apps in order to make everything work together and that's how I ended up trying to pull a nested app dependency into the root app component that creates the app. (Or rather: calls the app create function that's defined elsewhere, because the window management components shouldn't really have to know how to create apps.)

edison1105 commented 1 month ago

I think it's a bug

    const app = createApp({
      setup() {
        provide('foo', 'should not be seen')

  // nested createApp
        const childApp = createApp({
          setup() {
            provide('foo', 'foo from child')
          }
        })
        childApp.provide('foo',2)
        expect(childApp.runWithContext(() => inject('foo'))).toBe(2) // should be 2 but got 1

        return () => h('div')
      },
    })
    app.provide('foo', 1)

    expect(app.runWithContext(() => inject('foo'))).toBe(1)