Explorar el Código

feat: implement error handling for v-html (#30)

Rizumu Ayaka hace 2 años
padre
commit
886d16f458

+ 15 - 1
packages/compiler-vapor/__tests__/__snapshots__/compile.test.ts.snap

@@ -30,7 +30,21 @@ export function render(_ctx) {
 }"
 `;
 
-exports[`compile > directives > v-html > no expression 1`] = `
+exports[`compile > directives > v-html > should raise error and ignore children when v-html is present 1`] = `
+"import { template as _template, children as _children, effect as _effect, setHtml as _setHtml } from 'vue/vapor';
+
+export function render(_ctx) {
+  const t0 = _template(\\"<div></div>\\")
+  const n0 = t0()
+  const { 0: [n1],} = _children(n0)
+  _effect(() => {
+    _setHtml(n1, undefined, test)
+  })
+  return n0
+}"
+`;
+
+exports[`compile > directives > v-html > should raise error if has no expression 1`] = `
 "import { template as _template, children as _children, setHtml as _setHtml } from 'vue/vapor';
 
 export function render(_ctx) {

+ 25 - 3
packages/compiler-vapor/__tests__/compile.test.ts

@@ -1,4 +1,9 @@
-import { type RootNode, BindingTypes, ErrorCodes } from '@vue/compiler-dom'
+import {
+  type RootNode,
+  BindingTypes,
+  ErrorCodes,
+  DOMErrorCodes,
+} from '@vue/compiler-dom'
 import { type CompilerOptions, compile as _compile } from '../src'
 
 function compile(template: string | RootNode, options: CompilerOptions = {}) {
@@ -133,9 +138,26 @@ describe('compile', () => {
         expect(code).matchSnapshot()
       })
 
-      test('no expression', async () => {
-        const code = await compile(`<div v-html></div>`)
+      test('should raise error and ignore children when v-html is present', async () => {
+        const onError = vi.fn()
+        const code = await compile(`<div v-html="test">hello</div>`, {
+          onError,
+        })
+        expect(code).matchSnapshot()
+        expect(onError.mock.calls).toMatchObject([
+          [{ code: DOMErrorCodes.X_V_HTML_WITH_CHILDREN }],
+        ])
+      })
+
+      test('should raise error if has no expression', async () => {
+        const onError = vi.fn()
+        const code = await compile(`<div v-html></div>`, {
+          onError,
+        })
         expect(code).matchSnapshot()
+        expect(onError.mock.calls).toMatchObject([
+          [{ code: DOMErrorCodes.X_V_HTML_NO_EXPRESSION }],
+        ])
       })
     })
 

+ 14 - 0
packages/compiler-vapor/src/transform.ts

@@ -14,6 +14,8 @@ import {
   defaultOnWarn,
   ErrorCodes,
   createCompilerError,
+  DOMErrorCodes,
+  createDOMCompilerError,
 } from '@vue/compiler-dom'
 import { EMPTY_OBJ, NOOP, isArray, isVoidTag } from '@vue/shared'
 import {
@@ -508,6 +510,18 @@ function transformProp(
       break
     }
     case 'html': {
+      if (!exp) {
+        ctx.options.onError(
+          createDOMCompilerError(DOMErrorCodes.X_V_HTML_NO_EXPRESSION, loc),
+        )
+      }
+      if (ctx.node.children.length) {
+        ctx.options.onError(
+          createDOMCompilerError(DOMErrorCodes.X_V_HTML_WITH_CHILDREN, loc),
+        )
+        ctx.node.children.length = 0
+      }
+
       ctx.registerEffect(
         [exp],
         [