@vue/compat 3.2.39 → 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: '' }`
@@ -4989,7 +4996,7 @@ function injectHook(type, hook, target = currentInstance, prepend = false) {
4989
4996
  const createHook = (lifecycle) => (hook, target = currentInstance) =>
4990
4997
  // post-create lifecycle registrations are noops during SSR (except for serverPrefetch)
4991
4998
  (!isInSSRComponentSetup || lifecycle === "sp" /* LifecycleHooks.SERVER_PREFETCH */) &&
4992
- injectHook(lifecycle, hook, target);
4999
+ injectHook(lifecycle, (...args) => hook(...args), target);
4993
5000
  const onBeforeMount = createHook("bm" /* LifecycleHooks.BEFORE_MOUNT */);
4994
5001
  const onMounted = createHook("m" /* LifecycleHooks.MOUNTED */);
4995
5002
  const onBeforeUpdate = createHook("bu" /* LifecycleHooks.BEFORE_UPDATE */);
@@ -5541,7 +5548,10 @@ function createSlots(slots, dynamicSlots) {
5541
5548
  slots[slot.name] = slot.key
5542
5549
  ? (...args) => {
5543
5550
  const res = slot.fn(...args);
5544
- 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;
5545
5555
  return res;
5546
5556
  }
5547
5557
  : slot.fn;
@@ -7309,7 +7319,7 @@ function createCompatVue(createApp, createSingletonApp) {
7309
7319
  return vm;
7310
7320
  }
7311
7321
  }
7312
- Vue.version = `2.6.14-compat:${"3.2.39"}`;
7322
+ Vue.version = `2.6.14-compat:${"3.2.40"}`;
7313
7323
  Vue.config = singletonApp.config;
7314
7324
  Vue.use = (p, ...options) => {
7315
7325
  if (p && isFunction(p.install)) {
@@ -8020,7 +8030,7 @@ function createHydrationFunctions(rendererInternals) {
8020
8030
  const isFragmentStart = isComment(node) && node.data === '[';
8021
8031
  const onMismatch = () => handleMismatch(node, vnode, parentComponent, parentSuspense, slotScopeIds, isFragmentStart);
8022
8032
  const { type, ref, shapeFlag, patchFlag } = vnode;
8023
- const domType = node.nodeType;
8033
+ let domType = node.nodeType;
8024
8034
  vnode.el = node;
8025
8035
  if (patchFlag === -2 /* PatchFlags.BAIL */) {
8026
8036
  optimized = false;
@@ -8060,10 +8070,12 @@ function createHydrationFunctions(rendererInternals) {
8060
8070
  }
8061
8071
  break;
8062
8072
  case Static:
8063
- if (domType !== 1 /* DOMNodeTypes.ELEMENT */ && domType !== 3 /* DOMNodeTypes.TEXT */) {
8064
- nextNode = onMismatch();
8073
+ if (isFragmentStart) {
8074
+ // entire template is static but SSRed as a fragment
8075
+ node = nextSibling(node);
8076
+ domType = node.nodeType;
8065
8077
  }
8066
- else {
8078
+ if (domType === 1 /* DOMNodeTypes.ELEMENT */ || domType === 3 /* DOMNodeTypes.TEXT */) {
8067
8079
  // determine anchor, adopt content
8068
8080
  nextNode = node;
8069
8081
  // if the static vnode has its content stripped during build,
@@ -8080,7 +8092,10 @@ function createHydrationFunctions(rendererInternals) {
8080
8092
  }
8081
8093
  nextNode = nextSibling(nextNode);
8082
8094
  }
8083
- return nextNode;
8095
+ return isFragmentStart ? nextSibling(nextNode) : nextNode;
8096
+ }
8097
+ else {
8098
+ onMismatch();
8084
8099
  }
8085
8100
  break;
8086
8101
  case Fragment:
@@ -8405,7 +8420,7 @@ function baseCreateRenderer(options, createHydrationFns) {
8405
8420
  {
8406
8421
  setDevtoolsHook(target.__VUE_DEVTOOLS_GLOBAL_HOOK__, target);
8407
8422
  }
8408
- 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;
8409
8424
  // Note: functions inside this closure should use `const xxx = () => {}`
8410
8425
  // style in order to prevent being inlined by minifiers.
8411
8426
  const patch = (n1, n2, container, anchor = null, parentComponent = null, parentSuspense = null, isSVG = false, slotScopeIds = null, optimized = isHmrUpdating ? false : !!n2.dynamicChildren) => {
@@ -8532,46 +8547,44 @@ function baseCreateRenderer(options, createHydrationFns) {
8532
8547
  const mountElement = (vnode, container, anchor, parentComponent, parentSuspense, isSVG, slotScopeIds, optimized) => {
8533
8548
  let el;
8534
8549
  let vnodeHook;
8535
- const { type, props, shapeFlag, transition, patchFlag, dirs } = vnode;
8536
- {
8537
- el = vnode.el = hostCreateElement(vnode.type, isSVG, props && props.is, props);
8538
- // mount children first, since some props may rely on child content
8539
- // being already rendered, e.g. `<select value>`
8540
- if (shapeFlag & 8 /* ShapeFlags.TEXT_CHILDREN */) {
8541
- hostSetElementText(el, vnode.children);
8542
- }
8543
- else if (shapeFlag & 16 /* ShapeFlags.ARRAY_CHILDREN */) {
8544
- mountChildren(vnode.children, el, null, parentComponent, parentSuspense, isSVG && type !== 'foreignObject', slotScopeIds, optimized);
8545
- }
8546
- if (dirs) {
8547
- invokeDirectiveHook(vnode, null, parentComponent, 'created');
8548
- }
8549
- // props
8550
- if (props) {
8551
- for (const key in props) {
8552
- if (key !== 'value' && !isReservedProp(key)) {
8553
- hostPatchProp(el, key, null, props[key], isSVG, vnode.children, parentComponent, parentSuspense, unmountChildren);
8554
- }
8555
- }
8556
- /**
8557
- * Special case for setting value on DOM elements:
8558
- * - it can be order-sensitive (e.g. should be set *after* min/max, #2325, #4024)
8559
- * - it needs to be forced (#1471)
8560
- * #2353 proposes adding another renderer option to configure this, but
8561
- * the properties affects are so finite it is worth special casing it
8562
- * here to reduce the complexity. (Special casing it also should not
8563
- * affect non-DOM renderers)
8564
- */
8565
- if ('value' in props) {
8566
- hostPatchProp(el, 'value', null, props.value);
8567
- }
8568
- if ((vnodeHook = props.onVnodeBeforeMount)) {
8569
- invokeVNodeHook(vnodeHook, parentComponent, vnode);
8570
- }
8571
- }
8572
- // scopeId
8573
- 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);
8574
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);
8575
8588
  {
8576
8589
  Object.defineProperty(el, '__vnode', {
8577
8590
  value: vnode,
@@ -8757,6 +8770,13 @@ function baseCreateRenderer(options, createHydrationFns) {
8757
8770
  };
8758
8771
  const patchProps = (el, vnode, oldProps, newProps, parentComponent, parentSuspense, isSVG) => {
8759
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
+ }
8760
8780
  for (const key in newProps) {
8761
8781
  // empty string is not valid prop
8762
8782
  if (isReservedProp(key))
@@ -8768,13 +8788,6 @@ function baseCreateRenderer(options, createHydrationFns) {
8768
8788
  hostPatchProp(el, key, prev, next, isSVG, vnode.children, parentComponent, parentSuspense, unmountChildren);
8769
8789
  }
8770
8790
  }
8771
- if (oldProps !== EMPTY_OBJ) {
8772
- for (const key in oldProps) {
8773
- if (!isReservedProp(key) && !(key in newProps)) {
8774
- hostPatchProp(el, key, oldProps[key], null, isSVG, vnode.children, parentComponent, parentSuspense, unmountChildren);
8775
- }
8776
- }
8777
- }
8778
8791
  if ('value' in newProps) {
8779
8792
  hostPatchProp(el, 'value', oldProps.value, newProps.value);
8780
8793
  }
@@ -10394,7 +10407,10 @@ function normalizeVNode(child) {
10394
10407
  }
10395
10408
  // optimized normalization for template-compiled render fns
10396
10409
  function cloneIfMounted(child) {
10397
- 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);
10398
10414
  }
10399
10415
  function normalizeChildren(vnode, children) {
10400
10416
  let type = 0;
@@ -11312,7 +11328,7 @@ function isMemoSame(cached, memo) {
11312
11328
  }
11313
11329
 
11314
11330
  // Core API ------------------------------------------------------------------
11315
- const version = "3.2.39";
11331
+ const version = "3.2.40";
11316
11332
  const _ssrUtils = {
11317
11333
  createComponentInstance,
11318
11334
  setupComponent,
@@ -11378,22 +11394,6 @@ const nodeOps = {
11378
11394
  setScopeId(el, id) {
11379
11395
  el.setAttribute(id, '');
11380
11396
  },
11381
- cloneNode(el) {
11382
- const cloned = el.cloneNode(true);
11383
- // #3072
11384
- // - in `patchDOMProp`, we store the actual value in the `el._value` property.
11385
- // - normally, elements using `:value` bindings will not be hoisted, but if
11386
- // the bound value is a constant, e.g. `:value="true"` - they do get
11387
- // hoisted.
11388
- // - in production, hoisted nodes are cloned when subsequent inserts, but
11389
- // cloneNode() does not copy the custom property we attached.
11390
- // - This may need to account for other custom DOM properties we attach to
11391
- // elements in addition to `_value` in the future.
11392
- if (`_value` in el) {
11393
- cloned._value = el._value;
11394
- }
11395
- return cloned;
11396
- },
11397
11397
  // __UNSAFE__
11398
11398
  // Reason: innerHTML.
11399
11399
  // Static content here can only come from compiled templates.
@@ -11564,14 +11564,14 @@ const isEnumeratedAttr = /*#__PURE__*/ makeMap('contenteditable,draggable,spellc
11564
11564
  ;
11565
11565
  function compatCoerceAttr(el, key, value, instance = null) {
11566
11566
  if (isEnumeratedAttr(key)) {
11567
- const v2CocercedValue = value === null
11567
+ const v2CoercedValue = value === null
11568
11568
  ? 'false'
11569
11569
  : typeof value !== 'boolean' && value !== undefined
11570
11570
  ? 'true'
11571
11571
  : null;
11572
- if (v2CocercedValue &&
11573
- compatUtils.softAssertCompatEnabled("ATTR_ENUMERATED_COERCION" /* DeprecationTypes.ATTR_ENUMERATED_COERCION */, instance, key, value, v2CocercedValue)) {
11574
- 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);
11575
11575
  return true;
11576
11576
  }
11577
11577
  }
@@ -11632,7 +11632,6 @@ prevChildren, parentComponent, parentSuspense, unmountChildren) {
11632
11632
  }
11633
11633
  else if (type === 'number') {
11634
11634
  // e.g. <img :width="null">
11635
- // the value of some IDL attr must be greater than 0, e.g. input.size = 0 -> error
11636
11635
  value = 0;
11637
11636
  needRemove = true;
11638
11637
  }
@@ -11655,7 +11654,8 @@ prevChildren, parentComponent, parentSuspense, unmountChildren) {
11655
11654
  el[key] = value;
11656
11655
  }
11657
11656
  catch (e) {
11658
- {
11657
+ // do not warn if value is auto-coerced from nullish values
11658
+ if (!needRemove) {
11659
11659
  warn$1(`Failed setting prop "${key}" on <${el.tagName.toLowerCase()}>: ` +
11660
11660
  `value ${value} is invalid.`, e);
11661
11661
  }
@@ -14115,34 +14115,42 @@ function parseChildren(context, mode, ancestors) {
14115
14115
  const shouldCondense = context.options.whitespace !== 'preserve';
14116
14116
  for (let i = 0; i < nodes.length; i++) {
14117
14117
  const node = nodes[i];
14118
- if (!context.inPre && node.type === 2 /* NodeTypes.TEXT */) {
14119
- if (!/[^\t\r\n\f ]/.test(node.content)) {
14120
- const prev = nodes[i - 1];
14121
- const next = nodes[i + 1];
14122
- // Remove if:
14123
- // - the whitespace is the first or last node, or:
14124
- // - (condense mode) the whitespace is adjacent to a comment, or:
14125
- // - (condense mode) the whitespace is between two elements AND contains newline
14126
- if (!prev ||
14127
- !next ||
14128
- (shouldCondense &&
14129
- (prev.type === 3 /* NodeTypes.COMMENT */ ||
14130
- next.type === 3 /* NodeTypes.COMMENT */ ||
14131
- (prev.type === 1 /* NodeTypes.ELEMENT */ &&
14132
- next.type === 1 /* NodeTypes.ELEMENT */ &&
14133
- /[\r\n]/.test(node.content))))) {
14134
- removedWhitespace = true;
14135
- 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
+ }
14136
14142
  }
14137
- else {
14138
- // Otherwise, the whitespace is condensed into a single space
14139
- 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, ' ');
14140
14147
  }
14141
14148
  }
14142
- else if (shouldCondense) {
14143
- // in condense mode, consecutive whitespaces in text are condensed
14144
- // down to a single space.
14145
- 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');
14146
14154
  }
14147
14155
  }
14148
14156
  // Remove comment nodes if desired by configuration.
@@ -14830,11 +14838,6 @@ function walk$1(node, context, doNotHoistNode = false) {
14830
14838
  }
14831
14839
  }
14832
14840
  }
14833
- else if (child.type === 12 /* NodeTypes.TEXT_CALL */ &&
14834
- getConstantType(child.content, context) >= 2 /* ConstantTypes.CAN_HOIST */) {
14835
- child.codegenNode = context.hoist(child.codegenNode);
14836
- hoistedCount++;
14837
- }
14838
14841
  // walk further
14839
14842
  if (child.type === 1 /* NodeTypes.ELEMENT */) {
14840
14843
  const isComponent = child.tagType === 1 /* ElementTypes.COMPONENT */;
@@ -17717,6 +17720,14 @@ function buildProps(node, context, props = node.props, isComponent, isDynamicCom
17717
17720
  let hasDynamicKeys = false;
17718
17721
  let hasVnodeHook = false;
17719
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
+ };
17720
17731
  const analyzePatchFlag = ({ key, value }) => {
17721
17732
  if (isStaticExp(key)) {
17722
17733
  const name = key.content;
@@ -17838,11 +17849,9 @@ function buildProps(node, context, props = node.props, isComponent, isDynamicCom
17838
17849
  if (!arg && (isVBind || isVOn)) {
17839
17850
  hasDynamicKeys = true;
17840
17851
  if (exp) {
17841
- if (properties.length) {
17842
- mergeArgs.push(createObjectExpression(dedupeProperties(properties), elementLoc));
17843
- properties = [];
17844
- }
17845
17852
  if (isVBind) {
17853
+ // have to merge early for compat build check
17854
+ pushMergeArg();
17846
17855
  {
17847
17856
  // 2.x v-bind object order compat
17848
17857
  {
@@ -17876,7 +17885,7 @@ function buildProps(node, context, props = node.props, isComponent, isDynamicCom
17876
17885
  }
17877
17886
  else {
17878
17887
  // v-on="obj" -> toHandlers(obj)
17879
- mergeArgs.push({
17888
+ pushMergeArg({
17880
17889
  type: 14 /* NodeTypes.JS_CALL_EXPRESSION */,
17881
17890
  loc,
17882
17891
  callee: context.helper(TO_HANDLERS),
@@ -17896,7 +17905,12 @@ function buildProps(node, context, props = node.props, isComponent, isDynamicCom
17896
17905
  // has built-in directive transform.
17897
17906
  const { props, needRuntime } = directiveTransform(prop, node, context);
17898
17907
  !ssr && props.forEach(analyzePatchFlag);
17899
- properties.push(...props);
17908
+ if (isVOn && arg && !isStaticExp(arg)) {
17909
+ pushMergeArg(createObjectExpression(props, elementLoc));
17910
+ }
17911
+ else {
17912
+ properties.push(...props);
17913
+ }
17900
17914
  if (needRuntime) {
17901
17915
  runtimeDirectives.push(prop);
17902
17916
  if (isSymbol(needRuntime)) {
@@ -17918,9 +17932,8 @@ function buildProps(node, context, props = node.props, isComponent, isDynamicCom
17918
17932
  let propsExpression = undefined;
17919
17933
  // has v-bind="object" or v-on="object", wrap with mergeProps
17920
17934
  if (mergeArgs.length) {
17921
- if (properties.length) {
17922
- mergeArgs.push(createObjectExpression(dedupeProperties(properties), elementLoc));
17923
- }
17935
+ // close up any not-yet-merged props
17936
+ pushMergeArg();
17924
17937
  if (mergeArgs.length > 1) {
17925
17938
  propsExpression = createCallExpression(context.helper(MERGE_PROPS), mergeArgs, elementLoc);
17926
17939
  }
@@ -21817,6 +21830,11 @@ function stringifyElement(node, context) {
21817
21830
  res += ` ${p.arg.content}="__VUE_EXP_START__${exp.content}__VUE_EXP_END__"`;
21818
21831
  continue;
21819
21832
  }
21833
+ // #6568
21834
+ if (isBooleanAttr(p.arg.content) &&
21835
+ exp.content === 'false') {
21836
+ continue;
21837
+ }
21820
21838
  // constant v-bind, e.g. :foo="1"
21821
21839
  let evaluated = evaluateConstant(exp);
21822
21840
  if (evaluated != null) {