ssrVModel.spec.ts 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. import { compile } from '../src'
  2. function compileWithWrapper(src: string) {
  3. return compile(`<div>${src}</div>`)
  4. }
  5. describe('ssr: v-model', () => {
  6. test('<input> (text types)', () => {
  7. expect(compileWithWrapper(`<input v-model="bar">`).code)
  8. .toMatchInlineSnapshot(`
  9. "const { ssrRenderAttr: _ssrRenderAttr, ssrRenderAttrs: _ssrRenderAttrs } = require("vue/server-renderer")
  10. return function ssrRender(_ctx, _push, _parent, _attrs) {
  11. _push(\`<div\${
  12. _ssrRenderAttrs(_attrs)
  13. }><input\${
  14. _ssrRenderAttr("value", _ctx.bar)
  15. }></div>\`)
  16. }"
  17. `)
  18. expect(compileWithWrapper(`<input type="email" v-model="bar">`).code)
  19. .toMatchInlineSnapshot(`
  20. "const { ssrRenderAttr: _ssrRenderAttr, ssrRenderAttrs: _ssrRenderAttrs } = require("vue/server-renderer")
  21. return function ssrRender(_ctx, _push, _parent, _attrs) {
  22. _push(\`<div\${
  23. _ssrRenderAttrs(_attrs)
  24. }><input type="email"\${
  25. _ssrRenderAttr("value", _ctx.bar)
  26. }></div>\`)
  27. }"
  28. `)
  29. })
  30. test('<select v-model>', () => {
  31. expect(
  32. compileWithWrapper(
  33. `<select v-model="model"><option value="1"></option></select>`,
  34. ).code,
  35. ).toMatchInlineSnapshot(`
  36. "const { ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrLooseContain: _ssrLooseContain, ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs } = require("vue/server-renderer")
  37. return function ssrRender(_ctx, _push, _parent, _attrs) {
  38. _push(\`<div\${
  39. _ssrRenderAttrs(_attrs)
  40. }><select><option value="1"\${
  41. (_ssrIncludeBooleanAttr((Array.isArray(_ctx.model))
  42. ? _ssrLooseContain(_ctx.model, "1")
  43. : _ssrLooseEqual(_ctx.model, "1"))) ? " selected" : ""
  44. }></option></select></div>\`)
  45. }"
  46. `)
  47. expect(
  48. compileWithWrapper(
  49. `<select v-model="model"><option v-for="i in items" :value="i"></option></select>`,
  50. ).code,
  51. ).toMatchInlineSnapshot(`
  52. "const { ssrRenderAttr: _ssrRenderAttr, ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrLooseContain: _ssrLooseContain, ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs, ssrRenderList: _ssrRenderList } = require("vue/server-renderer")
  53. return function ssrRender(_ctx, _push, _parent, _attrs) {
  54. _push(\`<div\${_ssrRenderAttrs(_attrs)}><select><!--[-->\`)
  55. _ssrRenderList(_ctx.items, (i) => {
  56. _push(\`<option\${
  57. _ssrRenderAttr("value", i)
  58. }\${
  59. (_ssrIncludeBooleanAttr((Array.isArray(_ctx.model))
  60. ? _ssrLooseContain(_ctx.model, i)
  61. : _ssrLooseEqual(_ctx.model, i))) ? " selected" : ""
  62. }></option>\`)
  63. })
  64. _push(\`<!--]--></select></div>\`)
  65. }"
  66. `)
  67. expect(
  68. compileWithWrapper(
  69. `<select v-model="model"><option v-if="true" :value="i"></option></select>`,
  70. ).code,
  71. ).toMatchInlineSnapshot(`
  72. "const { ssrRenderAttr: _ssrRenderAttr, ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrLooseContain: _ssrLooseContain, ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs } = require("vue/server-renderer")
  73. return function ssrRender(_ctx, _push, _parent, _attrs) {
  74. _push(\`<div\${_ssrRenderAttrs(_attrs)}><select>\`)
  75. if (true) {
  76. _push(\`<option\${
  77. _ssrRenderAttr("value", _ctx.i)
  78. }\${
  79. (_ssrIncludeBooleanAttr((Array.isArray(_ctx.model))
  80. ? _ssrLooseContain(_ctx.model, _ctx.i)
  81. : _ssrLooseEqual(_ctx.model, _ctx.i))) ? " selected" : ""
  82. }></option>\`)
  83. } else {
  84. _push(\`<!---->\`)
  85. }
  86. _push(\`</select></div>\`)
  87. }"
  88. `)
  89. expect(
  90. compileWithWrapper(
  91. `<select multiple v-model="model"><option value="1" selected></option><option value="2"></option></select>`,
  92. ).code,
  93. ).toMatchInlineSnapshot(`
  94. "const { ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrLooseContain: _ssrLooseContain, ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs } = require("vue/server-renderer")
  95. return function ssrRender(_ctx, _push, _parent, _attrs) {
  96. _push(\`<div\${
  97. _ssrRenderAttrs(_attrs)
  98. }><select multiple><option value="1" selected></option><option value="2"\${
  99. (_ssrIncludeBooleanAttr((Array.isArray(_ctx.model))
  100. ? _ssrLooseContain(_ctx.model, "2")
  101. : _ssrLooseEqual(_ctx.model, "2"))) ? " selected" : ""
  102. }></option></select></div>\`)
  103. }"
  104. `)
  105. expect(
  106. compileWithWrapper(`<select multiple v-model="model"><slot/></select>`)
  107. .code,
  108. ).toMatchInlineSnapshot(`
  109. "const { ssrRenderSlot: _ssrRenderSlot, ssrRenderAttrs: _ssrRenderAttrs } = require("vue/server-renderer")
  110. return function ssrRender(_ctx, _push, _parent, _attrs) {
  111. _push(\`<div\${_ssrRenderAttrs(_attrs)}><select multiple>\`)
  112. _ssrRenderSlot(_ctx.$slots, "default", {}, null, _push, _parent)
  113. _push(\`</select></div>\`)
  114. }"
  115. `)
  116. expect(
  117. compileWithWrapper(`
  118. <select multiple v-model="model">
  119. <optgroup label="foo">
  120. <option value="bar">bar</option>
  121. </optgroup>
  122. </select>`).code,
  123. ).toMatchInlineSnapshot(`
  124. "const { ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrLooseContain: _ssrLooseContain, ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs } = require("vue/server-renderer")
  125. return function ssrRender(_ctx, _push, _parent, _attrs) {
  126. _push(\`<div\${
  127. _ssrRenderAttrs(_attrs)
  128. }><select multiple><optgroup label="foo"><option value="bar"\${
  129. (_ssrIncludeBooleanAttr((Array.isArray(_ctx.model))
  130. ? _ssrLooseContain(_ctx.model, "bar")
  131. : _ssrLooseEqual(_ctx.model, "bar"))) ? " selected" : ""
  132. }>bar</option></optgroup></select></div>\`)
  133. }"
  134. `)
  135. expect(
  136. compileWithWrapper(`
  137. <select multiple v-model="model">
  138. <optgroup label="foo">
  139. <slot/>
  140. </optgroup>
  141. </select>`).code,
  142. ).toMatchInlineSnapshot(`
  143. "const { ssrRenderSlot: _ssrRenderSlot, ssrRenderAttrs: _ssrRenderAttrs } = require("vue/server-renderer")
  144. return function ssrRender(_ctx, _push, _parent, _attrs) {
  145. _push(\`<div\${_ssrRenderAttrs(_attrs)}><select multiple><optgroup label="foo">\`)
  146. _ssrRenderSlot(_ctx.$slots, "default", {}, null, _push, _parent)
  147. _push(\`</optgroup></select></div>\`)
  148. }"
  149. `)
  150. expect(
  151. compileWithWrapper(`
  152. <select multiple v-model="model">
  153. <optgroup>
  154. <option v-for="item in items" :value="item">{{item}}</option>
  155. </optgroup>
  156. </select>`).code,
  157. ).toMatchInlineSnapshot(`
  158. "const { ssrRenderAttr: _ssrRenderAttr, ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrLooseContain: _ssrLooseContain, ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs, ssrInterpolate: _ssrInterpolate, ssrRenderList: _ssrRenderList } = require("vue/server-renderer")
  159. return function ssrRender(_ctx, _push, _parent, _attrs) {
  160. _push(\`<div\${_ssrRenderAttrs(_attrs)}><select multiple><optgroup><!--[-->\`)
  161. _ssrRenderList(_ctx.items, (item) => {
  162. _push(\`<option\${
  163. _ssrRenderAttr("value", item)
  164. }\${
  165. (_ssrIncludeBooleanAttr((Array.isArray(_ctx.model))
  166. ? _ssrLooseContain(_ctx.model, item)
  167. : _ssrLooseEqual(_ctx.model, item))) ? " selected" : ""
  168. }>\${
  169. _ssrInterpolate(item)
  170. }</option>\`)
  171. })
  172. _push(\`<!--]--></optgroup></select></div>\`)
  173. }"
  174. `)
  175. expect(
  176. compileWithWrapper(`
  177. <select multiple v-model="model">
  178. <optgroup>
  179. <option v-if="true" :value="item">{{item}}</option>
  180. </optgroup>
  181. </select>`).code,
  182. ).toMatchInlineSnapshot(`
  183. "const { ssrRenderAttr: _ssrRenderAttr, ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrLooseContain: _ssrLooseContain, ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs, ssrInterpolate: _ssrInterpolate } = require("vue/server-renderer")
  184. return function ssrRender(_ctx, _push, _parent, _attrs) {
  185. _push(\`<div\${_ssrRenderAttrs(_attrs)}><select multiple><optgroup>\`)
  186. if (true) {
  187. _push(\`<option\${
  188. _ssrRenderAttr("value", _ctx.item)
  189. }\${
  190. (_ssrIncludeBooleanAttr((Array.isArray(_ctx.model))
  191. ? _ssrLooseContain(_ctx.model, _ctx.item)
  192. : _ssrLooseEqual(_ctx.model, _ctx.item))) ? " selected" : ""
  193. }>\${
  194. _ssrInterpolate(_ctx.item)
  195. }</option>\`)
  196. } else {
  197. _push(\`<!---->\`)
  198. }
  199. _push(\`</optgroup></select></div>\`)
  200. }"
  201. `)
  202. expect(
  203. compileWithWrapper(`
  204. <select multiple v-model="model">
  205. <optgroup>
  206. <template v-if="ok">
  207. <option v-for="item in items" :value="item">{{item}}</option>
  208. </template>
  209. </optgroup>
  210. </select>`).code,
  211. ).toMatchInlineSnapshot(`
  212. "const { ssrRenderAttr: _ssrRenderAttr, ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrLooseContain: _ssrLooseContain, ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs, ssrInterpolate: _ssrInterpolate, ssrRenderList: _ssrRenderList } = require("vue/server-renderer")
  213. return function ssrRender(_ctx, _push, _parent, _attrs) {
  214. _push(\`<div\${_ssrRenderAttrs(_attrs)}><select multiple><optgroup>\`)
  215. if (_ctx.ok) {
  216. _push(\`<!--[-->\`)
  217. _ssrRenderList(_ctx.items, (item) => {
  218. _push(\`<option\${
  219. _ssrRenderAttr("value", item)
  220. }\${
  221. (_ssrIncludeBooleanAttr((Array.isArray(_ctx.model))
  222. ? _ssrLooseContain(_ctx.model, item)
  223. : _ssrLooseEqual(_ctx.model, item))) ? " selected" : ""
  224. }>\${
  225. _ssrInterpolate(item)
  226. }</option>\`)
  227. })
  228. _push(\`<!--]-->\`)
  229. } else {
  230. _push(\`<!---->\`)
  231. }
  232. _push(\`</optgroup></select></div>\`)
  233. }"
  234. `)
  235. expect(
  236. compileWithWrapper(`
  237. <select multiple v-model="model">
  238. <optgroup>
  239. <template v-for="item in items" :value="item">
  240. <option v-if="item===1" :value="item">{{item}}</option>
  241. </template>
  242. </optgroup>
  243. </select>`).code,
  244. ).toMatchInlineSnapshot(`
  245. "const { ssrRenderAttr: _ssrRenderAttr, ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrLooseContain: _ssrLooseContain, ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs, ssrInterpolate: _ssrInterpolate, ssrRenderList: _ssrRenderList } = require("vue/server-renderer")
  246. return function ssrRender(_ctx, _push, _parent, _attrs) {
  247. _push(\`<div\${_ssrRenderAttrs(_attrs)}><select multiple><optgroup><!--[-->\`)
  248. _ssrRenderList(_ctx.items, (item) => {
  249. _push(\`<!--[-->\`)
  250. if (item===1) {
  251. _push(\`<option\${
  252. _ssrRenderAttr("value", item)
  253. }\${
  254. (_ssrIncludeBooleanAttr((Array.isArray(_ctx.model))
  255. ? _ssrLooseContain(_ctx.model, item)
  256. : _ssrLooseEqual(_ctx.model, item))) ? " selected" : ""
  257. }>\${
  258. _ssrInterpolate(item)
  259. }</option>\`)
  260. } else {
  261. _push(\`<!---->\`)
  262. }
  263. _push(\`<!--]-->\`)
  264. })
  265. _push(\`<!--]--></optgroup></select></div>\`)
  266. }"
  267. `)
  268. })
  269. test('<input type="radio">', () => {
  270. expect(
  271. compileWithWrapper(`<input type="radio" value="foo" v-model="bar">`).code,
  272. ).toMatchInlineSnapshot(`
  273. "const { ssrLooseEqual: _ssrLooseEqual, ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrRenderAttrs: _ssrRenderAttrs } = require("vue/server-renderer")
  274. return function ssrRender(_ctx, _push, _parent, _attrs) {
  275. _push(\`<div\${
  276. _ssrRenderAttrs(_attrs)
  277. }><input type="radio" value="foo"\${
  278. (_ssrIncludeBooleanAttr(_ssrLooseEqual(_ctx.bar, "foo"))) ? " checked" : ""
  279. }></div>\`)
  280. }"
  281. `)
  282. })
  283. test('<input type="checkbox">', () => {
  284. expect(compileWithWrapper(`<input type="checkbox" v-model="bar">`).code)
  285. .toMatchInlineSnapshot(`
  286. "const { ssrLooseContain: _ssrLooseContain, ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrRenderAttrs: _ssrRenderAttrs } = require("vue/server-renderer")
  287. return function ssrRender(_ctx, _push, _parent, _attrs) {
  288. _push(\`<div\${
  289. _ssrRenderAttrs(_attrs)
  290. }><input type="checkbox"\${
  291. (_ssrIncludeBooleanAttr((Array.isArray(_ctx.bar))
  292. ? _ssrLooseContain(_ctx.bar, null)
  293. : _ctx.bar)) ? " checked" : ""
  294. }></div>\`)
  295. }"
  296. `)
  297. expect(
  298. compileWithWrapper(`<input type="checkbox" value="foo" v-model="bar">`)
  299. .code,
  300. ).toMatchInlineSnapshot(`
  301. "const { ssrLooseContain: _ssrLooseContain, ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrRenderAttrs: _ssrRenderAttrs } = require("vue/server-renderer")
  302. return function ssrRender(_ctx, _push, _parent, _attrs) {
  303. _push(\`<div\${
  304. _ssrRenderAttrs(_attrs)
  305. }><input type="checkbox" value="foo"\${
  306. (_ssrIncludeBooleanAttr((Array.isArray(_ctx.bar))
  307. ? _ssrLooseContain(_ctx.bar, "foo")
  308. : _ctx.bar)) ? " checked" : ""
  309. }></div>\`)
  310. }"
  311. `)
  312. expect(
  313. compileWithWrapper(
  314. `<input type="checkbox" :true-value="foo" :false-value="bar" v-model="baz">`,
  315. ).code,
  316. ).toMatchInlineSnapshot(`
  317. "const { ssrLooseEqual: _ssrLooseEqual, ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrRenderAttrs: _ssrRenderAttrs } = require("vue/server-renderer")
  318. return function ssrRender(_ctx, _push, _parent, _attrs) {
  319. _push(\`<div\${
  320. _ssrRenderAttrs(_attrs)
  321. }><input type="checkbox"\${
  322. (_ssrIncludeBooleanAttr(_ssrLooseEqual(_ctx.baz, _ctx.foo))) ? " checked" : ""
  323. }></div>\`)
  324. }"
  325. `)
  326. expect(
  327. compileWithWrapper(
  328. `<input type="checkbox" true-value="foo" false-value="bar" v-model="baz">`,
  329. ).code,
  330. ).toMatchInlineSnapshot(`
  331. "const { ssrLooseEqual: _ssrLooseEqual, ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrRenderAttrs: _ssrRenderAttrs } = require("vue/server-renderer")
  332. return function ssrRender(_ctx, _push, _parent, _attrs) {
  333. _push(\`<div\${
  334. _ssrRenderAttrs(_attrs)
  335. }><input type="checkbox"\${
  336. (_ssrIncludeBooleanAttr(_ssrLooseEqual(_ctx.baz, "foo"))) ? " checked" : ""
  337. }></div>\`)
  338. }"
  339. `)
  340. })
  341. test('<textarea>', () => {
  342. expect(compileWithWrapper(`<textarea v-model="foo">bar</textarea>`).code)
  343. .toMatchInlineSnapshot(`
  344. "const { ssrRenderAttrs: _ssrRenderAttrs, ssrInterpolate: _ssrInterpolate } = require("vue/server-renderer")
  345. return function ssrRender(_ctx, _push, _parent, _attrs) {
  346. _push(\`<div\${
  347. _ssrRenderAttrs(_attrs)
  348. }><textarea>\${
  349. _ssrInterpolate(_ctx.foo)
  350. }</textarea></div>\`)
  351. }"
  352. `)
  353. })
  354. test('<input :type="x">', () => {
  355. expect(compileWithWrapper(`<input :type="x" v-model="foo">`).code)
  356. .toMatchInlineSnapshot(`
  357. "const { ssrRenderAttr: _ssrRenderAttr, ssrRenderDynamicModel: _ssrRenderDynamicModel, ssrRenderAttrs: _ssrRenderAttrs } = require("vue/server-renderer")
  358. return function ssrRender(_ctx, _push, _parent, _attrs) {
  359. _push(\`<div\${
  360. _ssrRenderAttrs(_attrs)
  361. }><input\${
  362. _ssrRenderAttr("type", _ctx.x)
  363. }\${
  364. _ssrRenderDynamicModel(_ctx.x, _ctx.foo, null)
  365. }></div>\`)
  366. }"
  367. `)
  368. expect(
  369. compileWithWrapper(`<input :type="x" v-model="foo" value="bar">`).code,
  370. ).toMatchInlineSnapshot(`
  371. "const { ssrRenderAttr: _ssrRenderAttr, ssrRenderDynamicModel: _ssrRenderDynamicModel, ssrRenderAttrs: _ssrRenderAttrs } = require("vue/server-renderer")
  372. return function ssrRender(_ctx, _push, _parent, _attrs) {
  373. _push(\`<div\${
  374. _ssrRenderAttrs(_attrs)
  375. }><input\${
  376. _ssrRenderAttr("type", _ctx.x)
  377. }\${
  378. _ssrRenderDynamicModel(_ctx.x, _ctx.foo, "bar")
  379. } value="bar"></div>\`)
  380. }"
  381. `)
  382. expect(
  383. compileWithWrapper(`<input :type="x" v-model="foo" :value="bar">`).code,
  384. ).toMatchInlineSnapshot(`
  385. "const { ssrRenderAttr: _ssrRenderAttr, ssrRenderDynamicModel: _ssrRenderDynamicModel, ssrRenderAttrs: _ssrRenderAttrs } = require("vue/server-renderer")
  386. return function ssrRender(_ctx, _push, _parent, _attrs) {
  387. _push(\`<div\${
  388. _ssrRenderAttrs(_attrs)
  389. }><input\${
  390. _ssrRenderAttr("type", _ctx.x)
  391. }\${
  392. _ssrRenderDynamicModel(_ctx.x, _ctx.foo, _ctx.bar)
  393. }\${
  394. _ssrRenderAttr("value", _ctx.bar)
  395. }></div>\`)
  396. }"
  397. `)
  398. })
  399. test('<input v-bind="obj">', () => {
  400. expect(compileWithWrapper(`<input v-bind="obj" v-model="foo">`).code)
  401. .toMatchInlineSnapshot(`
  402. "const { mergeProps: _mergeProps } = require("vue")
  403. const { ssrRenderAttrs: _ssrRenderAttrs, ssrGetDynamicModelProps: _ssrGetDynamicModelProps } = require("vue/server-renderer")
  404. return function ssrRender(_ctx, _push, _parent, _attrs) {
  405. let _temp0
  406. _push(\`<div\${
  407. _ssrRenderAttrs(_attrs)
  408. }><input\${
  409. _ssrRenderAttrs((_temp0 = _ctx.obj, _mergeProps(_temp0, _ssrGetDynamicModelProps(_temp0, _ctx.foo))))
  410. }></div>\`)
  411. }"
  412. `)
  413. expect(
  414. compileWithWrapper(`<input id="x" v-bind="obj" v-model="foo" class="y">`)
  415. .code,
  416. ).toMatchInlineSnapshot(`
  417. "const { mergeProps: _mergeProps } = require("vue")
  418. const { ssrRenderAttrs: _ssrRenderAttrs, ssrGetDynamicModelProps: _ssrGetDynamicModelProps } = require("vue/server-renderer")
  419. return function ssrRender(_ctx, _push, _parent, _attrs) {
  420. let _temp0
  421. _push(\`<div\${
  422. _ssrRenderAttrs(_attrs)
  423. }><input\${
  424. _ssrRenderAttrs((_temp0 = _mergeProps({ id: "x" }, _ctx.obj, { class: "y" }), _mergeProps(_temp0, _ssrGetDynamicModelProps(_temp0, _ctx.foo))))
  425. }></div>\`)
  426. }"
  427. `)
  428. })
  429. })