From: daiwei Date: Fri, 20 Jun 2025 03:29:36 +0000 (+0800) Subject: chore: Merge branch 'vapor' into edison/feat/vaporTeleport X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fed71cb8002be9c8da1bc6fb951880581724f8fc;p=thirdparty%2Fvuejs%2Fcore.git chore: Merge branch 'vapor' into edison/feat/vaporTeleport --- fed71cb8002be9c8da1bc6fb951880581724f8fc diff --cc packages/runtime-core/src/index.ts index fabe46dc31,1ed6f21df7..1ac5cb9bac --- a/packages/runtime-core/src/index.ts +++ b/packages/runtime-core/src/index.ts @@@ -557,11 -557,7 +557,15 @@@ export { startMeasure, endMeasure } fro * @internal */ export { initFeatureFlags } from './featureFlags' +/** + * @internal + */ +export { + resolveTarget as resolveTeleportTarget, + isTeleportDisabled, + isTeleportDeferred, +} from './components/Teleport' + /** + * @internal + */ + export { createInternalObject } from './internalObject' diff --cc packages/runtime-vapor/__tests__/components/Teleport.spec.ts index 6863d398bf,0000000000..bad5208726 mode 100644,000000..100644 --- a/packages/runtime-vapor/__tests__/components/Teleport.spec.ts +++ b/packages/runtime-vapor/__tests__/components/Teleport.spec.ts @@@ -1,1168 -1,0 +1,1169 @@@ +import { + type LooseRawProps, + type VaporComponent, + createComponent as createComp, +} from '../../src/component' +import { + type VaporDirective, + VaporTeleport, + child, + createIf, + createTemplateRefSetter, + defineVaporComponent, + renderEffect, + setInsertionState, + setText, + template, + withVaporDirectives, +} from '@vue/runtime-vapor' +import { makeRender } from '../_utils' +import { + nextTick, + onBeforeUnmount, + onMounted, + onUnmounted, + ref, + shallowRef, +} from 'vue' + +import type { HMRRuntime } from '@vue/runtime-dom' +declare var __VUE_HMR_RUNTIME__: HMRRuntime +const { createRecord, rerender, reload } = __VUE_HMR_RUNTIME__ + +const define = makeRender() + +describe('renderer: VaporTeleport', () => { + describe('eager mode', () => { + runSharedTests(false) + }) + + describe('defer mode', () => { + runSharedTests(true) + + test('should be able to target content appearing later than the teleport with defer', () => { + const root = document.createElement('div') + document.body.appendChild(root) + + const { mount } = define({ + setup() { + const n1 = createComp( + VaporTeleport, + { + to: () => '#target', + defer: () => true, + }, + { + default: () => template('
teleported
')(), + }, + ) + const n2 = template('
')() + return [n1, n2] + }, + }).create() + mount(root) + + expect(root.innerHTML).toBe( + '
teleported
', + ) + }) + + test.todo('defer mode should work inside suspense', () => {}) + + test('update before mounted with defer', async () => { + const root = document.createElement('div') + document.body.appendChild(root) + + const show = ref(false) + const foo = ref('foo') + const Header = defineVaporComponent({ + props: { foo: String }, + setup(props) { + const n0 = template(`
`)() + const x0 = child(n0 as any) + renderEffect(() => setText(x0 as any, props.foo)) + return [n0] + }, + }) + const Footer = defineVaporComponent({ + setup() { + foo.value = 'bar' + return template('
Footer
')() + }, + }) + + const { mount } = define({ + setup() { + return createIf( + () => show.value, + () => { + const n1 = createComp( + VaporTeleport, + { to: () => '#targetId', defer: () => true }, + { default: () => createComp(Header, { foo: () => foo.value }) }, + ) + const n2 = createComp(Footer) + const n3 = template('
')() + return [n1, n2, n3] + }, + () => template('
')(), + ) + }, + }).create() + mount(root) + + expect(root.innerHTML).toBe('
') + + show.value = true + await nextTick() + expect(root.innerHTML).toBe( + `
Footer
bar
`, + ) + }) + }) + + describe('HMR', () => { + test('rerender child + rerender parent', async () => { + const target = document.createElement('div') + const root = document.createElement('div') + const childId = 'test1-child-rerender' + const parentId = 'test1-parent-rerender' + + const { component: Child } = define({ + __hmrId: childId, + render() { + return template('
teleported
')() + }, + }) + createRecord(childId, Child as any) + + const { mount, component: Parent } = define({ + __hmrId: parentId, + render() { + const n0 = createComp( + VaporTeleport, + { + to: () => target, + }, + { + default: () => createComp(Child), + }, + ) + const n1 = template('
root
')() + return [n0, n1] + }, + }).create() + createRecord(parentId, Parent as any) + mount(root) + + expect(root.innerHTML).toBe('
root
') + expect(target.innerHTML).toBe('
teleported
') + + // rerender child + rerender(childId, () => { + return template('
teleported 2
')() + }) + + expect(root.innerHTML).toBe('
root
') + expect(target.innerHTML).toBe('
teleported 2
') + + // rerender parent + rerender(parentId, () => { + const n0 = createComp( + VaporTeleport, + { + to: () => target, + }, + { + default: () => createComp(Child), + }, + ) + const n1 = template('
root 2
')() + return [n0, n1] + }) + + expect(root.innerHTML).toBe('
root 2
') + expect(target.innerHTML).toBe('
teleported 2
') + }) + + test('parent rerender + toggle disabled', async () => { + const target = document.createElement('div') + const root = document.createElement('div') + const parentId = 'test3-parent-rerender' + const disabled = ref(true) + + const Child = defineVaporComponent({ + render() { + return template('
teleported
')() + }, + }) + + const { mount, component: Parent } = define({ + __hmrId: parentId, + render() { + const n2 = template('
root
', true)() as any + setInsertionState(n2, 0) + createComp( + VaporTeleport, + { + to: () => target, + disabled: () => disabled.value, + }, + { + default: () => createComp(Child), + }, + ) + return n2 + }, + }).create() + createRecord(parentId, Parent as any) + mount(root) + + expect(root.innerHTML).toBe( - '
teleported
root
', ++ '
teleported
root
', + ) + expect(target.innerHTML).toBe('') + + // rerender parent + rerender(parentId, () => { + const n2 = template('
root 2
', true)() as any + setInsertionState(n2, 0) + createComp( + VaporTeleport, + { + to: () => target, + disabled: () => disabled.value, + }, + { + default: () => createComp(Child), + }, + ) + return n2 + }) + + expect(root.innerHTML).toBe( - '
teleported
root 2
', ++ '
teleported
root 2
', + ) + expect(target.innerHTML).toBe('') + + // toggle disabled + disabled.value = false + await nextTick() + expect(root.innerHTML).toBe('
root 2
') + expect(target.innerHTML).toBe('
teleported
') + }) + + test('reload child + reload parent', async () => { + const target = document.createElement('div') + const root = document.createElement('div') + const childId = 'test1-child-reload' + const parentId = 'test1-parent-reload' + + const { component: Child } = define({ + __hmrId: childId, + setup() { + const msg = ref('teleported') + return { msg } + }, + render(ctx) { + const n0 = template(`
`)() + const x0 = child(n0 as any) + renderEffect(() => setText(x0 as any, ctx.msg)) + return [n0] + }, + }) + createRecord(childId, Child as any) + + const { mount, component: Parent } = define({ + __hmrId: parentId, + setup() { + const msg = ref('root') + const disabled = ref(false) + return { msg, disabled } + }, + render(ctx) { + const n0 = createComp( + VaporTeleport, + { + to: () => target, + disabled: () => ctx.disabled, + }, + { + default: () => createComp(Child), + }, + ) + const n1 = template(`
`)() + const x0 = child(n1 as any) + renderEffect(() => setText(x0 as any, ctx.msg)) + return [n0, n1] + }, + }).create() + createRecord(parentId, Parent as any) + mount(root) + + expect(root.innerHTML).toBe('
root
') + expect(target.innerHTML).toBe('
teleported
') + + // reload child by changing msg + reload(childId, { + __hmrId: childId, + __vapor: true, + setup() { + const msg = ref('teleported 2') + return { msg } + }, + render(ctx: any) { + const n0 = template(`
`)() + const x0 = child(n0 as any) + renderEffect(() => setText(x0 as any, ctx.msg)) + return [n0] + }, + }) + expect(root.innerHTML).toBe('
root
') + expect(target.innerHTML).toBe('
teleported 2
') + + // reload parent by changing msg + reload(parentId, { + __hmrId: parentId, + __vapor: true, + setup() { + const msg = ref('root 2') + const disabled = ref(false) + return { msg, disabled } + }, + render(ctx: any) { + const n0 = createComp( + VaporTeleport, + { + to: () => target, + disabled: () => ctx.disabled, + }, + { + default: () => createComp(Child), + }, + ) + const n1 = template(`
`)() + const x0 = child(n1 as any) + renderEffect(() => setText(x0 as any, ctx.msg)) + return [n0, n1] + }, + }) + + expect(root.innerHTML).toBe('
root 2
') + expect(target.innerHTML).toBe('
teleported 2
') + + // reload parent again by changing disabled + reload(parentId, { + __hmrId: parentId, + __vapor: true, + setup() { + const msg = ref('root 2') + const disabled = ref(true) + return { msg, disabled } + }, + render(ctx: any) { + const n0 = createComp( + VaporTeleport, + { + to: () => target, + disabled: () => ctx.disabled, + }, + { + default: () => createComp(Child), + }, + ) + const n1 = template(`
`)() + const x0 = child(n1 as any) + renderEffect(() => setText(x0 as any, ctx.msg)) + return [n0, n1] + }, + }) + + expect(root.innerHTML).toBe( + '
teleported 2
root 2
', + ) + expect(target.innerHTML).toBe('') + }) + + test('reload single root child + toggle disabled', async () => { + const target = document.createElement('div') + const root = document.createElement('div') + const childId = 'test2-child-reload' + const parentId = 'test2-parent-reload' + + const disabled = ref(true) + const { component: Child } = define({ + __hmrId: childId, + setup() { + const msg = ref('teleported') + return { msg } + }, + render(ctx) { + const n0 = template(`
`)() + const x0 = child(n0 as any) + renderEffect(() => setText(x0 as any, ctx.msg)) + return [n0] + }, + }) + createRecord(childId, Child as any) + + const { mount, component: Parent } = define({ + __hmrId: parentId, + setup() { + const msg = ref('root') + return { msg, disabled } + }, + render(ctx) { + const n0 = createComp( + VaporTeleport, + { + to: () => target, + disabled: () => ctx.disabled, + }, + { + // with single root child + default: () => createComp(Child), + }, + ) + const n1 = template(`
`)() + const x0 = child(n1 as any) + renderEffect(() => setText(x0 as any, ctx.msg)) + return [n0, n1] + }, + }).create() + createRecord(parentId, Parent as any) + mount(root) + + expect(root.innerHTML).toBe( + '
teleported
root
', + ) + expect(target.innerHTML).toBe('') + + // reload child by changing msg + reload(childId, { + __hmrId: childId, + __vapor: true, + setup() { + const msg = ref('teleported 2') + return { msg } + }, + render(ctx: any) { + const n0 = template(`
`)() + const x0 = child(n0 as any) + renderEffect(() => setText(x0 as any, ctx.msg)) + return [n0] + }, + }) + expect(root.innerHTML).toBe( + '
teleported 2
root
', + ) + expect(target.innerHTML).toBe('') + + // reload child again by changing msg + reload(childId, { + __hmrId: childId, + __vapor: true, + setup() { + const msg = ref('teleported 3') + return { msg } + }, + render(ctx: any) { + const n0 = template(`
`)() + const x0 = child(n0 as any) + renderEffect(() => setText(x0 as any, ctx.msg)) + return [n0] + }, + }) + expect(root.innerHTML).toBe( + '
teleported 3
root
', + ) + expect(target.innerHTML).toBe('') + + // toggle disabled + disabled.value = false + await nextTick() + expect(root.innerHTML).toBe('
root
') + expect(target.innerHTML).toBe('
teleported 3
') + }) + + test('reload multiple root children + toggle disabled', async () => { + const target = document.createElement('div') + const root = document.createElement('div') + const childId = 'test3-child-reload' + const parentId = 'test3-parent-reload' + + const disabled = ref(true) + const { component: Child } = define({ + __hmrId: childId, + setup() { + const msg = ref('teleported') + return { msg } + }, + render(ctx) { + const n0 = template(`
`)() + const x0 = child(n0 as any) + renderEffect(() => setText(x0 as any, ctx.msg)) + return [n0] + }, + }) + createRecord(childId, Child as any) + + const { mount, component: Parent } = define({ + __hmrId: parentId, + setup() { + const msg = ref('root') + return { msg, disabled } + }, + render(ctx) { + const n0 = createComp( + VaporTeleport, + { + to: () => target, + disabled: () => ctx.disabled, + }, + { + default: () => { + // with multiple root children + return [createComp(Child), template(`child`)()] + }, + }, + ) + const n1 = template(`
`)() + const x0 = child(n1 as any) + renderEffect(() => setText(x0 as any, ctx.msg)) + return [n0, n1] + }, + }).create() + createRecord(parentId, Parent as any) + mount(root) + + expect(root.innerHTML).toBe( + '
teleported
child
root
', + ) + expect(target.innerHTML).toBe('') + + // reload child by changing msg + reload(childId, { + __hmrId: childId, + __vapor: true, + setup() { + const msg = ref('teleported 2') + return { msg } + }, + render(ctx: any) { + const n0 = template(`
`)() + const x0 = child(n0 as any) + renderEffect(() => setText(x0 as any, ctx.msg)) + return [n0] + }, + }) + expect(root.innerHTML).toBe( + '
teleported 2
child
root
', + ) + expect(target.innerHTML).toBe('') + + // reload child again by changing msg + reload(childId, { + __hmrId: childId, + __vapor: true, + setup() { + const msg = ref('teleported 3') + return { msg } + }, + render(ctx: any) { + const n0 = template(`
`)() + const x0 = child(n0 as any) + renderEffect(() => setText(x0 as any, ctx.msg)) + return [n0] + }, + }) + expect(root.innerHTML).toBe( + '
teleported 3
child
root
', + ) + expect(target.innerHTML).toBe('') + + // toggle disabled + disabled.value = false + await nextTick() + expect(root.innerHTML).toBe('
root
') + expect(target.innerHTML).toBe('
teleported 3
child') + }) + }) +}) + +function runSharedTests(deferMode: boolean): void { + const createComponent = deferMode + ? ( + component: VaporComponent, + rawProps?: LooseRawProps | null, + ...args: any[] + ) => { + if (component === VaporTeleport) { + rawProps!.defer = () => true + } + return createComp(component, rawProps, ...args) + } + : createComp + + test('should work', () => { + const target = document.createElement('div') + const root = document.createElement('div') + + const { mount } = define({ + setup() { + const n0 = createComponent( + VaporTeleport, + { + to: () => target, + }, + { + default: () => template('
teleported
')(), + }, + ) + const n1 = template('
root
')() + return [n0, n1] + }, + }).create() + mount(root) + + expect(root.innerHTML).toBe('
root
') + expect(target.innerHTML).toBe('
teleported
') + }) + + test.todo('should work with SVG', async () => {}) + + test('should update target', async () => { + const targetA = document.createElement('div') + const targetB = document.createElement('div') + const target = ref(targetA) + const root = document.createElement('div') + + const { mount } = define({ + setup() { + const n0 = createComponent( + VaporTeleport, + { + to: () => target.value, + }, + { + default: () => template('
teleported
')(), + }, + ) + const n1 = template('
root
')() + return [n0, n1] + }, + }).create() + mount(root) + + expect(root.innerHTML).toBe('
root
') + expect(targetA.innerHTML).toBe('
teleported
') + expect(targetB.innerHTML).toBe('') + + target.value = targetB + await nextTick() + + expect(root.innerHTML).toBe('
root
') + expect(targetA.innerHTML).toBe('') + expect(targetB.innerHTML).toBe('
teleported
') + }) + + test('should update children', async () => { + const target = document.createElement('div') + const root = document.createElement('div') + const children = shallowRef([template('
teleported
')()]) + + const { mount } = define({ + setup() { + const n0 = createComponent( + VaporTeleport, + { + to: () => target, + }, + { + default: () => children.value, + }, + ) + const n1 = template('
root
')() + return [n0, n1] + }, + }).create() + mount(root) + + expect(target.innerHTML).toBe('
teleported
') + + children.value = [template('')()] + await nextTick() + expect(target.innerHTML).toBe('') + + children.value = [template('teleported')()] + await nextTick() + expect(target.innerHTML).toBe('teleported') + }) + + test('should remove children when unmounted', async () => { + const target = document.createElement('div') + const root = document.createElement('div') + + function testUnmount(props: any) { + const { app } = define({ + setup() { + const n0 = createComponent(VaporTeleport, props, { + default: () => template('
teleported
')(), + }) + const n1 = template('
root
')() + return [n0, n1] + }, + }).create() + app.mount(root) + + expect(target.innerHTML).toBe( + props.disabled() ? '' : '
teleported
', + ) + + app.unmount() + expect(target.innerHTML).toBe('') + expect(target.children.length).toBe(0) + } + + testUnmount({ to: () => target, disabled: () => false }) + testUnmount({ to: () => target, disabled: () => true }) + testUnmount({ to: () => null, disabled: () => true }) + }) + + test('component with multi roots should be removed when unmounted', async () => { + const target = document.createElement('div') + const root = document.createElement('div') + + const { component: Comp } = define({ + setup() { + return [template('

')(), template('

')()] + }, + }) + + const { app } = define({ + setup() { + const n0 = createComponent( + VaporTeleport, + { + to: () => target, + }, + { + default: () => createComponent(Comp), + }, + ) + const n1 = template('

root
')() + return [n0, n1] + }, + }).create() + + app.mount(root) + expect(target.innerHTML).toBe('

') + + app.unmount() + expect(target.innerHTML).toBe('') + }) + + test('descendent component should be unmounted when teleport is disabled and unmounted', async () => { + const root = document.createElement('div') + const beforeUnmount = vi.fn() + const unmounted = vi.fn() + const { component: Comp } = define({ + setup() { + onBeforeUnmount(beforeUnmount) + onUnmounted(unmounted) + return [template('

')(), template('

')()] + }, + }) + + const { app } = define({ + setup() { + const n0 = createComponent( + VaporTeleport, + { + to: () => null, + disabled: () => true, + }, + { + default: () => createComponent(Comp), + }, + ) + return [n0] + }, + }).create() + app.mount(root) + + expect(beforeUnmount).toHaveBeenCalledTimes(0) + expect(unmounted).toHaveBeenCalledTimes(0) + + app.unmount() + await nextTick() + expect(beforeUnmount).toHaveBeenCalledTimes(1) + expect(unmounted).toHaveBeenCalledTimes(1) + }) + + test('multiple teleport with same target', async () => { + const target = document.createElement('div') + const root = document.createElement('div') + + const child1 = shallowRef(template('

one
')()) + const child2 = shallowRef(template('two')()) + + const { mount } = define({ + setup() { + const n0 = template('
')() + setInsertionState(n0 as any) + createComponent( + VaporTeleport, + { + to: () => target, + }, + { + default: () => child1.value, + }, + ) ++ setInsertionState(n0 as any) + createComponent( + VaporTeleport, + { + to: () => target, + }, + { + default: () => child2.value, + }, + ) + return [n0] + }, + }).create() + mount(root) + expect(root.innerHTML).toBe('
') + expect(target.innerHTML).toBe('
one
two') + + // update existing content + child1.value = [ + template('
one
')(), + template('
two
')(), + ] as any + child2.value = [template('three')()] as any + await nextTick() + expect(target.innerHTML).toBe('
one
two
three') + + // toggling + child1.value = [] as any + await nextTick() + expect(root.innerHTML).toBe('
') + expect(target.innerHTML).toBe('three') + + // toggle back + child1.value = [ + template('
one
')(), + template('
two
')(), + ] as any + child2.value = [template('three')()] as any + await nextTick() + expect(root.innerHTML).toBe('
') + // should append + expect(target.innerHTML).toBe('
one
two
three') + + // toggle the other teleport + child2.value = [] as any + await nextTick() + expect(root.innerHTML).toBe('
') + expect(target.innerHTML).toBe('
one
two
') + }) + + test('should work when using template ref as target', async () => { + const root = document.createElement('div') + const target = ref(null) + const disabled = ref(true) + + const { mount } = define({ + setup() { + const setTemplateRef = createTemplateRefSetter() + const n0 = template('
')() as any + setTemplateRef(n0, target) + + const n1 = createComponent( + VaporTeleport, + { + to: () => target.value, + disabled: () => disabled.value, + }, + { + default: () => template('
teleported
')(), + }, + ) + return [n0, n1] + }, + }).create() + mount(root) + + expect(root.innerHTML).toBe( + '
teleported
', + ) + disabled.value = false + await nextTick() + expect(root.innerHTML).toBe( + '
teleported
', + ) + }) + + test('disabled', async () => { + const target = document.createElement('div') + const root = document.createElement('div') + + const disabled = ref(false) + const { mount } = define({ + setup() { + const n0 = createComponent( + VaporTeleport, + { + to: () => target, + disabled: () => disabled.value, + }, + { + default: () => template('
teleported
')(), + }, + ) + const n1 = template('
root
')() + return [n0, n1] + }, + }).create() + mount(root) + + expect(root.innerHTML).toBe('
root
') + expect(target.innerHTML).toBe('
teleported
') + + disabled.value = true + await nextTick() + expect(root.innerHTML).toBe( + '
teleported
root
', + ) + expect(target.innerHTML).toBe('') + + // toggle back + disabled.value = false + await nextTick() + expect(root.innerHTML).toBe( + '
root
', + ) + expect(target.innerHTML).toBe('
teleported
') + }) + + test(`the dir hooks of the Teleport's children should be called correctly`, async () => { + const target = document.createElement('div') + const root = document.createElement('div') + const toggle = ref(true) + + const spy = vi.fn() + const teardown = vi.fn() + const dir: VaporDirective = vi.fn((el, source) => { + spy() + return teardown + }) + + const { mount } = define({ + setup() { + return createComponent( + VaporTeleport, + { + to: () => target, + }, + { + default: () => { + return createIf( + () => toggle.value, + () => { + const n1 = template('
foo
')() as any + withVaporDirectives(n1, [[dir]]) + return n1 + }, + ) + }, + }, + ) + }, + }).create() + + mount(root) + expect(root.innerHTML).toBe('') + expect(target.innerHTML).toBe('
foo
') + expect(spy).toHaveBeenCalledTimes(1) + expect(teardown).not.toHaveBeenCalled() + + toggle.value = false + await nextTick() + expect(root.innerHTML).toBe('') + expect(target.innerHTML).toBe('') + expect(spy).toHaveBeenCalledTimes(1) + expect(teardown).toHaveBeenCalledTimes(1) + }) + + test(`ensure that target changes when disabled are updated correctly when enabled`, async () => { + const root = document.createElement('div') + const target1 = document.createElement('div') + const target2 = document.createElement('div') + const target3 = document.createElement('div') + const target = ref(target1) + const disabled = ref(true) + + const { mount } = define({ + setup() { + return createComponent( + VaporTeleport, + { + to: () => target.value, + disabled: () => disabled.value, + }, + { + default: () => template('
teleported
')(), + }, + ) + }, + }).create() + mount(root) + + disabled.value = false + await nextTick() + expect(target1.innerHTML).toBe('
teleported
') + expect(target2.innerHTML).toBe('') + expect(target3.innerHTML).toBe('') + + disabled.value = true + await nextTick() + target.value = target2 + await nextTick() + expect(target1.innerHTML).toBe('') + expect(target2.innerHTML).toBe('') + expect(target3.innerHTML).toBe('') + + target.value = target3 + await nextTick() + expect(target1.innerHTML).toBe('') + expect(target2.innerHTML).toBe('') + expect(target3.innerHTML).toBe('') + + disabled.value = false + await nextTick() + expect(target1.innerHTML).toBe('') + expect(target2.innerHTML).toBe('') + expect(target3.innerHTML).toBe('
teleported
') + }) + + test('toggle sibling node inside target node', async () => { + const root = document.createElement('div') + const show = ref(false) + const { mount } = define({ + setup() { + return createIf( + () => show.value, + () => { + return createComponent( + VaporTeleport, + { + to: () => root, + }, + { + default: () => template('
teleported
')(), + }, + ) + }, + () => { + return template('
foo
')() + }, + ) + }, + }).create() + + mount(root) + expect(root.innerHTML).toBe('
foo
') + + show.value = true + await nextTick() + expect(root.innerHTML).toBe('
teleported
') + + show.value = false + await nextTick() + expect(root.innerHTML).toBe('
foo
') + }) + + test('unmount previous sibling node inside target node', async () => { + const root = document.createElement('div') + const parentShow = ref(false) + const childShow = ref(true) + + const { component: Comp } = define({ + setup() { + return createComponent( + VaporTeleport, + { to: () => root }, + { + default: () => { + return template('
foo
')() + }, + }, + ) + }, + }) + + const { mount } = define({ + setup() { + return createIf( + () => parentShow.value, + () => + createIf( + () => childShow.value, + () => createComponent(Comp), + () => template('bar')(), + ), + () => template('foo')(), + ) + }, + }).create() + + mount(root) + expect(root.innerHTML).toBe('foo') + + parentShow.value = true + await nextTick() + expect(root.innerHTML).toBe( + '
foo
', + ) + + parentShow.value = false + await nextTick() + expect(root.innerHTML).toBe('foo') + }) + + test('accessing template refs inside teleport', async () => { + const target = document.createElement('div') + const tRef = ref() + let tRefInMounted + + const { mount } = define({ + setup() { + onMounted(() => { + tRefInMounted = tRef.value + }) + const n1 = createComponent( + VaporTeleport, + { + to: () => target, + }, + { + default: () => { + const setTemplateRef = createTemplateRefSetter() + const n0 = template('
teleported
')() as any + setTemplateRef(n0, tRef) + return n0 + }, + }, + ) + return n1 + }, + }).create() + mount(target) + + const child = target.children[0] + expect(child.outerHTML).toBe(`
teleported
`) + expect(tRefInMounted).toBe(child) + }) +} diff --cc packages/runtime-vapor/src/apiCreateDynamicComponent.ts index abdc1a1cf2,945e0f38d8..409d73d7df --- a/packages/runtime-vapor/src/apiCreateDynamicComponent.ts +++ b/packages/runtime-vapor/src/apiCreateDynamicComponent.ts @@@ -1,9 -1,15 +1,16 @@@ import { resolveDynamicComponent } from '@vue/runtime-dom' -import { DynamicFragment, type VaporFragment, insert } from './block' ++import { insert } from './block' import { createComponentWithFallback } from './component' import { renderEffect } from './renderEffect' import type { RawProps } from './componentProps' import type { RawSlots } from './componentSlots' + import { + insertionAnchor, + insertionParent, + resetInsertionState, + } from './insertionState' + import { isHydrating, locateHydrationNode } from './dom/hydration' +import { DynamicFragment, type VaporFragment } from './fragment' export function createDynamicComponent( getter: () => any, diff --cc packages/runtime-vapor/src/apiCreateFor.ts index ca976aa8cc,62529149ad..a0f780406c --- a/packages/runtime-vapor/src/apiCreateFor.ts +++ b/packages/runtime-vapor/src/apiCreateFor.ts @@@ -18,8 -25,11 +20,12 @@@ import type { DynamicSlot } from './com import { renderEffect } from './renderEffect' import { VaporVForFlags } from '../../shared/src/vaporFlags' import { isHydrating, locateHydrationNode } from './dom/hydration' - import { insertionAnchor, insertionParent } from './insertionState' +import { VaporFragment } from './fragment' + import { + insertionAnchor, + insertionParent, + resetInsertionState, + } from './insertionState' class ForBlock extends VaporFragment { scope: EffectScope | undefined diff --cc packages/runtime-vapor/src/apiCreateIf.ts index e83b251d06,f573a61b16..37f6077b0f --- a/packages/runtime-vapor/src/apiCreateIf.ts +++ b/packages/runtime-vapor/src/apiCreateIf.ts @@@ -1,8 -1,11 +1,12 @@@ -import { type Block, type BlockFn, DynamicFragment, insert } from './block' +import { type Block, type BlockFn, insert } from './block' import { isHydrating, locateHydrationNode } from './dom/hydration' - import { insertionAnchor, insertionParent } from './insertionState' + import { + insertionAnchor, + insertionParent, + resetInsertionState, + } from './insertionState' import { renderEffect } from './renderEffect' +import { DynamicFragment } from './fragment' export function createIf( condition: () => any, diff --cc packages/runtime-vapor/src/apiTemplateRef.ts index c5a6c5fb2b,d3f3cf7181..a03085422e --- a/packages/runtime-vapor/src/apiTemplateRef.ts +++ b/packages/runtime-vapor/src/apiTemplateRef.ts @@@ -20,6 -20,7 +20,7 @@@ import isString, remove, } from '@vue/shared' -import { DynamicFragment } from './block' ++import { DynamicFragment } from './fragment' export type NodeRef = string | Ref | ((ref: Element) => void) export type RefEl = Element | VaporComponentInstance diff --cc packages/runtime-vapor/src/component.ts index 672bb75dc1,af15133dbe..38054e710c --- a/packages/runtime-vapor/src/component.ts +++ b/packages/runtime-vapor/src/component.ts @@@ -59,8 -59,11 +59,13 @@@ import } from './componentSlots' import { hmrReload, hmrRerender } from './hmr' import { isHydrating, locateHydrationNode } from './dom/hydration' - import { insertionAnchor, insertionParent } from './insertionState' +import { isVaporTeleport } from './components/Teleport' + import { + insertionAnchor, + insertionParent, + resetInsertionState, + } from './insertionState' ++import { DynamicFragment } from './fragment' export { currentInstance } from '@vue/runtime-dom' diff --cc packages/runtime-vapor/src/componentSlots.ts index 3d17e5c0a5,100c99cdb8..2f8c3dd3ce --- a/packages/runtime-vapor/src/componentSlots.ts +++ b/packages/runtime-vapor/src/componentSlots.ts @@@ -4,9 -4,12 +4,13 @@@ import { rawPropsProxyHandlers } from ' import { currentInstance, isRef } from '@vue/runtime-dom' import type { LooseRawProps, VaporComponentInstance } from './component' import { renderEffect } from './renderEffect' - import { insertionAnchor, insertionParent } from './insertionState' + import { + insertionAnchor, + insertionParent, + resetInsertionState, + } from './insertionState' import { isHydrating, locateHydrationNode } from './dom/hydration' +import { DynamicFragment } from './fragment' export type RawSlots = Record & { $?: DynamicSlotSource[] diff --cc pnpm-lock.yaml index c72eaa1ab1,a8c6e9bb42..52d16261e9 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@@ -34,28 -34,28 +34,28 @@@ importers devDependencies: '@babel/parser': specifier: 'catalog:' - version: 7.26.10 + version: 7.27.5 '@babel/types': specifier: 'catalog:' - version: 7.26.10 + version: 7.27.6 '@rollup/plugin-alias': specifier: ^5.1.1 - version: 5.1.1(rollup@4.37.0) + version: 5.1.1(rollup@4.44.0) '@rollup/plugin-commonjs': specifier: ^28.0.3 - version: 28.0.3(rollup@4.37.0) + version: 28.0.6(rollup@4.44.0) '@rollup/plugin-json': specifier: ^6.1.0 - version: 6.1.0(rollup@4.37.0) + version: 6.1.0(rollup@4.44.0) '@rollup/plugin-node-resolve': specifier: ^16.0.1 - version: 16.0.1(rollup@4.37.0) + version: 16.0.1(rollup@4.44.0) '@rollup/plugin-replace': specifier: 5.0.4 - version: 5.0.4(rollup@4.37.0) + version: 5.0.4(rollup@4.44.0) '@swc/core': - specifier: ^1.11.12 - version: 1.11.12 + specifier: ^1.11.24 - version: 1.12.3 ++ version: 1.12.4 '@types/hash-sum': specifier: ^1.0.2 version: 1.0.2 @@@ -1297,75 -1288,71 +1288,71 @@@ packages cpu: [x64] os: [win32] - '@swc/core-darwin-arm64@1.11.12': - resolution: {integrity: sha512-x+iljeyIaVq7VCAy9pM0rqAb9GKA1cqDkqCxgFDxH3rcH+ykZa12vkDlTwysgkfLV8pr0KhCRHkwY+iAqPbO9g==} - '@swc/core-darwin-arm64@1.12.3': - resolution: {integrity: sha512-QCV9vQ/s27AMxm8j8MTDL/nDoiEMrANiENRrWnb0Fxvz/O39CajPVShp/W7HlOkzt1GYtUXPdQJpSKylugfrWw==} ++ '@swc/core-darwin-arm64@1.12.4': ++ resolution: {integrity: sha512-HihKfeitjZU2ab94Zf893sxzFryLKX0TweGsNXXOLNtkSMLw50auuYfpRM0BOL9/uXXtuCWgRIF6P030SAX5xQ==} engines: {node: '>=10'} cpu: [arm64] os: [darwin] - '@swc/core-darwin-x64@1.11.12': - resolution: {integrity: sha512-DwTXPdhJ/+scUR1iWttu3p0q8b5omF71xWFCw6UC99QBJQ4femmRtZNacgdiBkxZ5IbUlxd8m5UzMBc/+H5rWw==} - '@swc/core-darwin-x64@1.12.3': - resolution: {integrity: sha512-LylCMfzGhdvl5tyKaTT9ePetHUX7wSsST7hxWiHzS+cUMj7FnhcfdEr6kcNVT7y1RJn3fCvuv7T98ZB+T2q3HA==} ++ '@swc/core-darwin-x64@1.12.4': ++ resolution: {integrity: sha512-meYCXHyYb6RDdu2N5PNAf0EelyxPBFhRcVo4kBFLuvuNb0m6EUg///VWy8MUMXq9/s9uzGS9kJVXXdRdr/d6FA==} engines: {node: '>=10'} cpu: [x64] os: [darwin] - '@swc/core-linux-arm-gnueabihf@1.11.12': - resolution: {integrity: sha512-ls9b3lX2x3tnJKGn6zSDFK1ohdmdUkE6nwqrVmdzqAwr/Q5i2ij/dmkOFCloItc2PHNVtRGGsC4+FYSm1EBLjg==} - '@swc/core-linux-arm-gnueabihf@1.12.3': - resolution: {integrity: sha512-DQODb7S+q+pwQY41Azcavwb2rb4rGxP70niScRDxB9X68hHOM9D0w9fxzC+Nr3AHcPSmVJUYUIiq5h38O5hVgQ==} ++ '@swc/core-linux-arm-gnueabihf@1.12.4': ++ resolution: {integrity: sha512-szfDbf7mE8V64of0q/LSqbk+em+T+TD3uqnH40Z7Qu/aL8vi5CHgyLjWG2SLkLLpyjgkAUF6AKrupgnBYcC2NA==} engines: {node: '>=10'} cpu: [arm] os: [linux] - '@swc/core-linux-arm64-gnu@1.11.12': - resolution: {integrity: sha512-F0nMLl5kYbew5GjHq7B21poE5VOPgSsoQ0VEXd4Fji3rR0d0gLoK2r+JP92XmpRxAzdzpdak1DQczWMyf2BQAQ==} - '@swc/core-linux-arm64-gnu@1.12.3': - resolution: {integrity: sha512-nTxtJSq78AjeaQBueYImoFBs5j7qXbgOxtirpyt8jE29NQBd0VFzDzRBhkr6I9jq0hNiChgMkqBN4eUkEQjytg==} ++ '@swc/core-linux-arm64-gnu@1.12.4': ++ resolution: {integrity: sha512-n0IY76w+Scx8m3HIVRvLkoResuwsQgjDfAk9bxn99dq4leQO+mE0fkPl0Yw/1BIsPh+kxGfopIJH9zsZ1Z2YrA==} engines: {node: '>=10'} cpu: [arm64] os: [linux] - libc: [glibc] - '@swc/core-linux-arm64-musl@1.11.12': - resolution: {integrity: sha512-3dlHowBgYBgi23ZBSvFHe/tD3PowEhxfVAy08NckWBeaG/e4dyrYMhAiccfuy6jkDYXEF1L2DtpRtxGImxoaPg==} - '@swc/core-linux-arm64-musl@1.12.3': - resolution: {integrity: sha512-lBGvC5UgPSxqLr/y1NZxQhyRQ7nXy3/Ec1Z47YNXtqtpKiG1EcOGPyS0UZgwiYQkXqq8NBFMHnyHmpKnXTvRDA==} ++ '@swc/core-linux-arm64-musl@1.12.4': ++ resolution: {integrity: sha512-wE5jmFi5cEQyLy8WmCWmNwfKETrnzy2D8YNi/xpYWpLPWqPhcelpa6tswkfYlbsMmmOh7hQNoTba1QdGu0jvHQ==} engines: {node: '>=10'} cpu: [arm64] os: [linux] - libc: [musl] - '@swc/core-linux-x64-gnu@1.11.12': - resolution: {integrity: sha512-ToEWzLA5lXlYCbGNzMow6+uy4zhpXKQyFb3RHM8AYVb0n4pNPWvwF+8ybWDimeGBBaHJLgRQsUMuJ4NV6urSrA==} - '@swc/core-linux-x64-gnu@1.12.3': - resolution: {integrity: sha512-61wZ8hwxNYzBY9MCWB50v90ICzdIhOuPk1O1qXswz9AXw5O6iQStEBHQ1rozPkfQ/rmhepk0pOf/6LCwssJOwg==} ++ '@swc/core-linux-x64-gnu@1.12.4': ++ resolution: {integrity: sha512-6S50Xd/7ePjEwrXyHMxpKTZ+KBrgUwMA8hQPbArUOwH4S5vHBr51heL0iXbUkppn1bkSr0J0IbOove5hzn+iqQ==} engines: {node: '>=10'} cpu: [x64] os: [linux] - libc: [glibc] - '@swc/core-linux-x64-musl@1.11.12': - resolution: {integrity: sha512-N5xF+MDZr79e8gvVXX3YP1bMeaRL16Kst/R7bGUQvvCq1UGD86qMUtSr5KfCl0h5SNKP2YKtkN98HQLnGEikow==} - '@swc/core-linux-x64-musl@1.12.3': - resolution: {integrity: sha512-NNeBiTpCgWt80vumTKVoaj6Fa/ZjUcaNQNM7np3PIgB8EbuXfyztboV7vUxpkmD/lUgsk8GlEFYViHvo6VMefQ==} ++ '@swc/core-linux-x64-musl@1.12.4': ++ resolution: {integrity: sha512-hbYRyaHhC13vYKuGG5BrAG5fjjWEQFfQetuFp/4QKEoXDzdnabJoixxWTQACDL3m0JW32nJ+gUzsYIPtFYkwXg==} engines: {node: '>=10'} cpu: [x64] os: [linux] - libc: [musl] - '@swc/core-win32-arm64-msvc@1.11.12': - resolution: {integrity: sha512-/PYiyYWSQRtMoOamMfhAfq0y3RWk9LpUZ49yetJn2XI85TRkL5u2DTLLNkTPvoTiCfo0eZOJF9t5b7Z6ly0iHQ==} - '@swc/core-win32-arm64-msvc@1.12.3': - resolution: {integrity: sha512-fxraM7exaPb1/W0CoHW45EFNOQUQh0nonBEcNFm2iv095mziBwttyxZyQBoDkQocpkd5NtsZw3xW5FTBPnn+Vw==} ++ '@swc/core-win32-arm64-msvc@1.12.4': ++ resolution: {integrity: sha512-e6EbfjPL8GA/bb1lc9Omtxjlz+1ThTsAuBsy4Q3Kpbuh6B3jclg8KzxU/6t91v23wG593mieTyR5f3Pr7X3AWw==} engines: {node: '>=10'} cpu: [arm64] os: [win32] - '@swc/core-win32-ia32-msvc@1.11.12': - resolution: {integrity: sha512-Dxm6W4p0YVNIPnYh/Kf/9zPeaD6sVAGDQN+2c52l4m/4gR5aDgE+xg6k5lAt4ok7LDXInL3n1nwYEG7Tc4JcSQ==} - '@swc/core-win32-ia32-msvc@1.12.3': - resolution: {integrity: sha512-FFIhMPXIDjRcewomwbYGPvem7Fj76AsuzbRahnAyp+OzJwrrtxVmra/kyUCfj4kix7vdGByY0WvVfiVCf5b7Mg==} ++ '@swc/core-win32-ia32-msvc@1.12.4': ++ resolution: {integrity: sha512-RG2FzmllBTUf4EksANlIvLckcBrLZEA0t13LIa6L213UZKQfEuDNHezqESgoVhJMg2S/tWauitATOCFgZNSmjg==} engines: {node: '>=10'} cpu: [ia32] os: [win32] - '@swc/core-win32-x64-msvc@1.11.12': - resolution: {integrity: sha512-PP8RSJTcda5nUHJGkbKeQ20OC+L2LxcbjYpyha1OqIFyu/qWG9zMMYVaTLKJL7zsJ14pIM/mpS3u+CJARQ+Hzw==} - '@swc/core-win32-x64-msvc@1.12.3': - resolution: {integrity: sha512-Sf4iSg+IYT5AzFSDDmii08DfeKcvtkVxIuo+uS8BJMbiLjFNjgMkkVlBthknGyJcSK15ncg9248XjnM4jU8DZA==} ++ '@swc/core-win32-x64-msvc@1.12.4': ++ resolution: {integrity: sha512-oRHKnZlR83zaMeVUCmHENa4j5uNRAWbmEpjYbzRcfC45LPFNWKGWGAGERLx0u87XMUtTGqnVYxnBTHN/rzDHOw==} engines: {node: '>=10'} cpu: [x64] os: [win32] - '@swc/core@1.11.12': - resolution: {integrity: sha512-Jwx9JH1O6Vm7BS9AEPLlquJNSy6Lbt/kiJIlxSslDuBLeDJD13lXQfitvazqgRwGEHx1QmwEq8mc0OSristtRw==} - '@swc/core@1.12.3': - resolution: {integrity: sha512-c4NeXW8P3gPqcFwtm+4aH+F2Cj5KJLMiLaKhSj3mpv19glq+jmekomdktAw/VHyjsXlsmouOeNWrk8rVlkCRsg==} ++ '@swc/core@1.12.4': ++ resolution: {integrity: sha512-hn30ebV4njAn0NAUM+3a0qCF+MJgqTNSrfA/hUAbC6TVjOQy2OYGQwkUvCu/V7S2+rZxrUsTpKOnZ7qqECZV9Q==} engines: {node: '>=10'} peerDependencies: - '@swc/helpers': '*' + '@swc/helpers': '>=0.5.17' peerDependenciesMeta: '@swc/helpers': optional: true @@@ -4426,130 -4403,130 +4403,130 @@@ snapshots '@types/resolve': 1.20.2 deepmerge: 4.3.1 is-module: 1.0.0 - resolve: 1.22.8 + resolve: 1.22.10 optionalDependencies: - rollup: 4.37.0 + rollup: 4.44.0 - '@rollup/plugin-replace@5.0.4(rollup@4.37.0)': + '@rollup/plugin-replace@5.0.4(rollup@4.44.0)': dependencies: - '@rollup/pluginutils': 5.1.0(rollup@4.37.0) + '@rollup/pluginutils': 5.2.0(rollup@4.44.0) magic-string: 0.30.17 optionalDependencies: - rollup: 4.37.0 + rollup: 4.44.0 - '@rollup/pluginutils@5.1.0(rollup@4.37.0)': + '@rollup/pluginutils@5.2.0(rollup@4.44.0)': dependencies: - '@types/estree': 1.0.6 + '@types/estree': 1.0.8 estree-walker: 2.0.2 - picomatch: 2.3.1 + picomatch: 4.0.2 optionalDependencies: - rollup: 4.37.0 + rollup: 4.44.0 - '@rollup/rollup-android-arm-eabi@4.37.0': + '@rollup/rollup-android-arm-eabi@4.44.0': optional: true - '@rollup/rollup-android-arm64@4.37.0': + '@rollup/rollup-android-arm64@4.44.0': optional: true - '@rollup/rollup-darwin-arm64@4.37.0': + '@rollup/rollup-darwin-arm64@4.44.0': optional: true - '@rollup/rollup-darwin-x64@4.37.0': + '@rollup/rollup-darwin-x64@4.44.0': optional: true - '@rollup/rollup-freebsd-arm64@4.37.0': + '@rollup/rollup-freebsd-arm64@4.44.0': optional: true - '@rollup/rollup-freebsd-x64@4.37.0': + '@rollup/rollup-freebsd-x64@4.44.0': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.37.0': + '@rollup/rollup-linux-arm-gnueabihf@4.44.0': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.37.0': + '@rollup/rollup-linux-arm-musleabihf@4.44.0': optional: true - '@rollup/rollup-linux-arm64-gnu@4.37.0': + '@rollup/rollup-linux-arm64-gnu@4.44.0': optional: true - '@rollup/rollup-linux-arm64-musl@4.37.0': + '@rollup/rollup-linux-arm64-musl@4.44.0': optional: true - '@rollup/rollup-linux-loongarch64-gnu@4.37.0': + '@rollup/rollup-linux-loongarch64-gnu@4.44.0': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.37.0': + '@rollup/rollup-linux-powerpc64le-gnu@4.44.0': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.37.0': + '@rollup/rollup-linux-riscv64-gnu@4.44.0': optional: true - '@rollup/rollup-linux-riscv64-musl@4.37.0': + '@rollup/rollup-linux-riscv64-musl@4.44.0': optional: true - '@rollup/rollup-linux-s390x-gnu@4.37.0': + '@rollup/rollup-linux-s390x-gnu@4.44.0': optional: true - '@rollup/rollup-linux-x64-gnu@4.37.0': + '@rollup/rollup-linux-x64-gnu@4.44.0': optional: true - '@rollup/rollup-linux-x64-musl@4.37.0': + '@rollup/rollup-linux-x64-musl@4.44.0': optional: true - '@rollup/rollup-win32-arm64-msvc@4.37.0': + '@rollup/rollup-win32-arm64-msvc@4.44.0': optional: true - '@rollup/rollup-win32-ia32-msvc@4.37.0': + '@rollup/rollup-win32-ia32-msvc@4.44.0': optional: true - '@rollup/rollup-win32-x64-msvc@4.37.0': + '@rollup/rollup-win32-x64-msvc@4.44.0': optional: true - '@swc/core-darwin-arm64@1.11.12': - '@swc/core-darwin-arm64@1.12.3': ++ '@swc/core-darwin-arm64@1.12.4': optional: true - '@swc/core-darwin-x64@1.11.12': - '@swc/core-darwin-x64@1.12.3': ++ '@swc/core-darwin-x64@1.12.4': optional: true - '@swc/core-linux-arm-gnueabihf@1.11.12': - '@swc/core-linux-arm-gnueabihf@1.12.3': ++ '@swc/core-linux-arm-gnueabihf@1.12.4': optional: true - '@swc/core-linux-arm64-gnu@1.11.12': - '@swc/core-linux-arm64-gnu@1.12.3': ++ '@swc/core-linux-arm64-gnu@1.12.4': optional: true - '@swc/core-linux-arm64-musl@1.11.12': - '@swc/core-linux-arm64-musl@1.12.3': ++ '@swc/core-linux-arm64-musl@1.12.4': optional: true - '@swc/core-linux-x64-gnu@1.11.12': - '@swc/core-linux-x64-gnu@1.12.3': ++ '@swc/core-linux-x64-gnu@1.12.4': optional: true - '@swc/core-linux-x64-musl@1.11.12': - '@swc/core-linux-x64-musl@1.12.3': ++ '@swc/core-linux-x64-musl@1.12.4': optional: true - '@swc/core-win32-arm64-msvc@1.11.12': - '@swc/core-win32-arm64-msvc@1.12.3': ++ '@swc/core-win32-arm64-msvc@1.12.4': optional: true - '@swc/core-win32-ia32-msvc@1.11.12': - '@swc/core-win32-ia32-msvc@1.12.3': ++ '@swc/core-win32-ia32-msvc@1.12.4': optional: true - '@swc/core-win32-x64-msvc@1.11.12': - '@swc/core-win32-x64-msvc@1.12.3': ++ '@swc/core-win32-x64-msvc@1.12.4': optional: true - '@swc/core@1.11.12': - '@swc/core@1.12.3': ++ '@swc/core@1.12.4': dependencies: '@swc/counter': 0.1.3 - '@swc/types': 0.1.19 + '@swc/types': 0.1.23 optionalDependencies: - '@swc/core-darwin-arm64': 1.11.12 - '@swc/core-darwin-x64': 1.11.12 - '@swc/core-linux-arm-gnueabihf': 1.11.12 - '@swc/core-linux-arm64-gnu': 1.11.12 - '@swc/core-linux-arm64-musl': 1.11.12 - '@swc/core-linux-x64-gnu': 1.11.12 - '@swc/core-linux-x64-musl': 1.11.12 - '@swc/core-win32-arm64-msvc': 1.11.12 - '@swc/core-win32-ia32-msvc': 1.11.12 - '@swc/core-win32-x64-msvc': 1.11.12 - '@swc/core-darwin-arm64': 1.12.3 - '@swc/core-darwin-x64': 1.12.3 - '@swc/core-linux-arm-gnueabihf': 1.12.3 - '@swc/core-linux-arm64-gnu': 1.12.3 - '@swc/core-linux-arm64-musl': 1.12.3 - '@swc/core-linux-x64-gnu': 1.12.3 - '@swc/core-linux-x64-musl': 1.12.3 - '@swc/core-win32-arm64-msvc': 1.12.3 - '@swc/core-win32-ia32-msvc': 1.12.3 - '@swc/core-win32-x64-msvc': 1.12.3 ++ '@swc/core-darwin-arm64': 1.12.4 ++ '@swc/core-darwin-x64': 1.12.4 ++ '@swc/core-linux-arm-gnueabihf': 1.12.4 ++ '@swc/core-linux-arm64-gnu': 1.12.4 ++ '@swc/core-linux-arm64-musl': 1.12.4 ++ '@swc/core-linux-x64-gnu': 1.12.4 ++ '@swc/core-linux-x64-musl': 1.12.4 ++ '@swc/core-win32-arm64-msvc': 1.12.4 ++ '@swc/core-win32-ia32-msvc': 1.12.4 ++ '@swc/core-win32-x64-msvc': 1.12.4 '@swc/counter@0.1.3': {}