diff --git a/packages/compiler-dom/__tests__/transforms/__snapshots__/stringifyStatic.spec.ts.snap b/packages/compiler-dom/__tests__/transforms/__snapshots__/stringifyStatic.spec.ts.snap index 33fb37a58f9..57d880a03f6 100644 --- a/packages/compiler-dom/__tests__/transforms/__snapshots__/stringifyStatic.spec.ts.snap +++ b/packages/compiler-dom/__tests__/transforms/__snapshots__/stringifyStatic.spec.ts.snap @@ -1,5 +1,24 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html +exports[`stringify static html > should bail for elements with number values 1`] = ` +"const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue + +const _hoisted_1 = /*#__PURE__*/_createElementVNode("select", null, [ + /*#__PURE__*/_createElementVNode("option", { value: 1 }), + /*#__PURE__*/_createElementVNode("option", { value: 1 }), + /*#__PURE__*/_createElementVNode("option", { value: 1 }), + /*#__PURE__*/_createElementVNode("option", { value: 1 }), + /*#__PURE__*/_createElementVNode("option", { value: 1 }) +], -1 /* HOISTED */) +const _hoisted_2 = [ + _hoisted_1 +] + +return function render(_ctx, _cache) { + return (_openBlock(), _createElementBlock("div", null, _hoisted_2)) +}" +`; + exports[`stringify static html > should bail on bindings that are hoisted but not stringifiable 1`] = ` "const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue @@ -20,6 +39,19 @@ return function render(_ctx, _cache) { }" `; +exports[`stringify static html > should work for elements with string values 1`] = ` +"const { createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue + +const _hoisted_1 = /*#__PURE__*/_createStaticVNode("", 1) +const _hoisted_2 = [ + _hoisted_1 +] + +return function render(_ctx, _cache) { + return (_openBlock(), _createElementBlock("div", null, _hoisted_2)) +}" +`; + exports[`stringify static html > should work with bindings that are non-static but stringifiable 1`] = ` "const { createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue diff --git a/packages/compiler-dom/__tests__/transforms/stringifyStatic.spec.ts b/packages/compiler-dom/__tests__/transforms/stringifyStatic.spec.ts index b0eb515c254..67267c13dee 100644 --- a/packages/compiler-dom/__tests__/transforms/stringifyStatic.spec.ts +++ b/packages/compiler-dom/__tests__/transforms/stringifyStatic.spec.ts @@ -485,4 +485,51 @@ describe('stringify static html', () => { expect(code).toMatch(`text1`) expect(code).toMatchSnapshot() }) + + test('should work for elements with string values', () => { + const { ast, code } = compileWithStringify( + `${repeat( + ``, + StringifyThresholds.ELEMENT_WITH_BINDING_COUNT, + )}`, + ) + // should be optimized now + expect(ast.hoists).toMatchObject([ + { + type: NodeTypes.JS_CALL_EXPRESSION, + callee: CREATE_STATIC, + arguments: [ + JSON.stringify( + `${repeat( + ``, + StringifyThresholds.ELEMENT_WITH_BINDING_COUNT, + )}`, + ), + '1', + ], + }, + { + type: NodeTypes.JS_ARRAY_EXPRESSION, + }, + ]) + expect(code).toMatchSnapshot() + }) + + test('should bail for elements with number values', () => { + const { ast, code } = compileWithStringify( + `${repeat( + ``, + StringifyThresholds.ELEMENT_WITH_BINDING_COUNT, + )}`, + ) + expect(ast.hoists).toMatchObject([ + { + type: NodeTypes.VNODE_CALL, + }, + { + type: NodeTypes.JS_ARRAY_EXPRESSION, + }, + ]) + expect(code).toMatchSnapshot() + }) }) diff --git a/packages/compiler-dom/src/transforms/stringifyStatic.ts b/packages/compiler-dom/src/transforms/stringifyStatic.ts index a5ff770f4e8..5accb18283a 100644 --- a/packages/compiler-dom/src/transforms/stringifyStatic.ts +++ b/packages/compiler-dom/src/transforms/stringifyStatic.ts @@ -225,6 +225,19 @@ function analyzeNode(node: StringifiableNode): [number, number] | false { ) { return bail() } + if ( + p.arg && + p.arg.isStatic && + p.exp && + p.exp.ast && + p.exp.ast.type !== 'StringLiteral' && + node.ns === Namespaces.HTML + ) { + // cannot be safely stringified + if (node.tag === 'option' && p.arg.content === 'value') { + return bail() + } + } } } for (let i = 0; i < node.children.length; i++) {
text1