@vue/compat 3.2.38 → 3.2.40

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -311,7 +311,7 @@ Features that start with `COMPILER_` are compiler-specific: if you are using the
311
311
  | V_ON_KEYCODE_MODIFIER | ✔ | `v-on` no longer supports keyCode modifiers | [link](https://v3-migration.vuejs.org/breaking-changes/keycode-modifiers.html) |
312
312
  | CUSTOM_DIR | ✔ | Custom directive hook names changed | [link](https://v3-migration.vuejs.org/breaking-changes/custom-directives.html) |
313
313
  | ATTR_FALSE_VALUE | ✔ | No longer removes attribute if binding value is boolean `false` | [link](https://v3-migration.vuejs.org/breaking-changes/attribute-coercion.html) |
314
- | ATTR_ENUMERATED_COERSION | ✔ | No longer special case enumerated attributes | [link](https://v3-migration.vuejs.org/breaking-changes/attribute-coercion.html) |
314
+ | ATTR_ENUMERATED_COERCION | ✔ | No longer special case enumerated attributes | [link](https://v3-migration.vuejs.org/breaking-changes/attribute-coercion.html) |
315
315
  | TRANSITION_GROUP_ROOT | ✔ | `<transition-group>` no longer renders a root element by default | [link](https://v3-migration.vuejs.org/breaking-changes/transition-group.html) |
316
316
  | COMPONENT_ASYNC | ✔ | Async component API changed (now requires `defineAsyncComponent`) | [link](https://v3-migration.vuejs.org/breaking-changes/async-components.html) |
317
317
  | COMPONENT_FUNCTIONAL | ✔ | Functional component API changed (now must be plain functions) | [link](https://v3-migration.vuejs.org/breaking-changes/functional-components.html) |
package/dist/vue.cjs.js CHANGED
@@ -111,6 +111,13 @@ function generateCodeFrame(source, start = 0, end = source.length) {
111
111
  */
112
112
  const specialBooleanAttrs = `itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly`;
113
113
  const isSpecialBooleanAttr = /*#__PURE__*/ makeMap(specialBooleanAttrs);
114
+ /**
115
+ * The full list is needed during SSR to produce the correct initial markup.
116
+ */
117
+ const isBooleanAttr = /*#__PURE__*/ makeMap(specialBooleanAttrs +
118
+ `,async,autofocus,autoplay,controls,default,defer,disabled,hidden,` +
119
+ `loop,open,required,reversed,scoped,seamless,` +
120
+ `checked,muted,multiple,selected`);
114
121
  /**
115
122
  * Boolean attributes should be included if the value is truthy or ''.
116
123
  * e.g. `<select multiple>` compiles to `{ multiple: '' }`
@@ -2022,7 +2029,9 @@ function queuePostFlushCb(cb) {
2022
2029
  }
2023
2030
  queueFlush();
2024
2031
  }
2025
- function flushPreFlushCbs(seen, i = flushIndex) {
2032
+ function flushPreFlushCbs(seen,
2033
+ // if currently flushing, skip the current job itself
2034
+ i = isFlushing ? flushIndex + 1 : 0) {
2026
2035
  {
2027
2036
  seen = seen || new Map();
2028
2037
  }
@@ -4987,7 +4996,7 @@ function injectHook(type, hook, target = currentInstance, prepend = false) {
4987
4996
  const createHook = (lifecycle) => (hook, target = currentInstance) =>
4988
4997
  // post-create lifecycle registrations are noops during SSR (except for serverPrefetch)
4989
4998
  (!isInSSRComponentSetup || lifecycle === "sp" /* LifecycleHooks.SERVER_PREFETCH */) &&
4990
- injectHook(lifecycle, hook, target);
4999
+ injectHook(lifecycle, (...args) => hook(...args), target);
4991
5000
  const onBeforeMount = createHook("bm" /* LifecycleHooks.BEFORE_MOUNT */);
4992
5001
  const onMounted = createHook("m" /* LifecycleHooks.MOUNTED */);
4993
5002
  const onBeforeUpdate = createHook("bu" /* LifecycleHooks.BEFORE_UPDATE */);
@@ -5539,7 +5548,10 @@ function createSlots(slots, dynamicSlots) {
5539
5548
  slots[slot.name] = slot.key
5540
5549
  ? (...args) => {
5541
5550
  const res = slot.fn(...args);
5542
- res.key = slot.key;
5551
+ // attach branch key so each conditional branch is considered a
5552
+ // different fragment
5553
+ if (res)
5554
+ res.key = slot.key;
5543
5555
  return res;
5544
5556
  }
5545
5557
  : slot.fn;
@@ -7307,7 +7319,7 @@ function createCompatVue(createApp, createSingletonApp) {
7307
7319
  return vm;
7308
7320
  }
7309
7321
  }
7310
- Vue.version = `2.6.14-compat:${"3.2.38"}`;
7322
+ Vue.version = `2.6.14-compat:${"3.2.40"}`;
7311
7323
  Vue.config = singletonApp.config;
7312
7324
  Vue.use = (p, ...options) => {
7313
7325
  if (p && isFunction(p.install)) {
@@ -8018,7 +8030,7 @@ function createHydrationFunctions(rendererInternals) {
8018
8030
  const isFragmentStart = isComment(node) && node.data === '[';
8019
8031
  const onMismatch = () => handleMismatch(node, vnode, parentComponent, parentSuspense, slotScopeIds, isFragmentStart);
8020
8032
  const { type, ref, shapeFlag, patchFlag } = vnode;
8021
- const domType = node.nodeType;
8033
+ let domType = node.nodeType;
8022
8034
  vnode.el = node;
8023
8035
  if (patchFlag === -2 /* PatchFlags.BAIL */) {
8024
8036
  optimized = false;
@@ -8058,10 +8070,12 @@ function createHydrationFunctions(rendererInternals) {
8058
8070
  }
8059
8071
  break;
8060
8072
  case Static:
8061
- if (domType !== 1 /* DOMNodeTypes.ELEMENT */ && domType !== 3 /* DOMNodeTypes.TEXT */) {
8062
- nextNode = onMismatch();
8073
+ if (isFragmentStart) {
8074
+ // entire template is static but SSRed as a fragment
8075
+ node = nextSibling(node);
8076
+ domType = node.nodeType;
8063
8077
  }
8064
- else {
8078
+ if (domType === 1 /* DOMNodeTypes.ELEMENT */ || domType === 3 /* DOMNodeTypes.TEXT */) {
8065
8079
  // determine anchor, adopt content
8066
8080
  nextNode = node;
8067
8081
  // if the static vnode has its content stripped during build,
@@ -8078,7 +8092,10 @@ function createHydrationFunctions(rendererInternals) {
8078
8092
  }
8079
8093
  nextNode = nextSibling(nextNode);
8080
8094
  }
8081
- return nextNode;
8095
+ return isFragmentStart ? nextSibling(nextNode) : nextNode;
8096
+ }
8097
+ else {
8098
+ onMismatch();
8082
8099
  }
8083
8100
  break;
8084
8101
  case Fragment:
@@ -8403,7 +8420,7 @@ function baseCreateRenderer(options, createHydrationFns) {
8403
8420
  {
8404
8421
  setDevtoolsHook(target.__VUE_DEVTOOLS_GLOBAL_HOOK__, target);
8405
8422
  }
8406
- const { insert: hostInsert, remove: hostRemove, patchProp: hostPatchProp, createElement: hostCreateElement, createText: hostCreateText, createComment: hostCreateComment, setText: hostSetText, setElementText: hostSetElementText, parentNode: hostParentNode, nextSibling: hostNextSibling, setScopeId: hostSetScopeId = NOOP, cloneNode: hostCloneNode, insertStaticContent: hostInsertStaticContent } = options;
8423
+ const { insert: hostInsert, remove: hostRemove, patchProp: hostPatchProp, createElement: hostCreateElement, createText: hostCreateText, createComment: hostCreateComment, setText: hostSetText, setElementText: hostSetElementText, parentNode: hostParentNode, nextSibling: hostNextSibling, setScopeId: hostSetScopeId = NOOP, insertStaticContent: hostInsertStaticContent } = options;
8407
8424
  // Note: functions inside this closure should use `const xxx = () => {}`
8408
8425
  // style in order to prevent being inlined by minifiers.
8409
8426
  const patch = (n1, n2, container, anchor = null, parentComponent = null, parentSuspense = null, isSVG = false, slotScopeIds = null, optimized = isHmrUpdating ? false : !!n2.dynamicChildren) => {
@@ -8530,46 +8547,44 @@ function baseCreateRenderer(options, createHydrationFns) {
8530
8547
  const mountElement = (vnode, container, anchor, parentComponent, parentSuspense, isSVG, slotScopeIds, optimized) => {
8531
8548
  let el;
8532
8549
  let vnodeHook;
8533
- const { type, props, shapeFlag, transition, patchFlag, dirs } = vnode;
8534
- {
8535
- el = vnode.el = hostCreateElement(vnode.type, isSVG, props && props.is, props);
8536
- // mount children first, since some props may rely on child content
8537
- // being already rendered, e.g. `<select value>`
8538
- if (shapeFlag & 8 /* ShapeFlags.TEXT_CHILDREN */) {
8539
- hostSetElementText(el, vnode.children);
8540
- }
8541
- else if (shapeFlag & 16 /* ShapeFlags.ARRAY_CHILDREN */) {
8542
- mountChildren(vnode.children, el, null, parentComponent, parentSuspense, isSVG && type !== 'foreignObject', slotScopeIds, optimized);
8543
- }
8544
- if (dirs) {
8545
- invokeDirectiveHook(vnode, null, parentComponent, 'created');
8546
- }
8547
- // props
8548
- if (props) {
8549
- for (const key in props) {
8550
- if (key !== 'value' && !isReservedProp(key)) {
8551
- hostPatchProp(el, key, null, props[key], isSVG, vnode.children, parentComponent, parentSuspense, unmountChildren);
8552
- }
8553
- }
8554
- /**
8555
- * Special case for setting value on DOM elements:
8556
- * - it can be order-sensitive (e.g. should be set *after* min/max, #2325, #4024)
8557
- * - it needs to be forced (#1471)
8558
- * #2353 proposes adding another renderer option to configure this, but
8559
- * the properties affects are so finite it is worth special casing it
8560
- * here to reduce the complexity. (Special casing it also should not
8561
- * affect non-DOM renderers)
8562
- */
8563
- if ('value' in props) {
8564
- hostPatchProp(el, 'value', null, props.value);
8565
- }
8566
- if ((vnodeHook = props.onVnodeBeforeMount)) {
8567
- invokeVNodeHook(vnodeHook, parentComponent, vnode);
8568
- }
8569
- }
8570
- // scopeId
8571
- setScopeId(el, vnode, vnode.scopeId, slotScopeIds, parentComponent);
8550
+ const { type, props, shapeFlag, transition, dirs } = vnode;
8551
+ el = vnode.el = hostCreateElement(vnode.type, isSVG, props && props.is, props);
8552
+ // mount children first, since some props may rely on child content
8553
+ // being already rendered, e.g. `<select value>`
8554
+ if (shapeFlag & 8 /* ShapeFlags.TEXT_CHILDREN */) {
8555
+ hostSetElementText(el, vnode.children);
8572
8556
  }
8557
+ else if (shapeFlag & 16 /* ShapeFlags.ARRAY_CHILDREN */) {
8558
+ mountChildren(vnode.children, el, null, parentComponent, parentSuspense, isSVG && type !== 'foreignObject', slotScopeIds, optimized);
8559
+ }
8560
+ if (dirs) {
8561
+ invokeDirectiveHook(vnode, null, parentComponent, 'created');
8562
+ }
8563
+ // props
8564
+ if (props) {
8565
+ for (const key in props) {
8566
+ if (key !== 'value' && !isReservedProp(key)) {
8567
+ hostPatchProp(el, key, null, props[key], isSVG, vnode.children, parentComponent, parentSuspense, unmountChildren);
8568
+ }
8569
+ }
8570
+ /**
8571
+ * Special case for setting value on DOM elements:
8572
+ * - it can be order-sensitive (e.g. should be set *after* min/max, #2325, #4024)
8573
+ * - it needs to be forced (#1471)
8574
+ * #2353 proposes adding another renderer option to configure this, but
8575
+ * the properties affects are so finite it is worth special casing it
8576
+ * here to reduce the complexity. (Special casing it also should not
8577
+ * affect non-DOM renderers)
8578
+ */
8579
+ if ('value' in props) {
8580
+ hostPatchProp(el, 'value', null, props.value);
8581
+ }
8582
+ if ((vnodeHook = props.onVnodeBeforeMount)) {
8583
+ invokeVNodeHook(vnodeHook, parentComponent, vnode);
8584
+ }
8585
+ }
8586
+ // scopeId
8587
+ setScopeId(el, vnode, vnode.scopeId, slotScopeIds, parentComponent);
8573
8588
  {
8574
8589
  Object.defineProperty(el, '__vnode', {
8575
8590
  value: vnode,
@@ -8755,6 +8770,13 @@ function baseCreateRenderer(options, createHydrationFns) {
8755
8770
  };
8756
8771
  const patchProps = (el, vnode, oldProps, newProps, parentComponent, parentSuspense, isSVG) => {
8757
8772
  if (oldProps !== newProps) {
8773
+ if (oldProps !== EMPTY_OBJ) {
8774
+ for (const key in oldProps) {
8775
+ if (!isReservedProp(key) && !(key in newProps)) {
8776
+ hostPatchProp(el, key, oldProps[key], null, isSVG, vnode.children, parentComponent, parentSuspense, unmountChildren);
8777
+ }
8778
+ }
8779
+ }
8758
8780
  for (const key in newProps) {
8759
8781
  // empty string is not valid prop
8760
8782
  if (isReservedProp(key))
@@ -8766,13 +8788,6 @@ function baseCreateRenderer(options, createHydrationFns) {
8766
8788
  hostPatchProp(el, key, prev, next, isSVG, vnode.children, parentComponent, parentSuspense, unmountChildren);
8767
8789
  }
8768
8790
  }
8769
- if (oldProps !== EMPTY_OBJ) {
8770
- for (const key in oldProps) {
8771
- if (!isReservedProp(key) && !(key in newProps)) {
8772
- hostPatchProp(el, key, oldProps[key], null, isSVG, vnode.children, parentComponent, parentSuspense, unmountChildren);
8773
- }
8774
- }
8775
- }
8776
8791
  if ('value' in newProps) {
8777
8792
  hostPatchProp(el, 'value', oldProps.value, newProps.value);
8778
8793
  }
@@ -10392,7 +10407,10 @@ function normalizeVNode(child) {
10392
10407
  }
10393
10408
  // optimized normalization for template-compiled render fns
10394
10409
  function cloneIfMounted(child) {
10395
- return child.el === null || child.memo ? child : cloneVNode(child);
10410
+ return (child.el === null && child.patchFlag !== -1 /* PatchFlags.HOISTED */) ||
10411
+ child.memo
10412
+ ? child
10413
+ : cloneVNode(child);
10396
10414
  }
10397
10415
  function normalizeChildren(vnode, children) {
10398
10416
  let type = 0;
@@ -10747,7 +10765,8 @@ function finishComponentSetup(instance, isSSR, skipOptions) {
10747
10765
  if (!isSSR && compile && !Component.render) {
10748
10766
  const template = (instance.vnode.props &&
10749
10767
  instance.vnode.props['inline-template']) ||
10750
- Component.template;
10768
+ Component.template ||
10769
+ resolveMergedOptions(instance).template;
10751
10770
  if (template) {
10752
10771
  {
10753
10772
  startMeasure(instance, `compile`);
@@ -11309,7 +11328,7 @@ function isMemoSame(cached, memo) {
11309
11328
  }
11310
11329
 
11311
11330
  // Core API ------------------------------------------------------------------
11312
- const version = "3.2.38";
11331
+ const version = "3.2.40";
11313
11332
  const _ssrUtils = {
11314
11333
  createComponentInstance,
11315
11334
  setupComponent,
@@ -11375,22 +11394,6 @@ const nodeOps = {
11375
11394
  setScopeId(el, id) {
11376
11395
  el.setAttribute(id, '');
11377
11396
  },
11378
- cloneNode(el) {
11379
- const cloned = el.cloneNode(true);
11380
- // #3072
11381
- // - in `patchDOMProp`, we store the actual value in the `el._value` property.
11382
- // - normally, elements using `:value` bindings will not be hoisted, but if
11383
- // the bound value is a constant, e.g. `:value="true"` - they do get
11384
- // hoisted.
11385
- // - in production, hoisted nodes are cloned when subsequent inserts, but
11386
- // cloneNode() does not copy the custom property we attached.
11387
- // - This may need to account for other custom DOM properties we attach to
11388
- // elements in addition to `_value` in the future.
11389
- if (`_value` in el) {
11390
- cloned._value = el._value;
11391
- }
11392
- return cloned;
11393
- },
11394
11397
  // __UNSAFE__
11395
11398
  // Reason: innerHTML.
11396
11399
  // Static content here can only come from compiled templates.
@@ -11561,14 +11564,14 @@ const isEnumeratedAttr = /*#__PURE__*/ makeMap('contenteditable,draggable,spellc
11561
11564
  ;
11562
11565
  function compatCoerceAttr(el, key, value, instance = null) {
11563
11566
  if (isEnumeratedAttr(key)) {
11564
- const v2CocercedValue = value === null
11567
+ const v2CoercedValue = value === null
11565
11568
  ? 'false'
11566
11569
  : typeof value !== 'boolean' && value !== undefined
11567
11570
  ? 'true'
11568
11571
  : null;
11569
- if (v2CocercedValue &&
11570
- compatUtils.softAssertCompatEnabled("ATTR_ENUMERATED_COERCION" /* DeprecationTypes.ATTR_ENUMERATED_COERCION */, instance, key, value, v2CocercedValue)) {
11571
- el.setAttribute(key, v2CocercedValue);
11572
+ if (v2CoercedValue &&
11573
+ compatUtils.softAssertCompatEnabled("ATTR_ENUMERATED_COERCION" /* DeprecationTypes.ATTR_ENUMERATED_COERCION */, instance, key, value, v2CoercedValue)) {
11574
+ el.setAttribute(key, v2CoercedValue);
11572
11575
  return true;
11573
11576
  }
11574
11577
  }
@@ -11629,7 +11632,6 @@ prevChildren, parentComponent, parentSuspense, unmountChildren) {
11629
11632
  }
11630
11633
  else if (type === 'number') {
11631
11634
  // e.g. <img :width="null">
11632
- // the value of some IDL attr must be greater than 0, e.g. input.size = 0 -> error
11633
11635
  value = 0;
11634
11636
  needRemove = true;
11635
11637
  }
@@ -11652,7 +11654,8 @@ prevChildren, parentComponent, parentSuspense, unmountChildren) {
11652
11654
  el[key] = value;
11653
11655
  }
11654
11656
  catch (e) {
11655
- {
11657
+ // do not warn if value is auto-coerced from nullish values
11658
+ if (!needRemove) {
11656
11659
  warn$1(`Failed setting prop "${key}" on <${el.tagName.toLowerCase()}>: ` +
11657
11660
  `value ${value} is invalid.`, e);
11658
11661
  }
@@ -14112,34 +14115,42 @@ function parseChildren(context, mode, ancestors) {
14112
14115
  const shouldCondense = context.options.whitespace !== 'preserve';
14113
14116
  for (let i = 0; i < nodes.length; i++) {
14114
14117
  const node = nodes[i];
14115
- if (!context.inPre && node.type === 2 /* NodeTypes.TEXT */) {
14116
- if (!/[^\t\r\n\f ]/.test(node.content)) {
14117
- const prev = nodes[i - 1];
14118
- const next = nodes[i + 1];
14119
- // Remove if:
14120
- // - the whitespace is the first or last node, or:
14121
- // - (condense mode) the whitespace is adjacent to a comment, or:
14122
- // - (condense mode) the whitespace is between two elements AND contains newline
14123
- if (!prev ||
14124
- !next ||
14125
- (shouldCondense &&
14126
- (prev.type === 3 /* NodeTypes.COMMENT */ ||
14127
- next.type === 3 /* NodeTypes.COMMENT */ ||
14128
- (prev.type === 1 /* NodeTypes.ELEMENT */ &&
14129
- next.type === 1 /* NodeTypes.ELEMENT */ &&
14130
- /[\r\n]/.test(node.content))))) {
14131
- removedWhitespace = true;
14132
- nodes[i] = null;
14118
+ if (node.type === 2 /* NodeTypes.TEXT */) {
14119
+ if (!context.inPre) {
14120
+ if (!/[^\t\r\n\f ]/.test(node.content)) {
14121
+ const prev = nodes[i - 1];
14122
+ const next = nodes[i + 1];
14123
+ // Remove if:
14124
+ // - the whitespace is the first or last node, or:
14125
+ // - (condense mode) the whitespace is adjacent to a comment, or:
14126
+ // - (condense mode) the whitespace is between two elements AND contains newline
14127
+ if (!prev ||
14128
+ !next ||
14129
+ (shouldCondense &&
14130
+ (prev.type === 3 /* NodeTypes.COMMENT */ ||
14131
+ next.type === 3 /* NodeTypes.COMMENT */ ||
14132
+ (prev.type === 1 /* NodeTypes.ELEMENT */ &&
14133
+ next.type === 1 /* NodeTypes.ELEMENT */ &&
14134
+ /[\r\n]/.test(node.content))))) {
14135
+ removedWhitespace = true;
14136
+ nodes[i] = null;
14137
+ }
14138
+ else {
14139
+ // Otherwise, the whitespace is condensed into a single space
14140
+ node.content = ' ';
14141
+ }
14133
14142
  }
14134
- else {
14135
- // Otherwise, the whitespace is condensed into a single space
14136
- node.content = ' ';
14143
+ else if (shouldCondense) {
14144
+ // in condense mode, consecutive whitespaces in text are condensed
14145
+ // down to a single space.
14146
+ node.content = node.content.replace(/[\t\r\n\f ]+/g, ' ');
14137
14147
  }
14138
14148
  }
14139
- else if (shouldCondense) {
14140
- // in condense mode, consecutive whitespaces in text are condensed
14141
- // down to a single space.
14142
- node.content = node.content.replace(/[\t\r\n\f ]+/g, ' ');
14149
+ else {
14150
+ // #6410 normalize windows newlines in <pre>:
14151
+ // in SSR, browsers normalize server-rendered \r\n into a single \n
14152
+ // in the DOM
14153
+ node.content = node.content.replace(/\r\n/g, '\n');
14143
14154
  }
14144
14155
  }
14145
14156
  // Remove comment nodes if desired by configuration.
@@ -14827,11 +14838,6 @@ function walk$1(node, context, doNotHoistNode = false) {
14827
14838
  }
14828
14839
  }
14829
14840
  }
14830
- else if (child.type === 12 /* NodeTypes.TEXT_CALL */ &&
14831
- getConstantType(child.content, context) >= 2 /* ConstantTypes.CAN_HOIST */) {
14832
- child.codegenNode = context.hoist(child.codegenNode);
14833
- hoistedCount++;
14834
- }
14835
14841
  // walk further
14836
14842
  if (child.type === 1 /* NodeTypes.ELEMENT */) {
14837
14843
  const isComponent = child.tagType === 1 /* ElementTypes.COMPONENT */;
@@ -17714,6 +17720,14 @@ function buildProps(node, context, props = node.props, isComponent, isDynamicCom
17714
17720
  let hasDynamicKeys = false;
17715
17721
  let hasVnodeHook = false;
17716
17722
  const dynamicPropNames = [];
17723
+ const pushMergeArg = (arg) => {
17724
+ if (properties.length) {
17725
+ mergeArgs.push(createObjectExpression(dedupeProperties(properties), elementLoc));
17726
+ properties = [];
17727
+ }
17728
+ if (arg)
17729
+ mergeArgs.push(arg);
17730
+ };
17717
17731
  const analyzePatchFlag = ({ key, value }) => {
17718
17732
  if (isStaticExp(key)) {
17719
17733
  const name = key.content;
@@ -17835,11 +17849,9 @@ function buildProps(node, context, props = node.props, isComponent, isDynamicCom
17835
17849
  if (!arg && (isVBind || isVOn)) {
17836
17850
  hasDynamicKeys = true;
17837
17851
  if (exp) {
17838
- if (properties.length) {
17839
- mergeArgs.push(createObjectExpression(dedupeProperties(properties), elementLoc));
17840
- properties = [];
17841
- }
17842
17852
  if (isVBind) {
17853
+ // have to merge early for compat build check
17854
+ pushMergeArg();
17843
17855
  {
17844
17856
  // 2.x v-bind object order compat
17845
17857
  {
@@ -17873,7 +17885,7 @@ function buildProps(node, context, props = node.props, isComponent, isDynamicCom
17873
17885
  }
17874
17886
  else {
17875
17887
  // v-on="obj" -> toHandlers(obj)
17876
- mergeArgs.push({
17888
+ pushMergeArg({
17877
17889
  type: 14 /* NodeTypes.JS_CALL_EXPRESSION */,
17878
17890
  loc,
17879
17891
  callee: context.helper(TO_HANDLERS),
@@ -17893,7 +17905,12 @@ function buildProps(node, context, props = node.props, isComponent, isDynamicCom
17893
17905
  // has built-in directive transform.
17894
17906
  const { props, needRuntime } = directiveTransform(prop, node, context);
17895
17907
  !ssr && props.forEach(analyzePatchFlag);
17896
- properties.push(...props);
17908
+ if (isVOn && arg && !isStaticExp(arg)) {
17909
+ pushMergeArg(createObjectExpression(props, elementLoc));
17910
+ }
17911
+ else {
17912
+ properties.push(...props);
17913
+ }
17897
17914
  if (needRuntime) {
17898
17915
  runtimeDirectives.push(prop);
17899
17916
  if (isSymbol(needRuntime)) {
@@ -17915,9 +17932,8 @@ function buildProps(node, context, props = node.props, isComponent, isDynamicCom
17915
17932
  let propsExpression = undefined;
17916
17933
  // has v-bind="object" or v-on="object", wrap with mergeProps
17917
17934
  if (mergeArgs.length) {
17918
- if (properties.length) {
17919
- mergeArgs.push(createObjectExpression(dedupeProperties(properties), elementLoc));
17920
- }
17935
+ // close up any not-yet-merged props
17936
+ pushMergeArg();
17921
17937
  if (mergeArgs.length > 1) {
17922
17938
  propsExpression = createCallExpression(context.helper(MERGE_PROPS), mergeArgs, elementLoc);
17923
17939
  }
@@ -21814,6 +21830,11 @@ function stringifyElement(node, context) {
21814
21830
  res += ` ${p.arg.content}="__VUE_EXP_START__${exp.content}__VUE_EXP_END__"`;
21815
21831
  continue;
21816
21832
  }
21833
+ // #6568
21834
+ if (isBooleanAttr(p.arg.content) &&
21835
+ exp.content === 'false') {
21836
+ continue;
21837
+ }
21817
21838
  // constant v-bind, e.g. :foo="1"
21818
21839
  let evaluated = evaluateConstant(exp);
21819
21840
  if (evaluated != null) {