Przeglądaj źródła

test(compiler-vapor): reorganize expression cache tests

daiwei 3 miesięcy temu
rodzic
commit
3ef86bdad9

+ 427 - 20
packages/compiler-vapor/__tests__/transforms/__snapshots__/expression.spec.ts.snap

@@ -11,6 +11,433 @@ export function render(_ctx) {
 }"
 `;
 
+exports[`compiler: expression > cache expressions > TSNonNullExpression 1`] = `
+"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("<div>", true)
+
+export function render(_ctx) {
+  const n0 = t0()
+  _renderEffect(() => {
+    const _obj = _ctx.obj
+    _setProp(n0, "id", _obj!.foo + _obj!.bar)
+  })
+  return n0
+}"
+`;
+
+exports[`compiler: expression > cache expressions > cache variable used in both property shorthand and normal binding 1`] = `
+"import { setStyle as _setStyle, setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("<div>", true)
+
+export function render(_ctx) {
+  const n0 = t0()
+  _renderEffect(() => {
+    const _color = _ctx.color
+    _setStyle(n0, {color: _color})
+    _setProp(n0, "id", _color)
+  })
+  return n0
+}"
+`;
+
+exports[`compiler: expression > cache expressions > dynamic key bindings with expressions 1`] = `
+"import { setDynamicProps as _setDynamicProps, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("<div>", true)
+
+export function render(_ctx) {
+  const n0 = t0()
+  _renderEffect(() => {
+    const _key = _ctx.key
+    _setDynamicProps(n0, [{ [_key+1]: _ctx.foo[_key+1]() }])
+  })
+  return n0
+}"
+`;
+
+exports[`compiler: expression > cache expressions > dynamic property access 1`] = `
+"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("<div>", true)
+
+export function render(_ctx) {
+  const n0 = t0()
+  _renderEffect(() => {
+    const _obj = _ctx.obj
+    _setProp(n0, "id", _obj[1][_ctx.baz] + _obj.bar)
+  })
+  return n0
+}"
+`;
+
+exports[`compiler: expression > cache expressions > dynamic property access with parentheses 1`] = `
+"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("<div>", true)
+
+export function render(_ctx) {
+  const n0 = t0()
+  _renderEffect(() => {
+    const _foo_bar = _ctx.foo[_ctx.bar]
+    _setProp(n0, "x", (_foo_bar).x)
+    _setProp(n0, "bar", (_foo_bar))
+  })
+  return n0
+}"
+`;
+
+exports[`compiler: expression > cache expressions > function calls with arguments 1`] = `
+"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("<div>")
+
+export function render(_ctx) {
+  const n0 = t0()
+  const n1 = t0()
+  const n2 = t0()
+  _renderEffect(() => {
+    const _foo = _ctx.foo
+    const _bar = _ctx.bar
+    const _foo_bar_baz = _foo[_bar(_ctx.baz)]
+    _setProp(n0, "id", _foo_bar_baz)
+    _setProp(n1, "id", _foo_bar_baz)
+    _setProp(n2, "id", _bar() + _foo)
+  })
+  return [n0, n1, n2]
+}"
+`;
+
+exports[`compiler: expression > cache expressions > not cache variable and member expression with the same name 1`] = `
+"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("<div>", true)
+
+export function render(_ctx) {
+  const n0 = t0()
+  _renderEffect(() => _setProp(n0, "id", _ctx.bar + _ctx.obj.bar))
+  return n0
+}"
+`;
+
+exports[`compiler: expression > cache expressions > not cache variable in function expression 1`] = `
+"import { setDynamicProps as _setDynamicProps, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("<div>", true)
+
+export function render(_ctx) {
+  const n0 = t0()
+  _renderEffect(() => _setDynamicProps(n0, [{ foo: bar => _ctx.foo = bar }]))
+  return n0
+}"
+`;
+
+exports[`compiler: expression > cache expressions > not cache variable only used in property shorthand 1`] = `
+"import { setStyle as _setStyle, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("<div>", true)
+
+export function render(_ctx) {
+  const n0 = t0()
+  _renderEffect(() => _setStyle(n0, {color: _ctx.color}))
+  return n0
+}"
+`;
+
+exports[`compiler: expression > cache expressions > object property chain access 1`] = `
+"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("<div>")
+
+export function render(_ctx) {
+  const n0 = t0()
+  const n1 = t0()
+  _renderEffect(() => {
+    const _obj = _ctx.obj
+    const _obj_foo_baz_obj_bar = _obj['foo']['baz'] + _obj.bar
+    _setProp(n0, "id", _obj_foo_baz_obj_bar)
+    _setProp(n1, "id", _obj_foo_baz_obj_bar)
+  })
+  return [n0, n1]
+}"
+`;
+
+exports[`compiler: expression > cache expressions > object property name substring cases 1`] = `
+"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("<div>", true)
+
+export function render(_ctx) {
+  const n0 = t0()
+  _renderEffect(() => {
+    const _p = _ctx.p
+    const _p_title = _p.title
+    _setProp(n0, "id", _p_title + _p.titles + _p_title)
+  })
+  return n0
+}"
+`;
+
+exports[`compiler: expression > cache expressions > optional chaining 1`] = `
+"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("<div>", true)
+
+export function render(_ctx) {
+  const n0 = t0()
+  _renderEffect(() => {
+    const _obj = _ctx.obj
+    _setProp(n0, "id", _obj?.foo + _obj?.bar)
+  })
+  return n0
+}"
+`;
+
+exports[`compiler: expression > cache expressions > repeated expression in expressions 1`] = `
+"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("<div>")
+
+export function render(_ctx) {
+  const n0 = t0()
+  const n1 = t0()
+  const n2 = t0()
+  _renderEffect(() => {
+    const _foo = _ctx.foo
+    const _foo_bar = _foo + _ctx.bar
+    _setProp(n0, "id", _foo_bar)
+    _setProp(n1, "id", _foo_bar)
+    _setProp(n2, "id", _foo + _foo_bar)
+  })
+  return [n0, n1, n2]
+}"
+`;
+
+exports[`compiler: expression > cache expressions > repeated expressions 1`] = `
+"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("<div>")
+
+export function render(_ctx) {
+  const n0 = t0()
+  const n1 = t0()
+  _renderEffect(() => {
+    const _foo_bar = _ctx.foo + _ctx.bar
+    _setProp(n0, "id", _foo_bar)
+    _setProp(n1, "id", _foo_bar)
+  })
+  return [n0, n1]
+}"
+`;
+
+exports[`compiler: expression > cache expressions > repeated variable in expressions 1`] = `
+"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("<div>")
+
+export function render(_ctx) {
+  const n0 = t0()
+  const n1 = t0()
+  _renderEffect(() => {
+    const _foo = _ctx.foo
+    _setProp(n0, "id", _foo + _foo + _ctx.bar)
+    _setProp(n1, "id", _foo)
+  })
+  return [n0, n1]
+}"
+`;
+
+exports[`compiler: expression > cache expressions > repeated variables 1`] = `
+"import { setClass as _setClass, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("<div>")
+
+export function render(_ctx) {
+  const n0 = t0()
+  const n1 = t0()
+  _renderEffect(() => {
+    const _foo = _ctx.foo
+    _setClass(n0, _foo)
+    _setClass(n1, _foo)
+  })
+  return [n0, n1]
+}"
+`;
+
+exports[`compiler: expression > cache expressions > shared member root 1`] = `
+"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("<div>")
+
+export function render(_ctx) {
+  const n0 = t0()
+  const n1 = t0()
+  _renderEffect(() => {
+    const _foo = _ctx.foo
+    _setProp(n0, "id", _foo.bar)
+    _setProp(n1, "id", _foo.baz)
+  })
+  return [n0, n1]
+}"
+`;
+
+exports[`compiler: expression > cache expressions > shared member root with TSNonNullExpression 1`] = `
+"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("<div>")
+
+export function render(_ctx) {
+  const n0 = t0()
+  const n1 = t0()
+  _renderEffect(() => {
+    const _foo = _ctx.foo
+    _setProp(n0, "id", _foo!.bar)
+    _setProp(n1, "id", _foo!.baz)
+  })
+  return [n0, n1]
+}"
+`;
+
+exports[`compiler: expression > cache expressions > should cache method call with same arguments 1`] = `
+"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("<div>")
+
+export function render(_ctx) {
+  const n0 = t0()
+  const n1 = t0()
+  _renderEffect(() => {
+    const _msg_replace_1_2 = _ctx.msg.replace('1', '2')
+    _setProp(n0, "id", _msg_replace_1_2)
+    _setProp(n1, "id", _msg_replace_1_2)
+  })
+  return [n0, n1]
+}"
+`;
+
+exports[`compiler: expression > cache expressions > should cache optional call expression with same arguments 1`] = `
+"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("<div>")
+
+export function render(_ctx) {
+  const n0 = t0()
+  const n1 = t0()
+  _renderEffect(() => {
+    const _obj_foo_bar = _ctx.obj[_ctx.foo?.(_ctx.bar)]
+    _setProp(n0, "id", _obj_foo_bar)
+    _setProp(n1, "id", _obj_foo_bar)
+  })
+  return [n0, n1]
+}"
+`;
+
+exports[`compiler: expression > cache expressions > should not cache Date.now() call expressions 1`] = `
+"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("<div>")
+
+export function render(_ctx) {
+  const n0 = t0()
+  const n1 = t0()
+  _renderEffect(() => {
+    _setProp(n0, "id", Date.now())
+    _setProp(n1, "id", Date.now())
+  })
+  return [n0, n1]
+}"
+`;
+
+exports[`compiler: expression > cache expressions > should not cache globally allowed identifier as variable 1`] = `
+"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("<div>")
+
+export function render(_ctx) {
+  const n0 = t0()
+  const n1 = t0()
+  _renderEffect(() => {
+    _setProp(n0, "id", String(_ctx.foo))
+    _setProp(n1, "id", String(_ctx.bar))
+  })
+  return [n0, n1]
+}"
+`;
+
+exports[`compiler: expression > cache expressions > should not cache globally allowed identifier call expressions 1`] = `
+"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("<div>")
+
+export function render(_ctx) {
+  const n0 = t0()
+  const n1 = t0()
+  _renderEffect(() => {
+    _setProp(n0, "id", Math.random())
+    _setProp(n1, "id", Math.random())
+  })
+  return [n0, n1]
+}"
+`;
+
+exports[`compiler: expression > cache expressions > should not cache member expression containing globally allowed call 1`] = `
+"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("<div>")
+
+export function render(_ctx) {
+  const n0 = t0()
+  const n1 = t0()
+  _renderEffect(() => {
+    _setProp(n0, "id", _ctx.obj[Math.random()])
+    _setProp(n1, "id", _ctx.obj[Math.random()])
+  })
+  return [n0, n1]
+}"
+`;
+
+exports[`compiler: expression > cache expressions > should not cache method call with different arguments 1`] = `
+"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("<div>")
+
+export function render(_ctx) {
+  const n0 = t0()
+  const n1 = t0()
+  _renderEffect(() => {
+    const _msg = _ctx.msg
+    _setProp(n0, "id", _msg.replace('1', '2'))
+    _setProp(n1, "id", _msg.replace('1', '3'))
+  })
+  return [n0, n1]
+}"
+`;
+
+exports[`compiler: expression > cache expressions > should not cache mixed expression with globally allowed call 1`] = `
+"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("<div>")
+
+export function render(_ctx) {
+  const n0 = t0()
+  const n1 = t0()
+  _renderEffect(() => {
+    _setProp(n0, "id", Math.random() + _ctx.foo)
+    _setProp(n1, "id", Math.random() + _ctx.foo)
+  })
+  return [n0, n1]
+}"
+`;
+
+exports[`compiler: expression > cache expressions > should not cache update expression 1`] = `
+"import { child as _child, txt as _txt, setProp as _setProp, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("<div> ", true)
+
+export function render(_ctx) {
+  const n1 = t0()
+  const n0 = _child(n1)
+  const x1 = _txt(n1)
+  _renderEffect(() => {
+    const _foo = _ctx.foo
+    _setProp(n1, "id", String(_foo.id++))
+    _setProp(n1, "foo", _foo)
+    _setProp(n1, "bar", _ctx.bar++)
+    _setText(n0, _toDisplayString(String(_foo.id++)) + " " + _toDisplayString(_foo) + " " + _toDisplayString(_ctx.bar))
+    _setText(x1, _toDisplayString(String(_foo.id++)) + " " + _toDisplayString(_foo) + " " + _toDisplayString(_ctx.bar))
+  })
+  return n1
+}"
+`;
+
+exports[`compiler: expression > cache expressions > variable name substring edge cases 1`] = `
+"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("<div>", true)
+
+export function render(_ctx) {
+  const n0 = t0()
+  _renderEffect(() => {
+    const _title = _ctx.title
+    _setProp(n0, "id", _title + _ctx.titles + _title)
+  })
+  return n0
+}"
+`;
+
 exports[`compiler: expression > empty interpolation 1`] = `
 "import { template as _template } from 'vue';
 const t0 = _template(" ")
@@ -79,23 +506,3 @@ export function render(_ctx, $props, $emit, $attrs, $slots) {
   return n0
 }"
 `;
-
-exports[`compiler: expression > update expression 1`] = `
-"import { child as _child, txt as _txt, setProp as _setProp, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, template as _template } from 'vue';
-const t0 = _template("<div> ", true)
-
-export function render(_ctx) {
-  const n1 = t0()
-  const n0 = _child(n1)
-  const x1 = _txt(n1)
-  _renderEffect(() => {
-    const _foo = _ctx.foo
-    _setProp(n1, "id", String(_foo.id++))
-    _setProp(n1, "foo", _foo)
-    _setProp(n1, "bar", _ctx.bar++)
-    _setText(n0, _toDisplayString(String(_foo.id++)) + " " + _toDisplayString(_foo) + " " + _toDisplayString(_ctx.bar))
-    _setText(x1, _toDisplayString(String(_foo.id++)) + " " + _toDisplayString(_foo) + " " + _toDisplayString(_ctx.bar))
-  })
-  return n1
-}"
-`;

+ 0 - 407
packages/compiler-vapor/__tests__/transforms/__snapshots__/vBind.spec.ts.snap

@@ -1,412 +1,5 @@
 // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
 
-exports[`cache multiple access > TSNonNullExpression 1`] = `
-"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
-const t0 = _template("<div>", true)
-
-export function render(_ctx) {
-  const n0 = t0()
-  _renderEffect(() => {
-    const _obj = _ctx.obj
-    _setProp(n0, "id", _obj!.foo + _obj!.bar)
-  })
-  return n0
-}"
-`;
-
-exports[`cache multiple access > cache variable used in both property shorthand and normal binding 1`] = `
-"import { setStyle as _setStyle, setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
-const t0 = _template("<div>", true)
-
-export function render(_ctx) {
-  const n0 = t0()
-  _renderEffect(() => {
-    const _color = _ctx.color
-    _setStyle(n0, {color: _color})
-    _setProp(n0, "id", _color)
-  })
-  return n0
-}"
-`;
-
-exports[`cache multiple access > dynamic key bindings with expressions 1`] = `
-"import { setDynamicProps as _setDynamicProps, renderEffect as _renderEffect, template as _template } from 'vue';
-const t0 = _template("<div>", true)
-
-export function render(_ctx) {
-  const n0 = t0()
-  _renderEffect(() => {
-    const _key = _ctx.key
-    _setDynamicProps(n0, [{ [_key+1]: _ctx.foo[_key+1]() }])
-  })
-  return n0
-}"
-`;
-
-exports[`cache multiple access > dynamic property access 1`] = `
-"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
-const t0 = _template("<div>", true)
-
-export function render(_ctx) {
-  const n0 = t0()
-  _renderEffect(() => {
-    const _obj = _ctx.obj
-    _setProp(n0, "id", _obj[1][_ctx.baz] + _obj.bar)
-  })
-  return n0
-}"
-`;
-
-exports[`cache multiple access > dynamic property access with parentheses 1`] = `
-"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
-const t0 = _template("<div>", true)
-
-export function render(_ctx) {
-  const n0 = t0()
-  _renderEffect(() => {
-    const _foo_bar = _ctx.foo[_ctx.bar]
-    _setProp(n0, "x", (_foo_bar).x)
-    _setProp(n0, "bar", (_foo_bar))
-  })
-  return n0
-}"
-`;
-
-exports[`cache multiple access > function calls with arguments 1`] = `
-"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
-const t0 = _template("<div>")
-
-export function render(_ctx) {
-  const n0 = t0()
-  const n1 = t0()
-  const n2 = t0()
-  _renderEffect(() => {
-    const _foo = _ctx.foo
-    const _bar = _ctx.bar
-    const _foo_bar_baz = _foo[_bar(_ctx.baz)]
-    _setProp(n0, "id", _foo_bar_baz)
-    _setProp(n1, "id", _foo_bar_baz)
-    _setProp(n2, "id", _bar() + _foo)
-  })
-  return [n0, n1, n2]
-}"
-`;
-
-exports[`cache multiple access > not cache variable and member expression with the same name 1`] = `
-"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
-const t0 = _template("<div>", true)
-
-export function render(_ctx) {
-  const n0 = t0()
-  _renderEffect(() => _setProp(n0, "id", _ctx.bar + _ctx.obj.bar))
-  return n0
-}"
-`;
-
-exports[`cache multiple access > not cache variable in function expression 1`] = `
-"import { setDynamicProps as _setDynamicProps, renderEffect as _renderEffect, template as _template } from 'vue';
-const t0 = _template("<div>", true)
-
-export function render(_ctx) {
-  const n0 = t0()
-  _renderEffect(() => _setDynamicProps(n0, [{ foo: bar => _ctx.foo = bar }]))
-  return n0
-}"
-`;
-
-exports[`cache multiple access > not cache variable only used in property shorthand 1`] = `
-"import { setStyle as _setStyle, renderEffect as _renderEffect, template as _template } from 'vue';
-const t0 = _template("<div>", true)
-
-export function render(_ctx) {
-  const n0 = t0()
-  _renderEffect(() => _setStyle(n0, {color: _ctx.color}))
-  return n0
-}"
-`;
-
-exports[`cache multiple access > object property chain access 1`] = `
-"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
-const t0 = _template("<div>")
-
-export function render(_ctx) {
-  const n0 = t0()
-  const n1 = t0()
-  _renderEffect(() => {
-    const _obj = _ctx.obj
-    const _obj_foo_baz_obj_bar = _obj['foo']['baz'] + _obj.bar
-    _setProp(n0, "id", _obj_foo_baz_obj_bar)
-    _setProp(n1, "id", _obj_foo_baz_obj_bar)
-  })
-  return [n0, n1]
-}"
-`;
-
-exports[`cache multiple access > object property name substring cases 1`] = `
-"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
-const t0 = _template("<div>", true)
-
-export function render(_ctx) {
-  const n0 = t0()
-  _renderEffect(() => {
-    const _p = _ctx.p
-    const _p_title = _p.title
-    _setProp(n0, "id", _p_title + _p.titles + _p_title)
-  })
-  return n0
-}"
-`;
-
-exports[`cache multiple access > optional chaining 1`] = `
-"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
-const t0 = _template("<div>", true)
-
-export function render(_ctx) {
-  const n0 = t0()
-  _renderEffect(() => {
-    const _obj = _ctx.obj
-    _setProp(n0, "id", _obj?.foo + _obj?.bar)
-  })
-  return n0
-}"
-`;
-
-exports[`cache multiple access > repeated expression in expressions 1`] = `
-"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
-const t0 = _template("<div>")
-
-export function render(_ctx) {
-  const n0 = t0()
-  const n1 = t0()
-  const n2 = t0()
-  _renderEffect(() => {
-    const _foo = _ctx.foo
-    const _foo_bar = _foo + _ctx.bar
-    _setProp(n0, "id", _foo_bar)
-    _setProp(n1, "id", _foo_bar)
-    _setProp(n2, "id", _foo + _foo_bar)
-  })
-  return [n0, n1, n2]
-}"
-`;
-
-exports[`cache multiple access > repeated expressions 1`] = `
-"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
-const t0 = _template("<div>")
-
-export function render(_ctx) {
-  const n0 = t0()
-  const n1 = t0()
-  _renderEffect(() => {
-    const _foo_bar = _ctx.foo + _ctx.bar
-    _setProp(n0, "id", _foo_bar)
-    _setProp(n1, "id", _foo_bar)
-  })
-  return [n0, n1]
-}"
-`;
-
-exports[`cache multiple access > repeated variable in expressions 1`] = `
-"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
-const t0 = _template("<div>")
-
-export function render(_ctx) {
-  const n0 = t0()
-  const n1 = t0()
-  _renderEffect(() => {
-    const _foo = _ctx.foo
-    _setProp(n0, "id", _foo + _foo + _ctx.bar)
-    _setProp(n1, "id", _foo)
-  })
-  return [n0, n1]
-}"
-`;
-
-exports[`cache multiple access > repeated variables 1`] = `
-"import { setClass as _setClass, renderEffect as _renderEffect, template as _template } from 'vue';
-const t0 = _template("<div>")
-
-export function render(_ctx) {
-  const n0 = t0()
-  const n1 = t0()
-  _renderEffect(() => {
-    const _foo = _ctx.foo
-    _setClass(n0, _foo)
-    _setClass(n1, _foo)
-  })
-  return [n0, n1]
-}"
-`;
-
-exports[`cache multiple access > shared member root 1`] = `
-"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
-const t0 = _template("<div>")
-
-export function render(_ctx) {
-  const n0 = t0()
-  const n1 = t0()
-  _renderEffect(() => {
-    const _foo = _ctx.foo
-    _setProp(n0, "id", _foo.bar)
-    _setProp(n1, "id", _foo.baz)
-  })
-  return [n0, n1]
-}"
-`;
-
-exports[`cache multiple access > shared member root with TSNonNullExpression 1`] = `
-"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
-const t0 = _template("<div>")
-
-export function render(_ctx) {
-  const n0 = t0()
-  const n1 = t0()
-  _renderEffect(() => {
-    const _foo = _ctx.foo
-    _setProp(n0, "id", _foo!.bar)
-    _setProp(n1, "id", _foo!.baz)
-  })
-  return [n0, n1]
-}"
-`;
-
-exports[`cache multiple access > should cache method call with same arguments 1`] = `
-"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
-const t0 = _template("<div>")
-
-export function render(_ctx) {
-  const n0 = t0()
-  const n1 = t0()
-  _renderEffect(() => {
-    const _msg_replace_1_2 = _ctx.msg.replace('1', '2')
-    _setProp(n0, "id", _msg_replace_1_2)
-    _setProp(n1, "id", _msg_replace_1_2)
-  })
-  return [n0, n1]
-}"
-`;
-
-exports[`cache multiple access > should cache optional call expression with same arguments 1`] = `
-"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
-const t0 = _template("<div>")
-
-export function render(_ctx) {
-  const n0 = t0()
-  const n1 = t0()
-  _renderEffect(() => {
-    const _obj_foo_bar = _ctx.obj[_ctx.foo?.(_ctx.bar)]
-    _setProp(n0, "id", _obj_foo_bar)
-    _setProp(n1, "id", _obj_foo_bar)
-  })
-  return [n0, n1]
-}"
-`;
-
-exports[`cache multiple access > should not cache Date.now() call expressions 1`] = `
-"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
-const t0 = _template("<div>")
-
-export function render(_ctx) {
-  const n0 = t0()
-  const n1 = t0()
-  _renderEffect(() => {
-    _setProp(n0, "id", Date.now())
-    _setProp(n1, "id", Date.now())
-  })
-  return [n0, n1]
-}"
-`;
-
-exports[`cache multiple access > should not cache globally allowed identifier as variable 1`] = `
-"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
-const t0 = _template("<div>")
-
-export function render(_ctx) {
-  const n0 = t0()
-  const n1 = t0()
-  _renderEffect(() => {
-    _setProp(n0, "id", String(_ctx.foo))
-    _setProp(n1, "id", String(_ctx.bar))
-  })
-  return [n0, n1]
-}"
-`;
-
-exports[`cache multiple access > should not cache globally allowed identifier call expressions 1`] = `
-"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
-const t0 = _template("<div>")
-
-export function render(_ctx) {
-  const n0 = t0()
-  const n1 = t0()
-  _renderEffect(() => {
-    _setProp(n0, "id", Math.random())
-    _setProp(n1, "id", Math.random())
-  })
-  return [n0, n1]
-}"
-`;
-
-exports[`cache multiple access > should not cache member expression containing globally allowed call 1`] = `
-"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
-const t0 = _template("<div>")
-
-export function render(_ctx) {
-  const n0 = t0()
-  const n1 = t0()
-  _renderEffect(() => {
-    _setProp(n0, "id", _ctx.obj[Math.random()])
-    _setProp(n1, "id", _ctx.obj[Math.random()])
-  })
-  return [n0, n1]
-}"
-`;
-
-exports[`cache multiple access > should not cache method call with different arguments 1`] = `
-"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
-const t0 = _template("<div>")
-
-export function render(_ctx) {
-  const n0 = t0()
-  const n1 = t0()
-  _renderEffect(() => {
-    const _msg = _ctx.msg
-    _setProp(n0, "id", _msg.replace('1', '2'))
-    _setProp(n1, "id", _msg.replace('1', '3'))
-  })
-  return [n0, n1]
-}"
-`;
-
-exports[`cache multiple access > should not cache mixed expression with globally allowed call 1`] = `
-"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
-const t0 = _template("<div>")
-
-export function render(_ctx) {
-  const n0 = t0()
-  const n1 = t0()
-  _renderEffect(() => {
-    _setProp(n0, "id", Math.random() + _ctx.foo)
-    _setProp(n1, "id", Math.random() + _ctx.foo)
-  })
-  return [n0, n1]
-}"
-`;
-
-exports[`cache multiple access > variable name substring edge cases 1`] = `
-"import { setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
-const t0 = _template("<div>", true)
-
-export function render(_ctx) {
-  const n0 = t0()
-  _renderEffect(() => {
-    const _title = _ctx.title
-    _setProp(n0, "id", _title + _ctx.titles + _title)
-  })
-  return n0
-}"
-`;
-
 exports[`compiler v-bind > .attr modifier 1`] = `
 "import { setAttr as _setAttr, renderEffect as _renderEffect, template as _template } from 'vue';
 const t0 = _template("<div>", true)

+ 287 - 10
packages/compiler-vapor/__tests__/transforms/expression.spec.ts

@@ -38,16 +38,6 @@ describe('compiler: expression', () => {
     expect(code).contains(`$props['bar']`)
   })
 
-  test('update expression', () => {
-    const { code } = compileWithExpression(`
-      <div :id="String(foo.id++)" :foo="foo" :bar="bar++">
-        {{ String(foo.id++) }} {{ foo }} {{ bar }}
-      </div>
-    `)
-    expect(code).toMatchSnapshot()
-    expect(code).contains(`String(_foo.id++)`)
-  })
-
   test('empty interpolation', () => {
     const { code } = compileWithExpression(`{{}}`)
     const { code: code2 } = compileWithExpression(`{{ }}`)
@@ -68,4 +58,291 @@ describe('compiler: expression', () => {
 
     expect(code4).toMatchSnapshot()
   })
+
+  describe('cache expressions', () => {
+    test('should not cache update expression', () => {
+      const { code } = compileWithExpression(`
+        <div :id="String(foo.id++)" :foo="foo" :bar="bar++">
+          {{ String(foo.id++) }} {{ foo }} {{ bar }}
+        </div>
+      `)
+      expect(code).toMatchSnapshot()
+      expect(code).contains(`String(_foo.id++)`)
+    })
+
+    test('repeated variables', () => {
+      const { code } = compileWithExpression(`
+        <div :class="foo"></div>
+        <div :class="foo"></div>
+      `)
+      expect(code).matchSnapshot()
+      expect(code).contains('const _foo = _ctx.foo')
+      expect(code).contains('setClass(n0, _foo)')
+      expect(code).contains('setClass(n1, _foo)')
+    })
+
+    test('repeated expressions', () => {
+      const { code } = compileWithExpression(`
+        <div :id="foo + bar"></div>
+        <div :id="foo + bar"></div>
+      `)
+      expect(code).matchSnapshot()
+      expect(code).contains('const _foo_bar = _ctx.foo + _ctx.bar')
+      expect(code).contains('_setProp(n0, "id", _foo_bar)')
+      expect(code).contains('_setProp(n1, "id", _foo_bar)')
+    })
+
+    test('repeated variable in expressions', () => {
+      const { code } = compileWithExpression(`
+        <div :id="foo + foo + bar"></div>
+        <div :id="foo"></div>
+      `)
+      expect(code).matchSnapshot()
+      expect(code).contains('const _foo = _ctx.foo')
+      expect(code).contains('_setProp(n0, "id", _foo + _foo + _ctx.bar)')
+      expect(code).contains('_setProp(n1, "id", _foo)')
+    })
+
+    test('repeated expression in expressions', () => {
+      const { code } = compileWithExpression(`
+        <div :id="foo + bar"></div>
+        <div :id="foo + bar"></div>
+        <div :id="foo + foo + bar"></div>
+      `)
+      expect(code).matchSnapshot()
+      expect(code).contains('const _foo_bar = _foo + _ctx.bar')
+      expect(code).contains('_setProp(n0, "id", _foo_bar)')
+      expect(code).contains('_setProp(n2, "id", _foo + _foo_bar)')
+    })
+
+    test('function calls with arguments', () => {
+      const { code } = compileWithExpression(`
+        <div :id="foo[bar(baz)]"></div>
+        <div :id="foo[bar(baz)]"></div>
+        <div :id="bar() + foo"></div>
+      `)
+      expect(code).matchSnapshot()
+      expect(code).contains('const _foo_bar_baz = _foo[_bar(_ctx.baz)]')
+      expect(code).contains('_setProp(n0, "id", _foo_bar_baz)')
+      expect(code).contains('_setProp(n1, "id", _foo_bar_baz)')
+      expect(code).contains('_setProp(n2, "id", _bar() + _foo)')
+    })
+
+    test('dynamic key bindings with expressions', () => {
+      const { code } = compileWithExpression(`
+        <div :[key+1]="foo[key+1]()" />
+      `)
+      expect(code).matchSnapshot()
+      expect(code).contains('const _key = _ctx.key')
+      expect(code).contains('[{ [_key+1]: _ctx.foo[_key+1]() }]')
+    })
+
+    test('object property chain access', () => {
+      const { code } = compileWithExpression(`
+        <div :id="obj['foo']['baz'] + obj.bar"></div>
+        <div :id="obj['foo']['baz'] + obj.bar"></div>
+      `)
+      expect(code).matchSnapshot()
+      expect(code).contains(
+        "const _obj_foo_baz_obj_bar = _obj['foo']['baz'] + _obj.bar",
+      )
+      expect(code).contains('_setProp(n0, "id", _obj_foo_baz_obj_bar)')
+      expect(code).contains('_setProp(n1, "id", _obj_foo_baz_obj_bar)')
+    })
+
+    test('dynamic property access', () => {
+      const { code } = compileWithExpression(`
+        <div :id="obj[1][baz] + obj.bar"></div>
+      `)
+      expect(code).matchSnapshot()
+      expect(code).contains('const _obj = _ctx.obj')
+      expect(code).contains('_setProp(n0, "id", _obj[1][_ctx.baz] + _obj.bar)')
+    })
+
+    test('dynamic property access with parentheses', () => {
+      const { code } = compileWithExpression(`
+        <div :x="(foo[bar]).x" :bar="(foo[bar])"></div>
+      `)
+      expect(code).matchSnapshot()
+      expect(code).contains('const _foo_bar = _ctx.foo[_ctx.bar]')
+      expect(code).contains('_setProp(n0, "x", (_foo_bar).x)')
+      expect(code).contains('_setProp(n0, "bar", (_foo_bar))')
+    })
+
+    test('variable name substring edge cases', () => {
+      const { code } = compileWithExpression(
+        `<div :id="title + titles + title"></div>`,
+      )
+      expect(code).matchSnapshot()
+      expect(code).contains('const _title = _ctx.title')
+      expect(code).contains('_setProp(n0, "id", _title + _ctx.titles + _title)')
+    })
+
+    test('object property name substring cases', () => {
+      const { code } = compileWithExpression(
+        `<div :id="p.title + p.titles + p.title"></div>`,
+      )
+      expect(code).matchSnapshot()
+      expect(code).contains('const _p = _ctx.p')
+      expect(code).contains('const _p_title = _p.title')
+      expect(code).contains(
+        '_setProp(n0, "id", _p_title + _p.titles + _p_title)',
+      )
+    })
+
+    test('cache variable used in both property shorthand and normal binding', () => {
+      const { code } = compileWithExpression(`
+        <div :style="{color}" :id="color"/>
+      `)
+      expect(code).matchSnapshot()
+      expect(code).contains('const _color = _ctx.color')
+      expect(code).contains('_setStyle(n0, {color: _color})')
+    })
+
+    test('optional chaining', () => {
+      const { code } = compileWithExpression(
+        `<div :id="obj?.foo + obj?.bar"></div>`,
+      )
+      expect(code).matchSnapshot()
+      expect(code).contains('const _obj = _ctx.obj')
+      expect(code).contains('_setProp(n0, "id", _obj?.foo + _obj?.bar)')
+    })
+
+    test('TSNonNullExpression', () => {
+      const { code } = compileWithExpression(
+        `<div :id="obj!.foo + obj!.bar"></div>`,
+      )
+      expect(code).matchSnapshot()
+      expect(code).contains('const _obj = _ctx.obj')
+      expect(code).contains('_setProp(n0, "id", _obj!.foo + _obj!.bar)')
+    })
+
+    test('shared member root', () => {
+      const { code } = compileWithExpression(`
+        <div :id="foo.bar"></div>
+        <div :id="foo.baz"></div>
+      `)
+      expect(code).matchSnapshot()
+      expect(code).contains('const _foo = _ctx.foo')
+      expect(code).contains('_setProp(n0, "id", _foo.bar)')
+      expect(code).contains('_setProp(n1, "id", _foo.baz)')
+    })
+
+    test('shared member root with TSNonNullExpression', () => {
+      const { code } = compileWithExpression(`
+        <div :id="foo!.bar"></div>
+        <div :id="foo!.baz"></div>
+      `)
+      expect(code).matchSnapshot()
+      expect(code).contains('const _foo = _ctx.foo')
+      expect(code).contains('_setProp(n0, "id", _foo!.bar)')
+      expect(code).contains('_setProp(n1, "id", _foo!.baz)')
+    })
+
+    test('not cache variable only used in property shorthand', () => {
+      const { code } = compileWithExpression(`
+        <div :style="{color}" />
+      `)
+      expect(code).matchSnapshot()
+      expect(code).not.contains('const _color = _ctx.color')
+    })
+
+    test('not cache variable and member expression with the same name', () => {
+      const { code } = compileWithExpression(`
+        <div :id="bar + obj.bar"></div>
+      `)
+      expect(code).matchSnapshot()
+      expect(code).not.contains('const _bar = _ctx.bar')
+    })
+
+    test('not cache variable in function expression', () => {
+      const { code } = compileWithExpression(`
+        <div v-bind="{ foo: bar => foo = bar }"></div>
+      `)
+      expect(code).matchSnapshot()
+      expect(code).not.contains('const _bar = _ctx.bar')
+    })
+
+    test('should not cache method call with different arguments', () => {
+      const { code } = compileWithExpression(`
+        <div :id="msg.replace('1', '2')"></div>
+        <div :id="msg.replace('1', '3')"></div>
+      `)
+      expect(code).matchSnapshot()
+      expect(code).contains('const _msg = _ctx.msg')
+      expect(code).not.contains('_ctx.msg.replace')
+    })
+
+    test('should cache method call with same arguments', () => {
+      const { code } = compileWithExpression(`
+        <div :id="msg.replace('1', '2')"></div>
+        <div :id="msg.replace('1', '2')"></div>
+      `)
+      expect(code).matchSnapshot()
+      expect(code).contains(
+        `const _msg_replace_1_2 = _ctx.msg.replace('1', '2')`,
+      )
+      expect(code).not.contains('const _msg = _ctx.msg')
+    })
+
+    test('should cache optional call expression with same arguments', () => {
+      const { code } = compileWithExpression(`
+        <div :id="obj[foo?.(bar)]"></div>
+        <div :id="obj[foo?.(bar)]"></div>
+      `)
+      expect(code).matchSnapshot()
+      expect(code).contains(
+        `const _obj_foo_bar = _ctx.obj[_ctx.foo?.(_ctx.bar)]`,
+      )
+    })
+
+    test('should not cache globally allowed identifier call expressions', () => {
+      const { code } = compileWithExpression(`
+        <div :id="Math.random()"></div>
+        <div :id="Math.random()"></div>
+      `)
+      expect(code).matchSnapshot()
+      expect(code).not.contains('const _Math')
+      expect(code).contains('Math.random()')
+    })
+
+    test('should not cache Date.now() call expressions', () => {
+      const { code } = compileWithExpression(`
+        <div :id="Date.now()"></div>
+        <div :id="Date.now()"></div>
+      `)
+      expect(code).matchSnapshot()
+      expect(code).not.contains('const _Date')
+      expect(code).contains('Date.now()')
+    })
+
+    test('should not cache mixed expression with globally allowed call', () => {
+      const { code } = compileWithExpression(`
+        <div :id="Math.random() + foo"></div>
+        <div :id="Math.random() + foo"></div>
+      `)
+      expect(code).matchSnapshot()
+      expect(code).not.contains('const _Math_random')
+      expect(code).contains('Math.random()')
+    })
+
+    test('should not cache globally allowed identifier as variable', () => {
+      const { code } = compileWithExpression(`
+        <div :id="String(foo)"></div>
+        <div :id="String(bar)"></div>
+      `)
+      expect(code).matchSnapshot()
+      expect(code).not.contains('const _String = String')
+    })
+
+    test('should not cache member expression containing globally allowed call', () => {
+      const { code } = compileWithExpression(`
+        <div :id="obj[Math.random()]"></div>
+        <div :id="obj[Math.random()]"></div>
+      `)
+      expect(code).matchSnapshot()
+      expect(code).not.contains('const _obj_Math_random')
+      expect(code).contains('Math.random()')
+    })
+  })
 })

+ 0 - 269
packages/compiler-vapor/__tests__/transforms/vBind.spec.ts

@@ -775,272 +775,3 @@ describe('compiler v-bind', () => {
     expect(code).matchSnapshot()
   })
 })
-
-describe('cache multiple access', () => {
-  test('repeated variables', () => {
-    const { code } = compileWithVBind(`
-        <div :class="foo"></div>
-        <div :class="foo"></div>
-      `)
-    expect(code).matchSnapshot()
-    expect(code).contains('const _foo = _ctx.foo')
-    expect(code).contains('setClass(n0, _foo)')
-    expect(code).contains('setClass(n1, _foo)')
-  })
-
-  test('repeated expressions', () => {
-    const { code } = compileWithVBind(`
-        <div :id="foo + bar"></div>
-        <div :id="foo + bar"></div>
-      `)
-    expect(code).matchSnapshot()
-    expect(code).contains('const _foo_bar = _ctx.foo + _ctx.bar')
-    expect(code).contains('_setProp(n0, "id", _foo_bar)')
-    expect(code).contains('_setProp(n1, "id", _foo_bar)')
-  })
-
-  test('repeated variable in expressions', () => {
-    const { code } = compileWithVBind(`
-        <div :id="foo + foo + bar"></div>
-        <div :id="foo"></div>
-      `)
-    expect(code).matchSnapshot()
-    expect(code).contains('const _foo = _ctx.foo')
-    expect(code).contains('_setProp(n0, "id", _foo + _foo + _ctx.bar)')
-    expect(code).contains('_setProp(n1, "id", _foo)')
-  })
-
-  test('repeated expression in expressions', () => {
-    const { code } = compileWithVBind(`
-        <div :id="foo + bar"></div>
-        <div :id="foo + bar"></div>
-        <div :id="foo + foo + bar"></div>
-      `)
-    expect(code).matchSnapshot()
-    expect(code).contains('const _foo_bar = _foo + _ctx.bar')
-    expect(code).contains('_setProp(n0, "id", _foo_bar)')
-    expect(code).contains('_setProp(n2, "id", _foo + _foo_bar)')
-  })
-
-  test('function calls with arguments', () => {
-    const { code } = compileWithVBind(`
-        <div :id="foo[bar(baz)]"></div>
-        <div :id="foo[bar(baz)]"></div>
-        <div :id="bar() + foo"></div>
-      `)
-    expect(code).matchSnapshot()
-    expect(code).contains('const _foo_bar_baz = _foo[_bar(_ctx.baz)]')
-    expect(code).contains('_setProp(n0, "id", _foo_bar_baz)')
-    expect(code).contains('_setProp(n1, "id", _foo_bar_baz)')
-    expect(code).contains('_setProp(n2, "id", _bar() + _foo)')
-  })
-
-  test('dynamic key bindings with expressions', () => {
-    const { code } = compileWithVBind(`
-        <div :[key+1]="foo[key+1]()" />
-      `)
-    expect(code).matchSnapshot()
-    expect(code).contains('const _key = _ctx.key')
-    expect(code).contains('[{ [_key+1]: _ctx.foo[_key+1]() }]')
-  })
-
-  test('object property chain access', () => {
-    const { code } = compileWithVBind(`
-        <div :id="obj['foo']['baz'] + obj.bar"></div>
-        <div :id="obj['foo']['baz'] + obj.bar"></div>
-      `)
-    expect(code).matchSnapshot()
-    expect(code).contains(
-      "const _obj_foo_baz_obj_bar = _obj['foo']['baz'] + _obj.bar",
-    )
-    expect(code).contains('_setProp(n0, "id", _obj_foo_baz_obj_bar)')
-    expect(code).contains('_setProp(n1, "id", _obj_foo_baz_obj_bar)')
-  })
-
-  test('dynamic property access', () => {
-    const { code } = compileWithVBind(`
-        <div :id="obj[1][baz] + obj.bar"></div>
-      `)
-    expect(code).matchSnapshot()
-    expect(code).contains('const _obj = _ctx.obj')
-    expect(code).contains('_setProp(n0, "id", _obj[1][_ctx.baz] + _obj.bar)')
-  })
-
-  test('dynamic property access with parentheses', () => {
-    const { code } = compileWithVBind(`
-        <div :x="(foo[bar]).x" :bar="(foo[bar])"></div>
-      `)
-    expect(code).matchSnapshot()
-    expect(code).contains('const _foo_bar = _ctx.foo[_ctx.bar]')
-    expect(code).contains('_setProp(n0, "x", (_foo_bar).x)')
-    expect(code).contains('_setProp(n0, "bar", (_foo_bar))')
-  })
-
-  test('variable name substring edge cases', () => {
-    const { code } = compileWithVBind(
-      `<div :id="title + titles + title"></div>`,
-    )
-    expect(code).matchSnapshot()
-    expect(code).contains('const _title = _ctx.title')
-    expect(code).contains('_setProp(n0, "id", _title + _ctx.titles + _title)')
-  })
-
-  test('object property name substring cases', () => {
-    const { code } = compileWithVBind(
-      `<div :id="p.title + p.titles + p.title"></div>`,
-    )
-    expect(code).matchSnapshot()
-    expect(code).contains('const _p = _ctx.p')
-    expect(code).contains('const _p_title = _p.title')
-    expect(code).contains('_setProp(n0, "id", _p_title + _p.titles + _p_title)')
-  })
-
-  test('cache variable used in both property shorthand and normal binding', () => {
-    const { code } = compileWithVBind(`
-        <div :style="{color}" :id="color"/>
-      `)
-    expect(code).matchSnapshot()
-    expect(code).contains('const _color = _ctx.color')
-    expect(code).contains('_setStyle(n0, {color: _color})')
-  })
-
-  test('optional chaining', () => {
-    const { code } = compileWithVBind(`<div :id="obj?.foo + obj?.bar"></div>`)
-    expect(code).matchSnapshot()
-    expect(code).contains('const _obj = _ctx.obj')
-    expect(code).contains('_setProp(n0, "id", _obj?.foo + _obj?.bar)')
-  })
-
-  test('TSNonNullExpression', () => {
-    const { code } = compileWithVBind(`<div :id="obj!.foo + obj!.bar"></div>`)
-    expect(code).matchSnapshot()
-    expect(code).contains('const _obj = _ctx.obj')
-    expect(code).contains('_setProp(n0, "id", _obj!.foo + _obj!.bar)')
-  })
-
-  test('shared member root', () => {
-    const { code } = compileWithVBind(`
-        <div :id="foo.bar"></div>
-        <div :id="foo.baz"></div>
-      `)
-    expect(code).matchSnapshot()
-    expect(code).contains('const _foo = _ctx.foo')
-    expect(code).contains('_setProp(n0, "id", _foo.bar)')
-    expect(code).contains('_setProp(n1, "id", _foo.baz)')
-  })
-
-  test('shared member root with TSNonNullExpression', () => {
-    const { code } = compileWithVBind(`
-        <div :id="foo!.bar"></div>
-        <div :id="foo!.baz"></div>
-      `)
-    expect(code).matchSnapshot()
-    expect(code).contains('const _foo = _ctx.foo')
-    expect(code).contains('_setProp(n0, "id", _foo!.bar)')
-    expect(code).contains('_setProp(n1, "id", _foo!.baz)')
-  })
-
-  test('not cache variable only used in property shorthand', () => {
-    const { code } = compileWithVBind(`
-        <div :style="{color}" />
-      `)
-    expect(code).matchSnapshot()
-    expect(code).not.contains('const _color = _ctx.color')
-  })
-
-  test('not cache variable and member expression with the same name', () => {
-    const { code } = compileWithVBind(`
-        <div :id="bar + obj.bar"></div>
-      `)
-    expect(code).matchSnapshot()
-    expect(code).not.contains('const _bar = _ctx.bar')
-  })
-
-  test('not cache variable in function expression', () => {
-    const { code } = compileWithVBind(`
-        <div v-bind="{ foo: bar => foo = bar }"></div>
-      `)
-    expect(code).matchSnapshot()
-    expect(code).not.contains('const _bar = _ctx.bar')
-  })
-
-  test('should not cache method call with different arguments', () => {
-    const { code } = compileWithVBind(`
-      <div :id="msg.replace('1', '2')"></div>
-      <div :id="msg.replace('1', '3')"></div>
-    `)
-    expect(code).matchSnapshot()
-    expect(code).contains('const _msg = _ctx.msg')
-    expect(code).not.contains('_ctx.msg.replace')
-  })
-
-  test('should cache method call with same arguments', () => {
-    const { code } = compileWithVBind(`
-      <div :id="msg.replace('1', '2')"></div>
-      <div :id="msg.replace('1', '2')"></div>
-    `)
-    expect(code).matchSnapshot()
-    expect(code).contains(`const _msg_replace_1_2 = _ctx.msg.replace('1', '2')`)
-    expect(code).not.contains('const _msg = _ctx.msg')
-  })
-
-  test('should cache optional call expression with same arguments', () => {
-    const { code } = compileWithVBind(`
-      <div :id="obj[foo?.(bar)]"></div>
-      <div :id="obj[foo?.(bar)]"></div>
-    `)
-    expect(code).matchSnapshot()
-    expect(code).contains(`const _obj_foo_bar = _ctx.obj[_ctx.foo?.(_ctx.bar)]`)
-  })
-
-  test('should not cache globally allowed identifier call expressions', () => {
-    const { code } = compileWithVBind(`
-      <div :id="Math.random()"></div>
-      <div :id="Math.random()"></div>
-    `)
-    expect(code).matchSnapshot()
-    // Math.random() should NOT be cached because it has side effects
-    expect(code).not.contains('const _Math')
-    expect(code).contains('Math.random()')
-  })
-
-  test('should not cache Date.now() call expressions', () => {
-    const { code } = compileWithVBind(`
-      <div :id="Date.now()"></div>
-      <div :id="Date.now()"></div>
-    `)
-    expect(code).matchSnapshot()
-    expect(code).not.contains('const _Date')
-    expect(code).contains('Date.now()')
-  })
-
-  test('should not cache mixed expression with globally allowed call', () => {
-    const { code } = compileWithVBind(`
-      <div :id="Math.random() + foo"></div>
-      <div :id="Math.random() + foo"></div>
-    `)
-    expect(code).matchSnapshot()
-    // The whole expression should NOT be cached because Math.random() has side effects
-    expect(code).not.contains('const _Math_random')
-    expect(code).contains('Math.random()')
-  })
-
-  test('should not cache globally allowed identifier as variable', () => {
-    const { code } = compileWithVBind(`
-      <div :id="String(foo)"></div>
-      <div :id="String(bar)"></div>
-    `)
-    expect(code).matchSnapshot()
-    expect(code).not.contains('const _String = String')
-  })
-
-  test('should not cache member expression containing globally allowed call', () => {
-    const { code } = compileWithVBind(`
-      <div :id="obj[Math.random()]"></div>
-      <div :id="obj[Math.random()]"></div>
-    `)
-    expect(code).matchSnapshot()
-    expect(code).not.contains('const _obj_Math_random')
-    expect(code).contains('Math.random()')
-  })
-})