|
6 | 6 | hasInjectionContext, |
7 | 7 | inject, |
8 | 8 | nextTick, |
| 9 | + onBeforeUpdate, |
| 10 | + onMounted, |
9 | 11 | provide, |
10 | 12 | reactive, |
11 | 13 | readonly, |
@@ -347,6 +349,104 @@ describe('api: provide/inject', () => { |
347 | 349 | expect(serialize(root)).toBe(`<div><!----></div>`) |
348 | 350 | }) |
349 | 351 |
|
| 352 | + // #13921 |
| 353 | + it('overlapping inheritance cycles', async () => { |
| 354 | + let shouldProvide = ref(false) |
| 355 | + |
| 356 | + const Comp4 = { |
| 357 | + props: ['data'], |
| 358 | + setup() { |
| 359 | + const data = ref('foo -1') |
| 360 | + |
| 361 | + onMounted(() => { |
| 362 | + data.value = inject('foo', 'foo 0') |
| 363 | + }) |
| 364 | + |
| 365 | + onBeforeUpdate(() => { |
| 366 | + data.value = inject('foo', 'foo 0') |
| 367 | + }) |
| 368 | + |
| 369 | + return () => [h('div', data.value)] |
| 370 | + }, |
| 371 | + } |
| 372 | + |
| 373 | + const Comp3 = { |
| 374 | + props: ['data'], |
| 375 | + setup() { |
| 376 | + const data = ref('foo -1') |
| 377 | + |
| 378 | + onMounted(() => { |
| 379 | + data.value = inject('foo', 'foo 0') |
| 380 | + }) |
| 381 | + |
| 382 | + onBeforeUpdate(() => { |
| 383 | + data.value = inject('foo', 'foo 0') |
| 384 | + }) |
| 385 | + |
| 386 | + return () => [ |
| 387 | + h('div', data.value), |
| 388 | + h(Comp4, { data: shouldProvide.value }), |
| 389 | + ] |
| 390 | + }, |
| 391 | + } |
| 392 | + |
| 393 | + const Comp2 = { |
| 394 | + setup() { |
| 395 | + const data = ref('foo -1') |
| 396 | + |
| 397 | + onMounted(() => { |
| 398 | + data.value = inject('foo', 'foo 0') |
| 399 | + }) |
| 400 | + |
| 401 | + onBeforeUpdate(() => { |
| 402 | + if (shouldProvide.value) { |
| 403 | + provide('foo', 'foo 2') |
| 404 | + } |
| 405 | + |
| 406 | + data.value = inject('foo', 'foo 0') |
| 407 | + }) |
| 408 | + |
| 409 | + return () => [ |
| 410 | + h('div', data.value), |
| 411 | + h(Comp3, { data: shouldProvide.value }), |
| 412 | + ] |
| 413 | + }, |
| 414 | + } |
| 415 | + |
| 416 | + const Comp1 = { |
| 417 | + setup() { |
| 418 | + provide('foo', 'foo 1') |
| 419 | + const data = ref('foo -1') |
| 420 | + |
| 421 | + onMounted(() => { |
| 422 | + data.value = inject('foo', 'foo 0') |
| 423 | + }) |
| 424 | + |
| 425 | + onBeforeUpdate(() => { |
| 426 | + data.value = inject('foo', 'foo 0') |
| 427 | + }) |
| 428 | + |
| 429 | + return () => [h('div', data.value), h(Comp2)] |
| 430 | + }, |
| 431 | + } |
| 432 | + |
| 433 | + const root = nodeOps.createElement('div') |
| 434 | + render(h(Comp1), root) |
| 435 | + |
| 436 | + shouldProvide.value = true |
| 437 | + await nextTick() |
| 438 | + |
| 439 | + /* |
| 440 | + First (Root Component) should be "foo 0" because it is the Root Component and provdes shall only be injected to Descandents. |
| 441 | + Second (Component 2) should be "foo 1" because it should inherit the provide from the Root Component |
| 442 | + Third (Component 3) should be "foo 2" because it should inherit the provide from Component 2 (in the second render when shouldProvide = true) |
| 443 | + Fourth (Component 4) should also be "foo 2" because it should inherit the provide from Component 3 which should inherit it from Component 2 (in the second render when shouldProvide = true) |
| 444 | + */ |
| 445 | + expect(serialize(root)).toBe( |
| 446 | + `<div><div>foo 0</div><div>foo 1</div><div>foo 2</div><div>foo 2</div></div>`, |
| 447 | + ) |
| 448 | + }) |
| 449 | + |
350 | 450 | describe('hasInjectionContext', () => { |
351 | 451 | it('should be false outside of setup', () => { |
352 | 452 | expect(hasInjectionContext()).toBe(false) |
|
0 commit comments