]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
perf(vapor): use nthChild instead of nextn (#12847)
authoredison <daiwei521@126.com>
Wed, 12 Feb 2025 08:43:26 +0000 (16:43 +0800)
committerGitHub <noreply@github.com>
Wed, 12 Feb 2025 08:43:26 +0000 (16:43 +0800)
packages/compiler-vapor/__tests__/transforms/__snapshots__/transformChildren.spec.ts.snap
packages/compiler-vapor/__tests__/transforms/transformChildren.spec.ts
packages/compiler-vapor/src/generators/template.ts
packages/runtime-vapor/__tests__/dom/template.spec.ts
packages/runtime-vapor/src/dom/node.ts
packages/runtime-vapor/src/index.ts

index 373b0795bb1c87f61425cb008dd0a75462ccbc5a..215ab9036ecb0931e7c2d0b95dbde899d1175a98 100644 (file)
@@ -1,13 +1,13 @@
 // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
 
 exports[`compiler: children transform > children & sibling references 1`] = `
-"import { child as _child, nextn as _nextn, next as _next, createTextNode as _createTextNode, insert as _insert, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, template as _template } from 'vue';
+"import { child as _child, nthChild as _nthChild, next as _next, createTextNode as _createTextNode, insert as _insert, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, template as _template } from 'vue';
 const t0 = _template("<div><p> </p> <!><p> </p></div>", true)
 
 export function render(_ctx) {
   const n4 = t0()
   const n0 = _child(n4)
-  const n3 = _nextn(n0, 2)
+  const n3 = _nthChild(n4, 2)
   const n2 = _next(n3)
   const x0 = _child(n0)
   const n1 = _createTextNode()
@@ -22,6 +22,19 @@ export function render(_ctx) {
 }"
 `;
 
+exports[`compiler: children transform > efficient find 1`] = `
+"import { child as _child, nthChild as _nthChild, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("<div><div>x</div><div>x</div><div> </div></div>", true)
+
+export function render(_ctx) {
+  const n1 = t0()
+  const n0 = _nthChild(n1, 2)
+  const x0 = _child(n0)
+  _renderEffect(() => _setText(x0, _toDisplayString(_ctx.msg)))
+  return n1
+}"
+`;
+
 exports[`compiler: children transform > efficient traversal 1`] = `
 "import { child as _child, next as _next, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, template as _template } from 'vue';
 const t0 = _template("<div><div>x</div><div><span> </span></div><div><span> </span></div><div><span> </span></div></div>", true)
index 39b1da072900df1976665d38bf1c2e55a392c3f3..152911dcdfafbd9aa8f7d8faf8e53f096d562343 100644 (file)
@@ -46,4 +46,16 @@ describe('compiler: children transform', () => {
     )
     expect(code).toMatchSnapshot()
   })
+
+  test('efficient find', () => {
+    const { code } = compileWithElementTransform(
+      `<div>
+        <div>x</div>
+        <div>x</div>
+        <div>{{ msg }}</div>
+      </div>`,
+    )
+    expect(code).contains(`const n0 = _nthChild(n1, 2)`)
+    expect(code).toMatchSnapshot()
+  })
 })
index 68d4c20b3e46937fef531d340cc7489dbb21fbcb..0c27a919246dccaa755fdbd7e6ceffdc0309497e 100644 (file)
@@ -70,7 +70,7 @@ export function genChildren(
       if (offset === 1) {
         push(...genCall(helper('next'), prev[0]))
       } else {
-        push(...genCall(helper('nextn'), prev[0], String(offset)))
+        push(...genCall(helper('nthChild'), from, String(offset)))
       }
     } else {
       if (newPath.length === 1 && newPath[0] === 0) {
@@ -113,7 +113,7 @@ export function genChildren(
           if (i === 1) {
             init = genCall(helper('next'), init)
           } else if (i > 1) {
-            init = genCall(helper('nextn'), init, String(i))
+            init = genCall(helper('nthChild'), resolvedFrom, String(i))
           }
         }
         push(...init!)
index f34702362f8efa3aad053105c1a49503f325a701..85de30987a55e22b52dffda3fae163b0412e6fe1 100644 (file)
@@ -1,5 +1,5 @@
 import { template } from '../../src/dom/template'
-import { child, next, nextn } from '../../src/dom/node'
+import { child, next, nthChild } from '../../src/dom/node'
 
 describe('api: template', () => {
   test('create element', () => {
@@ -18,6 +18,17 @@ describe('api: template', () => {
     expect(root.$root).toBe(true)
   })
 
+  test('nthChild', () => {
+    const t = template('<div><span><b>nested</b></span><p></p></div>')
+    const root = t()
+    const span = nthChild(root, 0)
+    const b = nthChild(span, 0)
+    const p = nthChild(root, 1)
+    expect(span).toBe(root.firstChild)
+    expect(b).toBe(root.firstChild!.firstChild)
+    expect(p).toBe(root.firstChild!.nextSibling)
+  })
+
   test('next', () => {
     const t = template('<div><span></span><b></b><p></p></div>')
     const root = t()
@@ -26,7 +37,7 @@ describe('api: template', () => {
 
     expect(span).toBe(root.childNodes[0])
     expect(b).toBe(root.childNodes[1])
-    expect(nextn(span, 2)).toBe(root.childNodes[2])
+    expect(nthChild(root, 2)).toBe(root.childNodes[2])
     expect(next(b)).toBe(root.childNodes[2])
   })
 })
index f620acb63e1414eee3345ac2c0ce1758a4b230e3..83bc32c57f0b0eef5c82cc6da675e3a244ce3edb 100644 (file)
@@ -19,14 +19,11 @@ export function child(node: ParentNode): Node {
 }
 
 /*! #__NO_SIDE_EFFECTS__ */
-export function next(node: Node): Node {
-  return node.nextSibling!
+export function nthChild(node: Node, i: number): Node {
+  return node.childNodes[i]
 }
 
 /*! #__NO_SIDE_EFFECTS__ */
-export function nextn(node: Node, offset: number = 1): Node {
-  for (let i = 0; i < offset; i++) {
-    node = node.nextSibling!
-  }
-  return node
+export function next(node: Node): Node {
+  return node.nextSibling!
 }
index e4b78391604ae0b716362377e30e2494c650bd0d..40a847ba8f5833013a327bf27fd314e111f1b140 100644 (file)
@@ -10,7 +10,7 @@ export { createComponent, createComponentWithFallback } from './component'
 export { renderEffect } from './renderEffect'
 export { createSlot } from './componentSlots'
 export { template } from './dom/template'
-export { createTextNode, child, next, nextn } from './dom/node'
+export { createTextNode, child, nthChild, next } from './dom/node'
 export {
   setText,
   setHtml,