@vue/compiler-core 3.2.21 → 3.2.25

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.
@@ -530,12 +530,12 @@ function findProp(node, name, dynamicOnly = false, allowEmpty = false) {
530
530
  }
531
531
  else if (p.name === 'bind' &&
532
532
  (p.exp || allowEmpty) &&
533
- isBindKey(p.arg, name)) {
533
+ isStaticArgOf(p.arg, name)) {
534
534
  return p;
535
535
  }
536
536
  }
537
537
  }
538
- function isBindKey(arg, name) {
538
+ function isStaticArgOf(arg, name) {
539
539
  return !!(arg && isStaticExp(arg) && arg.content === name);
540
540
  }
541
541
  function hasDynamicKeyVBind(node) {
@@ -578,7 +578,6 @@ function getUnnormalizedProps(props, callPath = []) {
578
578
  }
579
579
  function injectProp(node, prop, context) {
580
580
  let propsWithInjection;
581
- const originalProps = node.type === 13 /* VNODE_CALL */ ? node.props : node.arguments[2];
582
581
  /**
583
582
  * 1. mergeProps(...)
584
583
  * 2. toHandlers(...)
@@ -587,7 +586,7 @@ function injectProp(node, prop, context) {
587
586
  *
588
587
  * we need to get the real props before normalization
589
588
  */
590
- let props = originalProps;
589
+ let props = node.type === 13 /* VNODE_CALL */ ? node.props : node.arguments[2];
591
590
  let callPath = [];
592
591
  let parentCall;
593
592
  if (props &&
@@ -769,11 +768,6 @@ const deprecationData = {
769
768
  `data source.`,
770
769
  link: `https://v3.vuejs.org/guide/migration/v-if-v-for.html`
771
770
  },
772
- ["COMPILER_V_FOR_REF" /* COMPILER_V_FOR_REF */]: {
773
- message: `Ref usage on v-for no longer creates array ref values in Vue 3. ` +
774
- `Consider using function refs or refactor to avoid ref usage altogether.`,
775
- link: `https://v3.vuejs.org/guide/migration/array-refs.html`
776
- },
777
771
  ["COMPILER_NATIVE_TEMPLATE" /* COMPILER_NATIVE_TEMPLATE */]: {
778
772
  message: `<template> with no special directives will render as a native template ` +
779
773
  `element instead of its inner content in Vue 3.`
@@ -1291,7 +1285,7 @@ function isComponent(tag, props, context) {
1291
1285
  else if (
1292
1286
  // :is on plain element - only treat as component in compat mode
1293
1287
  p.name === 'bind' &&
1294
- isBindKey(p.arg, 'is') &&
1288
+ isStaticArgOf(p.arg, 'is') &&
1295
1289
  true &&
1296
1290
  checkCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context, p.loc)) {
1297
1291
  return true;
@@ -1651,15 +1645,6 @@ function isSingleElementRoot(root, child) {
1651
1645
  !isSlotOutlet(child));
1652
1646
  }
1653
1647
  function walk(node, context, doNotHoistNode = false) {
1654
- // Some transforms, e.g. transformAssetUrls from @vue/compiler-sfc, replaces
1655
- // static bindings with expressions. These expressions are guaranteed to be
1656
- // constant so they are still eligible for hoisting, but they are only
1657
- // available at runtime and therefore cannot be evaluated ahead of time.
1658
- // This is only a concern for pre-stringification (via transformHoist by
1659
- // @vue/compiler-dom), but doing it here allows us to perform only one full
1660
- // walk of the AST and allow `stringifyStatic` to stop walking as soon as its
1661
- // stringification threshold is met.
1662
- let canStringify = true;
1663
1648
  const { children } = node;
1664
1649
  const originalCount = children.length;
1665
1650
  let hoistedCount = 0;
@@ -1672,9 +1657,6 @@ function walk(node, context, doNotHoistNode = false) {
1672
1657
  ? 0 /* NOT_CONSTANT */
1673
1658
  : getConstantType(child, context);
1674
1659
  if (constantType > 0 /* NOT_CONSTANT */) {
1675
- if (constantType < 3 /* CAN_STRINGIFY */) {
1676
- canStringify = false;
1677
- }
1678
1660
  if (constantType >= 2 /* CAN_HOIST */) {
1679
1661
  child.codegenNode.patchFlag =
1680
1662
  -1 /* HOISTED */ + (` /* HOISTED */` );
@@ -1705,17 +1687,10 @@ function walk(node, context, doNotHoistNode = false) {
1705
1687
  }
1706
1688
  }
1707
1689
  }
1708
- else if (child.type === 12 /* TEXT_CALL */) {
1709
- const contentType = getConstantType(child.content, context);
1710
- if (contentType > 0) {
1711
- if (contentType < 3 /* CAN_STRINGIFY */) {
1712
- canStringify = false;
1713
- }
1714
- if (contentType >= 2 /* CAN_HOIST */) {
1715
- child.codegenNode = context.hoist(child.codegenNode);
1716
- hoistedCount++;
1717
- }
1718
- }
1690
+ else if (child.type === 12 /* TEXT_CALL */ &&
1691
+ getConstantType(child.content, context) >= 2 /* CAN_HOIST */) {
1692
+ child.codegenNode = context.hoist(child.codegenNode);
1693
+ hoistedCount++;
1719
1694
  }
1720
1695
  // walk further
1721
1696
  if (child.type === 1 /* ELEMENT */) {
@@ -1739,7 +1714,7 @@ function walk(node, context, doNotHoistNode = false) {
1739
1714
  }
1740
1715
  }
1741
1716
  }
1742
- if (canStringify && hoistedCount && context.transformHoist) {
1717
+ if (hoistedCount && context.transformHoist) {
1743
1718
  context.transformHoist(children, context, node);
1744
1719
  }
1745
1720
  // all children were hoisted - the entire children array is hoistable.
@@ -1768,6 +1743,11 @@ function getConstantType(node, context) {
1768
1743
  if (codegenNode.type !== 13 /* VNODE_CALL */) {
1769
1744
  return 0 /* NOT_CONSTANT */;
1770
1745
  }
1746
+ if (codegenNode.isBlock &&
1747
+ node.tag !== 'svg' &&
1748
+ node.tag !== 'foreignObject') {
1749
+ return 0 /* NOT_CONSTANT */;
1750
+ }
1771
1751
  const flag = getPatchFlag(codegenNode);
1772
1752
  if (!flag) {
1773
1753
  let returnType = 3 /* CAN_STRINGIFY */;
@@ -1904,7 +1884,7 @@ function getGeneratedPropsConstantType(node, context) {
1904
1884
  else if (value.type === 14 /* JS_CALL_EXPRESSION */) {
1905
1885
  // some helper calls can be hoisted,
1906
1886
  // such as the `normalizeProps` generated by the compiler for pre-normalize class,
1907
- // in this case we need to respect the ConstantType of the helper's argments
1887
+ // in this case we need to respect the ConstantType of the helper's arguments
1908
1888
  valueType = getConstantTypeOfHelperCall(value, context);
1909
1889
  }
1910
1890
  else {
@@ -4358,10 +4338,7 @@ const transformElement = (node, context) => {
4358
4338
  // updates inside get proper isSVG flag at runtime. (#639, #643)
4359
4339
  // This is technically web-specific, but splitting the logic out of core
4360
4340
  // leads to too much unnecessary complexity.
4361
- (tag === 'svg' ||
4362
- tag === 'foreignObject' ||
4363
- // #938: elements with dynamic keys should be forced into blocks
4364
- findProp(node, 'key', true)));
4341
+ (tag === 'svg' || tag === 'foreignObject'));
4365
4342
  // props
4366
4343
  if (props.length > 0) {
4367
4344
  const propsBuildResult = buildProps(node, context);
@@ -4373,6 +4350,9 @@ const transformElement = (node, context) => {
4373
4350
  directives && directives.length
4374
4351
  ? createArrayExpression(directives.map(dir => buildDirectiveArgs(dir, context)))
4375
4352
  : undefined;
4353
+ if (propsBuildResult.shouldUseBlock) {
4354
+ shouldUseBlock = true;
4355
+ }
4376
4356
  }
4377
4357
  // children
4378
4358
  if (node.children.length > 0) {
@@ -4562,11 +4542,13 @@ function resolveSetupReference(name, context) {
4562
4542
  }
4563
4543
  }
4564
4544
  function buildProps(node, context, props = node.props, ssr = false) {
4565
- const { tag, loc: elementLoc } = node;
4545
+ const { tag, loc: elementLoc, children } = node;
4566
4546
  const isComponent = node.tagType === 1 /* COMPONENT */;
4567
4547
  let properties = [];
4568
4548
  const mergeArgs = [];
4569
4549
  const runtimeDirectives = [];
4550
+ const hasChildren = children.length > 0;
4551
+ let shouldUseBlock = false;
4570
4552
  // patchFlag analysis
4571
4553
  let patchFlag = 0;
4572
4554
  let hasRef = false;
@@ -4629,15 +4611,20 @@ function buildProps(node, context, props = node.props, ssr = false) {
4629
4611
  const prop = props[i];
4630
4612
  if (prop.type === 6 /* ATTRIBUTE */) {
4631
4613
  const { loc, name, value } = prop;
4632
- let valueNode = createSimpleExpression(value ? value.content : '', true, value ? value.loc : loc);
4614
+ let isStatic = true;
4633
4615
  if (name === 'ref') {
4634
4616
  hasRef = true;
4617
+ if (context.scopes.vFor > 0) {
4618
+ properties.push(createObjectProperty(createSimpleExpression('ref_for', true), createSimpleExpression('true')));
4619
+ }
4635
4620
  // in inline mode there is no setupState object, so we can't use string
4636
4621
  // keys to set the ref. Instead, we need to transform it to pass the
4637
4622
  // actual ref instead.
4638
- if (context.inline && (value === null || value === void 0 ? void 0 : value.content)) {
4639
- valueNode = createFunctionExpression(['_value', '_refs']);
4640
- valueNode.body = createBlockStatement(processInlineRef(context, value.content));
4623
+ if (value &&
4624
+ context.inline &&
4625
+ context.bindingMetadata[value.content]) {
4626
+ isStatic = false;
4627
+ properties.push(createObjectProperty(createSimpleExpression('ref_key', true), createSimpleExpression(value.content, true, value.loc)));
4641
4628
  }
4642
4629
  }
4643
4630
  // skip is on <component>, or is="vue:xxx"
@@ -4647,7 +4634,7 @@ function buildProps(node, context, props = node.props, ssr = false) {
4647
4634
  (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context)))) {
4648
4635
  continue;
4649
4636
  }
4650
- properties.push(createObjectProperty(createSimpleExpression(name, true, getInnerRange(loc, 0, name.length)), valueNode));
4637
+ properties.push(createObjectProperty(createSimpleExpression(name, true, getInnerRange(loc, 0, name.length)), createSimpleExpression(value ? value.content : '', isStatic, value ? value.loc : loc)));
4651
4638
  }
4652
4639
  else {
4653
4640
  // directives
@@ -4668,7 +4655,7 @@ function buildProps(node, context, props = node.props, ssr = false) {
4668
4655
  // skip v-is and :is on <component>
4669
4656
  if (name === 'is' ||
4670
4657
  (isVBind &&
4671
- isBindKey(arg, 'is') &&
4658
+ isStaticArgOf(arg, 'is') &&
4672
4659
  (isComponentTag(tag) ||
4673
4660
  (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context))))) {
4674
4661
  continue;
@@ -4677,6 +4664,17 @@ function buildProps(node, context, props = node.props, ssr = false) {
4677
4664
  if (isVOn && ssr) {
4678
4665
  continue;
4679
4666
  }
4667
+ if (
4668
+ // #938: elements with dynamic keys should be forced into blocks
4669
+ (isVBind && isStaticArgOf(arg, 'key')) ||
4670
+ // inline before-update hooks need to force block so that it is invoked
4671
+ // before children
4672
+ (isVOn && hasChildren && isStaticArgOf(arg, 'vue:before-update'))) {
4673
+ shouldUseBlock = true;
4674
+ }
4675
+ if (isVBind && isStaticArgOf(arg, 'ref') && context.scopes.vFor > 0) {
4676
+ properties.push(createObjectProperty(createSimpleExpression('ref_for', true), createSimpleExpression('true')));
4677
+ }
4680
4678
  // special case for v-bind and v-on with no argument
4681
4679
  if (!arg && (isVBind || isVOn)) {
4682
4680
  hasDynamicKeys = true;
@@ -4750,14 +4748,13 @@ function buildProps(node, context, props = node.props, ssr = false) {
4750
4748
  else {
4751
4749
  // no built-in transform, this is a user custom directive.
4752
4750
  runtimeDirectives.push(prop);
4751
+ // custom dirs may use beforeUpdate so they need to force blocks
4752
+ // to ensure before-update gets called before children update
4753
+ if (hasChildren) {
4754
+ shouldUseBlock = true;
4755
+ }
4753
4756
  }
4754
4757
  }
4755
- if (prop.type === 6 /* ATTRIBUTE */ &&
4756
- prop.name === 'ref' &&
4757
- context.scopes.vFor > 0 &&
4758
- checkCompatEnabled("COMPILER_V_FOR_REF" /* COMPILER_V_FOR_REF */, context, prop.loc)) {
4759
- properties.push(createObjectProperty(createSimpleExpression('refInFor', true), createSimpleExpression('true', false)));
4760
- }
4761
4758
  }
4762
4759
  let propsExpression = undefined;
4763
4760
  // has v-bind="object" or v-on="object", wrap with mergeProps
@@ -4794,7 +4791,8 @@ function buildProps(node, context, props = node.props, ssr = false) {
4794
4791
  patchFlag |= 32 /* HYDRATE_EVENTS */;
4795
4792
  }
4796
4793
  }
4797
- if ((patchFlag === 0 || patchFlag === 32 /* HYDRATE_EVENTS */) &&
4794
+ if (!shouldUseBlock &&
4795
+ (patchFlag === 0 || patchFlag === 32 /* HYDRATE_EVENTS */) &&
4798
4796
  (hasRef || hasVnodeHook || runtimeDirectives.length > 0)) {
4799
4797
  patchFlag |= 512 /* NEED_PATCH */;
4800
4798
  }
@@ -4861,7 +4859,8 @@ function buildProps(node, context, props = node.props, ssr = false) {
4861
4859
  props: propsExpression,
4862
4860
  directives: runtimeDirectives,
4863
4861
  patchFlag,
4864
- dynamicPropNames
4862
+ dynamicPropNames,
4863
+ shouldUseBlock
4865
4864
  };
4866
4865
  }
4867
4866
  // Dedupe props in an object literal.
@@ -4955,22 +4954,7 @@ function stringifyDynamicPropNames(props) {
4955
4954
  return propsNamesString + `]`;
4956
4955
  }
4957
4956
  function isComponentTag(tag) {
4958
- return tag[0].toLowerCase() + tag.slice(1) === 'component';
4959
- }
4960
- function processInlineRef(context, raw) {
4961
- const body = [createSimpleExpression(`_refs['${raw}'] = _value`)];
4962
- const { bindingMetadata, helperString } = context;
4963
- const type = bindingMetadata[raw];
4964
- if (type === "setup-ref" /* SETUP_REF */) {
4965
- body.push(createSimpleExpression(`${raw}.value = _value`));
4966
- }
4967
- else if (type === "setup-maybe-ref" /* SETUP_MAYBE_REF */) {
4968
- body.push(createSimpleExpression(`${helperString(IS_REF)}(${raw}) && (${raw}.value = _value)`));
4969
- }
4970
- else if (type === "setup-let" /* SETUP_LET */) {
4971
- body.push(createSimpleExpression(`${helperString(IS_REF)}(${raw}) ? ${raw}.value = _value : ${raw} = _value`));
4972
- }
4973
- return body;
4957
+ return tag === 'component' || tag === 'Component';
4974
4958
  }
4975
4959
 
4976
4960
  Object.freeze({})
@@ -5036,7 +5020,7 @@ function processSlotOutlet(node, context) {
5036
5020
  }
5037
5021
  }
5038
5022
  else {
5039
- if (p.name === 'bind' && isBindKey(p.arg, 'name')) {
5023
+ if (p.name === 'bind' && isStaticArgOf(p.arg, 'name')) {
5040
5024
  if (p.exp)
5041
5025
  slotName = p.exp;
5042
5026
  }
@@ -5070,7 +5054,11 @@ const transformOn = (dir, node, context, augmentor) => {
5070
5054
  let eventName;
5071
5055
  if (arg.type === 4 /* SIMPLE_EXPRESSION */) {
5072
5056
  if (arg.isStatic) {
5073
- const rawName = arg.content;
5057
+ let rawName = arg.content;
5058
+ // TODO deprecate @vnodeXXX usage
5059
+ if (rawName.startsWith('vue:')) {
5060
+ rawName = `vnode-${rawName.slice(4)}`;
5061
+ }
5074
5062
  // for all event listeners, auto convert it to camelCase. See issue #2249
5075
5063
  eventName = createSimpleExpression(shared.toHandlerKey(shared.camelize(rawName)), true, arg.loc);
5076
5064
  }
@@ -5768,7 +5756,6 @@ exports.hasDynamicKeyVBind = hasDynamicKeyVBind;
5768
5756
  exports.hasScopeRef = hasScopeRef;
5769
5757
  exports.helperNameMap = helperNameMap;
5770
5758
  exports.injectProp = injectProp;
5771
- exports.isBindKey = isBindKey;
5772
5759
  exports.isBuiltInType = isBuiltInType;
5773
5760
  exports.isCoreComponent = isCoreComponent;
5774
5761
  exports.isFunctionType = isFunctionType;
@@ -5779,6 +5766,7 @@ exports.isMemberExpressionNode = isMemberExpressionNode;
5779
5766
  exports.isReferencedIdentifier = isReferencedIdentifier;
5780
5767
  exports.isSimpleIdentifier = isSimpleIdentifier;
5781
5768
  exports.isSlotOutlet = isSlotOutlet;
5769
+ exports.isStaticArgOf = isStaticArgOf;
5782
5770
  exports.isStaticExp = isStaticExp;
5783
5771
  exports.isStaticProperty = isStaticProperty;
5784
5772
  exports.isStaticPropertyKey = isStaticPropertyKey;
@@ -529,12 +529,12 @@ function findProp(node, name, dynamicOnly = false, allowEmpty = false) {
529
529
  }
530
530
  else if (p.name === 'bind' &&
531
531
  (p.exp || allowEmpty) &&
532
- isBindKey(p.arg, name)) {
532
+ isStaticArgOf(p.arg, name)) {
533
533
  return p;
534
534
  }
535
535
  }
536
536
  }
537
- function isBindKey(arg, name) {
537
+ function isStaticArgOf(arg, name) {
538
538
  return !!(arg && isStaticExp(arg) && arg.content === name);
539
539
  }
540
540
  function hasDynamicKeyVBind(node) {
@@ -577,7 +577,6 @@ function getUnnormalizedProps(props, callPath = []) {
577
577
  }
578
578
  function injectProp(node, prop, context) {
579
579
  let propsWithInjection;
580
- const originalProps = node.type === 13 /* VNODE_CALL */ ? node.props : node.arguments[2];
581
580
  /**
582
581
  * 1. mergeProps(...)
583
582
  * 2. toHandlers(...)
@@ -586,7 +585,7 @@ function injectProp(node, prop, context) {
586
585
  *
587
586
  * we need to get the real props before normalization
588
587
  */
589
- let props = originalProps;
588
+ let props = node.type === 13 /* VNODE_CALL */ ? node.props : node.arguments[2];
590
589
  let callPath = [];
591
590
  let parentCall;
592
591
  if (props &&
@@ -768,11 +767,6 @@ const deprecationData = {
768
767
  `data source.`,
769
768
  link: `https://v3.vuejs.org/guide/migration/v-if-v-for.html`
770
769
  },
771
- ["COMPILER_V_FOR_REF" /* COMPILER_V_FOR_REF */]: {
772
- message: `Ref usage on v-for no longer creates array ref values in Vue 3. ` +
773
- `Consider using function refs or refactor to avoid ref usage altogether.`,
774
- link: `https://v3.vuejs.org/guide/migration/array-refs.html`
775
- },
776
770
  ["COMPILER_NATIVE_TEMPLATE" /* COMPILER_NATIVE_TEMPLATE */]: {
777
771
  message: `<template> with no special directives will render as a native template ` +
778
772
  `element instead of its inner content in Vue 3.`
@@ -1266,7 +1260,7 @@ function isComponent(tag, props, context) {
1266
1260
  else if (
1267
1261
  // :is on plain element - only treat as component in compat mode
1268
1262
  p.name === 'bind' &&
1269
- isBindKey(p.arg, 'is') &&
1263
+ isStaticArgOf(p.arg, 'is') &&
1270
1264
  true &&
1271
1265
  checkCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context, p.loc)) {
1272
1266
  return true;
@@ -1623,15 +1617,6 @@ function isSingleElementRoot(root, child) {
1623
1617
  !isSlotOutlet(child));
1624
1618
  }
1625
1619
  function walk(node, context, doNotHoistNode = false) {
1626
- // Some transforms, e.g. transformAssetUrls from @vue/compiler-sfc, replaces
1627
- // static bindings with expressions. These expressions are guaranteed to be
1628
- // constant so they are still eligible for hoisting, but they are only
1629
- // available at runtime and therefore cannot be evaluated ahead of time.
1630
- // This is only a concern for pre-stringification (via transformHoist by
1631
- // @vue/compiler-dom), but doing it here allows us to perform only one full
1632
- // walk of the AST and allow `stringifyStatic` to stop walking as soon as its
1633
- // stringification threshold is met.
1634
- let canStringify = true;
1635
1620
  const { children } = node;
1636
1621
  const originalCount = children.length;
1637
1622
  let hoistedCount = 0;
@@ -1644,9 +1629,6 @@ function walk(node, context, doNotHoistNode = false) {
1644
1629
  ? 0 /* NOT_CONSTANT */
1645
1630
  : getConstantType(child, context);
1646
1631
  if (constantType > 0 /* NOT_CONSTANT */) {
1647
- if (constantType < 3 /* CAN_STRINGIFY */) {
1648
- canStringify = false;
1649
- }
1650
1632
  if (constantType >= 2 /* CAN_HOIST */) {
1651
1633
  child.codegenNode.patchFlag =
1652
1634
  -1 /* HOISTED */ + (``);
@@ -1677,17 +1659,10 @@ function walk(node, context, doNotHoistNode = false) {
1677
1659
  }
1678
1660
  }
1679
1661
  }
1680
- else if (child.type === 12 /* TEXT_CALL */) {
1681
- const contentType = getConstantType(child.content, context);
1682
- if (contentType > 0) {
1683
- if (contentType < 3 /* CAN_STRINGIFY */) {
1684
- canStringify = false;
1685
- }
1686
- if (contentType >= 2 /* CAN_HOIST */) {
1687
- child.codegenNode = context.hoist(child.codegenNode);
1688
- hoistedCount++;
1689
- }
1690
- }
1662
+ else if (child.type === 12 /* TEXT_CALL */ &&
1663
+ getConstantType(child.content, context) >= 2 /* CAN_HOIST */) {
1664
+ child.codegenNode = context.hoist(child.codegenNode);
1665
+ hoistedCount++;
1691
1666
  }
1692
1667
  // walk further
1693
1668
  if (child.type === 1 /* ELEMENT */) {
@@ -1711,7 +1686,7 @@ function walk(node, context, doNotHoistNode = false) {
1711
1686
  }
1712
1687
  }
1713
1688
  }
1714
- if (canStringify && hoistedCount && context.transformHoist) {
1689
+ if (hoistedCount && context.transformHoist) {
1715
1690
  context.transformHoist(children, context, node);
1716
1691
  }
1717
1692
  // all children were hoisted - the entire children array is hoistable.
@@ -1740,6 +1715,11 @@ function getConstantType(node, context) {
1740
1715
  if (codegenNode.type !== 13 /* VNODE_CALL */) {
1741
1716
  return 0 /* NOT_CONSTANT */;
1742
1717
  }
1718
+ if (codegenNode.isBlock &&
1719
+ node.tag !== 'svg' &&
1720
+ node.tag !== 'foreignObject') {
1721
+ return 0 /* NOT_CONSTANT */;
1722
+ }
1743
1723
  const flag = getPatchFlag(codegenNode);
1744
1724
  if (!flag) {
1745
1725
  let returnType = 3 /* CAN_STRINGIFY */;
@@ -1876,7 +1856,7 @@ function getGeneratedPropsConstantType(node, context) {
1876
1856
  else if (value.type === 14 /* JS_CALL_EXPRESSION */) {
1877
1857
  // some helper calls can be hoisted,
1878
1858
  // such as the `normalizeProps` generated by the compiler for pre-normalize class,
1879
- // in this case we need to respect the ConstantType of the helper's argments
1859
+ // in this case we need to respect the ConstantType of the helper's arguments
1880
1860
  valueType = getConstantTypeOfHelperCall(value, context);
1881
1861
  }
1882
1862
  else {
@@ -4275,10 +4255,7 @@ const transformElement = (node, context) => {
4275
4255
  // updates inside get proper isSVG flag at runtime. (#639, #643)
4276
4256
  // This is technically web-specific, but splitting the logic out of core
4277
4257
  // leads to too much unnecessary complexity.
4278
- (tag === 'svg' ||
4279
- tag === 'foreignObject' ||
4280
- // #938: elements with dynamic keys should be forced into blocks
4281
- findProp(node, 'key', true)));
4258
+ (tag === 'svg' || tag === 'foreignObject'));
4282
4259
  // props
4283
4260
  if (props.length > 0) {
4284
4261
  const propsBuildResult = buildProps(node, context);
@@ -4290,6 +4267,9 @@ const transformElement = (node, context) => {
4290
4267
  directives && directives.length
4291
4268
  ? createArrayExpression(directives.map(dir => buildDirectiveArgs(dir, context)))
4292
4269
  : undefined;
4270
+ if (propsBuildResult.shouldUseBlock) {
4271
+ shouldUseBlock = true;
4272
+ }
4293
4273
  }
4294
4274
  // children
4295
4275
  if (node.children.length > 0) {
@@ -4460,11 +4440,13 @@ function resolveSetupReference(name, context) {
4460
4440
  }
4461
4441
  }
4462
4442
  function buildProps(node, context, props = node.props, ssr = false) {
4463
- const { tag, loc: elementLoc } = node;
4443
+ const { tag, loc: elementLoc, children } = node;
4464
4444
  const isComponent = node.tagType === 1 /* COMPONENT */;
4465
4445
  let properties = [];
4466
4446
  const mergeArgs = [];
4467
4447
  const runtimeDirectives = [];
4448
+ const hasChildren = children.length > 0;
4449
+ let shouldUseBlock = false;
4468
4450
  // patchFlag analysis
4469
4451
  let patchFlag = 0;
4470
4452
  let hasRef = false;
@@ -4527,15 +4509,20 @@ function buildProps(node, context, props = node.props, ssr = false) {
4527
4509
  const prop = props[i];
4528
4510
  if (prop.type === 6 /* ATTRIBUTE */) {
4529
4511
  const { loc, name, value } = prop;
4530
- let valueNode = createSimpleExpression(value ? value.content : '', true, value ? value.loc : loc);
4512
+ let isStatic = true;
4531
4513
  if (name === 'ref') {
4532
4514
  hasRef = true;
4515
+ if (context.scopes.vFor > 0) {
4516
+ properties.push(createObjectProperty(createSimpleExpression('ref_for', true), createSimpleExpression('true')));
4517
+ }
4533
4518
  // in inline mode there is no setupState object, so we can't use string
4534
4519
  // keys to set the ref. Instead, we need to transform it to pass the
4535
4520
  // actual ref instead.
4536
- if (context.inline && (value === null || value === void 0 ? void 0 : value.content)) {
4537
- valueNode = createFunctionExpression(['_value', '_refs']);
4538
- valueNode.body = createBlockStatement(processInlineRef(context, value.content));
4521
+ if (value &&
4522
+ context.inline &&
4523
+ context.bindingMetadata[value.content]) {
4524
+ isStatic = false;
4525
+ properties.push(createObjectProperty(createSimpleExpression('ref_key', true), createSimpleExpression(value.content, true, value.loc)));
4539
4526
  }
4540
4527
  }
4541
4528
  // skip is on <component>, or is="vue:xxx"
@@ -4545,7 +4532,7 @@ function buildProps(node, context, props = node.props, ssr = false) {
4545
4532
  (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context)))) {
4546
4533
  continue;
4547
4534
  }
4548
- properties.push(createObjectProperty(createSimpleExpression(name, true, getInnerRange(loc, 0, name.length)), valueNode));
4535
+ properties.push(createObjectProperty(createSimpleExpression(name, true, getInnerRange(loc, 0, name.length)), createSimpleExpression(value ? value.content : '', isStatic, value ? value.loc : loc)));
4549
4536
  }
4550
4537
  else {
4551
4538
  // directives
@@ -4566,7 +4553,7 @@ function buildProps(node, context, props = node.props, ssr = false) {
4566
4553
  // skip v-is and :is on <component>
4567
4554
  if (name === 'is' ||
4568
4555
  (isVBind &&
4569
- isBindKey(arg, 'is') &&
4556
+ isStaticArgOf(arg, 'is') &&
4570
4557
  (isComponentTag(tag) ||
4571
4558
  (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context))))) {
4572
4559
  continue;
@@ -4575,6 +4562,17 @@ function buildProps(node, context, props = node.props, ssr = false) {
4575
4562
  if (isVOn && ssr) {
4576
4563
  continue;
4577
4564
  }
4565
+ if (
4566
+ // #938: elements with dynamic keys should be forced into blocks
4567
+ (isVBind && isStaticArgOf(arg, 'key')) ||
4568
+ // inline before-update hooks need to force block so that it is invoked
4569
+ // before children
4570
+ (isVOn && hasChildren && isStaticArgOf(arg, 'vue:before-update'))) {
4571
+ shouldUseBlock = true;
4572
+ }
4573
+ if (isVBind && isStaticArgOf(arg, 'ref') && context.scopes.vFor > 0) {
4574
+ properties.push(createObjectProperty(createSimpleExpression('ref_for', true), createSimpleExpression('true')));
4575
+ }
4578
4576
  // special case for v-bind and v-on with no argument
4579
4577
  if (!arg && (isVBind || isVOn)) {
4580
4578
  hasDynamicKeys = true;
@@ -4625,14 +4623,13 @@ function buildProps(node, context, props = node.props, ssr = false) {
4625
4623
  else {
4626
4624
  // no built-in transform, this is a user custom directive.
4627
4625
  runtimeDirectives.push(prop);
4626
+ // custom dirs may use beforeUpdate so they need to force blocks
4627
+ // to ensure before-update gets called before children update
4628
+ if (hasChildren) {
4629
+ shouldUseBlock = true;
4630
+ }
4628
4631
  }
4629
4632
  }
4630
- if (prop.type === 6 /* ATTRIBUTE */ &&
4631
- prop.name === 'ref' &&
4632
- context.scopes.vFor > 0 &&
4633
- checkCompatEnabled("COMPILER_V_FOR_REF" /* COMPILER_V_FOR_REF */, context, prop.loc)) {
4634
- properties.push(createObjectProperty(createSimpleExpression('refInFor', true), createSimpleExpression('true', false)));
4635
- }
4636
4633
  }
4637
4634
  let propsExpression = undefined;
4638
4635
  // has v-bind="object" or v-on="object", wrap with mergeProps
@@ -4669,7 +4666,8 @@ function buildProps(node, context, props = node.props, ssr = false) {
4669
4666
  patchFlag |= 32 /* HYDRATE_EVENTS */;
4670
4667
  }
4671
4668
  }
4672
- if ((patchFlag === 0 || patchFlag === 32 /* HYDRATE_EVENTS */) &&
4669
+ if (!shouldUseBlock &&
4670
+ (patchFlag === 0 || patchFlag === 32 /* HYDRATE_EVENTS */) &&
4673
4671
  (hasRef || hasVnodeHook || runtimeDirectives.length > 0)) {
4674
4672
  patchFlag |= 512 /* NEED_PATCH */;
4675
4673
  }
@@ -4736,7 +4734,8 @@ function buildProps(node, context, props = node.props, ssr = false) {
4736
4734
  props: propsExpression,
4737
4735
  directives: runtimeDirectives,
4738
4736
  patchFlag,
4739
- dynamicPropNames
4737
+ dynamicPropNames,
4738
+ shouldUseBlock
4740
4739
  };
4741
4740
  }
4742
4741
  // Dedupe props in an object literal.
@@ -4830,22 +4829,7 @@ function stringifyDynamicPropNames(props) {
4830
4829
  return propsNamesString + `]`;
4831
4830
  }
4832
4831
  function isComponentTag(tag) {
4833
- return tag[0].toLowerCase() + tag.slice(1) === 'component';
4834
- }
4835
- function processInlineRef(context, raw) {
4836
- const body = [createSimpleExpression(`_refs['${raw}'] = _value`)];
4837
- const { bindingMetadata, helperString } = context;
4838
- const type = bindingMetadata[raw];
4839
- if (type === "setup-ref" /* SETUP_REF */) {
4840
- body.push(createSimpleExpression(`${raw}.value = _value`));
4841
- }
4842
- else if (type === "setup-maybe-ref" /* SETUP_MAYBE_REF */) {
4843
- body.push(createSimpleExpression(`${helperString(IS_REF)}(${raw}) && (${raw}.value = _value)`));
4844
- }
4845
- else if (type === "setup-let" /* SETUP_LET */) {
4846
- body.push(createSimpleExpression(`${helperString(IS_REF)}(${raw}) ? ${raw}.value = _value : ${raw} = _value`));
4847
- }
4848
- return body;
4832
+ return tag === 'component' || tag === 'Component';
4849
4833
  }
4850
4834
 
4851
4835
  const cacheStringFunction = (fn) => {
@@ -4908,7 +4892,7 @@ function processSlotOutlet(node, context) {
4908
4892
  }
4909
4893
  }
4910
4894
  else {
4911
- if (p.name === 'bind' && isBindKey(p.arg, 'name')) {
4895
+ if (p.name === 'bind' && isStaticArgOf(p.arg, 'name')) {
4912
4896
  if (p.exp)
4913
4897
  slotName = p.exp;
4914
4898
  }
@@ -4942,7 +4926,11 @@ const transformOn = (dir, node, context, augmentor) => {
4942
4926
  let eventName;
4943
4927
  if (arg.type === 4 /* SIMPLE_EXPRESSION */) {
4944
4928
  if (arg.isStatic) {
4945
- const rawName = arg.content;
4929
+ let rawName = arg.content;
4930
+ // TODO deprecate @vnodeXXX usage
4931
+ if (rawName.startsWith('vue:')) {
4932
+ rawName = `vnode-${rawName.slice(4)}`;
4933
+ }
4946
4934
  // for all event listeners, auto convert it to camelCase. See issue #2249
4947
4935
  eventName = createSimpleExpression(shared.toHandlerKey(shared.camelize(rawName)), true, arg.loc);
4948
4936
  }
@@ -5639,7 +5627,6 @@ exports.hasDynamicKeyVBind = hasDynamicKeyVBind;
5639
5627
  exports.hasScopeRef = hasScopeRef;
5640
5628
  exports.helperNameMap = helperNameMap;
5641
5629
  exports.injectProp = injectProp;
5642
- exports.isBindKey = isBindKey;
5643
5630
  exports.isBuiltInType = isBuiltInType;
5644
5631
  exports.isCoreComponent = isCoreComponent;
5645
5632
  exports.isFunctionType = isFunctionType;
@@ -5650,6 +5637,7 @@ exports.isMemberExpressionNode = isMemberExpressionNode;
5650
5637
  exports.isReferencedIdentifier = isReferencedIdentifier;
5651
5638
  exports.isSimpleIdentifier = isSimpleIdentifier;
5652
5639
  exports.isSlotOutlet = isSlotOutlet;
5640
+ exports.isStaticArgOf = isStaticArgOf;
5653
5641
  exports.isStaticExp = isStaticExp;
5654
5642
  exports.isStaticProperty = isStaticProperty;
5655
5643
  exports.isStaticPropertyKey = isStaticPropertyKey;
@@ -105,6 +105,7 @@ export declare function buildProps(node: ElementNode, context: TransformContext,
105
105
  directives: DirectiveNode[];
106
106
  patchFlag: number;
107
107
  dynamicPropNames: string[];
108
+ shouldUseBlock: boolean;
108
109
  };
109
110
 
110
111
  export declare function buildSlots(node: ElementNode, context: TransformContext, buildSlotFn?: SlotFnBuilder): {
@@ -220,7 +221,6 @@ export declare const enum CompilerDeprecationTypes {
220
221
  COMPILER_V_BIND_OBJECT_ORDER = "COMPILER_V_BIND_OBJECT_ORDER",
221
222
  COMPILER_V_ON_NATIVE = "COMPILER_V_ON_NATIVE",
222
223
  COMPILER_V_IF_V_FOR_PRECEDENCE = "COMPILER_V_IF_V_FOR_PRECEDENCE",
223
- COMPILER_V_FOR_REF = "COMPILER_V_FOR_REF",
224
224
  COMPILER_NATIVE_TEMPLATE = "COMPILER_NATIVE_TEMPLATE",
225
225
  COMPILER_INLINE_TEMPLATE = "COMPILER_INLINE_TEMPLATE",
226
226
  COMPILER_FILTERS = "COMPILER_FILTER"
@@ -589,8 +589,6 @@ export declare const IS_MEMO_SAME: unique symbol;
589
589
 
590
590
  export declare const IS_REF: unique symbol;
591
591
 
592
- export declare function isBindKey(arg: DirectiveNode['arg'], name: string): boolean;
593
-
594
592
  export declare const isBuiltInType: (tag: string, expected: string) => boolean;
595
593
 
596
594
  export declare function isCoreComponent(tag: string): symbol | void;
@@ -617,6 +615,8 @@ export declare const isSimpleIdentifier: (name: string) => boolean;
617
615
 
618
616
  export declare function isSlotOutlet(node: RootNode | TemplateChildNode): node is SlotOutletNode;
619
617
 
618
+ export declare function isStaticArgOf(arg: DirectiveNode['arg'], name: string): boolean;
619
+
620
620
  export declare const isStaticExp: (p: JSChildNode) => p is SimpleExpressionNode;
621
621
 
622
622
  export declare const isStaticProperty: (node: Node_3) => node is ObjectProperty;
@@ -512,12 +512,12 @@ function findProp(node, name, dynamicOnly = false, allowEmpty = false) {
512
512
  }
513
513
  else if (p.name === 'bind' &&
514
514
  (p.exp || allowEmpty) &&
515
- isBindKey(p.arg, name)) {
515
+ isStaticArgOf(p.arg, name)) {
516
516
  return p;
517
517
  }
518
518
  }
519
519
  }
520
- function isBindKey(arg, name) {
520
+ function isStaticArgOf(arg, name) {
521
521
  return !!(arg && isStaticExp(arg) && arg.content === name);
522
522
  }
523
523
  function hasDynamicKeyVBind(node) {
@@ -560,7 +560,6 @@ function getUnnormalizedProps(props, callPath = []) {
560
560
  }
561
561
  function injectProp(node, prop, context) {
562
562
  let propsWithInjection;
563
- const originalProps = node.type === 13 /* VNODE_CALL */ ? node.props : node.arguments[2];
564
563
  /**
565
564
  * 1. mergeProps(...)
566
565
  * 2. toHandlers(...)
@@ -569,7 +568,7 @@ function injectProp(node, prop, context) {
569
568
  *
570
569
  * we need to get the real props before normalization
571
570
  */
572
- let props = originalProps;
571
+ let props = node.type === 13 /* VNODE_CALL */ ? node.props : node.arguments[2];
573
572
  let callPath = [];
574
573
  let parentCall;
575
574
  if (props &&
@@ -752,11 +751,6 @@ const deprecationData = {
752
751
  `data source.`,
753
752
  link: `https://v3.vuejs.org/guide/migration/v-if-v-for.html`
754
753
  },
755
- ["COMPILER_V_FOR_REF" /* COMPILER_V_FOR_REF */]: {
756
- message: `Ref usage on v-for no longer creates array ref values in Vue 3. ` +
757
- `Consider using function refs or refactor to avoid ref usage altogether.`,
758
- link: `https://v3.vuejs.org/guide/migration/array-refs.html`
759
- },
760
754
  ["COMPILER_NATIVE_TEMPLATE" /* COMPILER_NATIVE_TEMPLATE */]: {
761
755
  message: `<template> with no special directives will render as a native template ` +
762
756
  `element instead of its inner content in Vue 3.`
@@ -1276,7 +1270,7 @@ function isComponent(tag, props, context) {
1276
1270
  else if (
1277
1271
  // :is on plain element - only treat as component in compat mode
1278
1272
  p.name === 'bind' &&
1279
- isBindKey(p.arg, 'is') &&
1273
+ isStaticArgOf(p.arg, 'is') &&
1280
1274
  true &&
1281
1275
  checkCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context, p.loc)) {
1282
1276
  return true;
@@ -1636,15 +1630,6 @@ function isSingleElementRoot(root, child) {
1636
1630
  !isSlotOutlet(child));
1637
1631
  }
1638
1632
  function walk(node, context, doNotHoistNode = false) {
1639
- // Some transforms, e.g. transformAssetUrls from @vue/compiler-sfc, replaces
1640
- // static bindings with expressions. These expressions are guaranteed to be
1641
- // constant so they are still eligible for hoisting, but they are only
1642
- // available at runtime and therefore cannot be evaluated ahead of time.
1643
- // This is only a concern for pre-stringification (via transformHoist by
1644
- // @vue/compiler-dom), but doing it here allows us to perform only one full
1645
- // walk of the AST and allow `stringifyStatic` to stop walking as soon as its
1646
- // stringification threshold is met.
1647
- let canStringify = true;
1648
1633
  const { children } = node;
1649
1634
  const originalCount = children.length;
1650
1635
  let hoistedCount = 0;
@@ -1657,9 +1642,6 @@ function walk(node, context, doNotHoistNode = false) {
1657
1642
  ? 0 /* NOT_CONSTANT */
1658
1643
  : getConstantType(child, context);
1659
1644
  if (constantType > 0 /* NOT_CONSTANT */) {
1660
- if (constantType < 3 /* CAN_STRINGIFY */) {
1661
- canStringify = false;
1662
- }
1663
1645
  if (constantType >= 2 /* CAN_HOIST */) {
1664
1646
  child.codegenNode.patchFlag =
1665
1647
  -1 /* HOISTED */ + ((process.env.NODE_ENV !== 'production') ? ` /* HOISTED */` : ``);
@@ -1690,17 +1672,10 @@ function walk(node, context, doNotHoistNode = false) {
1690
1672
  }
1691
1673
  }
1692
1674
  }
1693
- else if (child.type === 12 /* TEXT_CALL */) {
1694
- const contentType = getConstantType(child.content, context);
1695
- if (contentType > 0) {
1696
- if (contentType < 3 /* CAN_STRINGIFY */) {
1697
- canStringify = false;
1698
- }
1699
- if (contentType >= 2 /* CAN_HOIST */) {
1700
- child.codegenNode = context.hoist(child.codegenNode);
1701
- hoistedCount++;
1702
- }
1703
- }
1675
+ else if (child.type === 12 /* TEXT_CALL */ &&
1676
+ getConstantType(child.content, context) >= 2 /* CAN_HOIST */) {
1677
+ child.codegenNode = context.hoist(child.codegenNode);
1678
+ hoistedCount++;
1704
1679
  }
1705
1680
  // walk further
1706
1681
  if (child.type === 1 /* ELEMENT */) {
@@ -1724,7 +1699,7 @@ function walk(node, context, doNotHoistNode = false) {
1724
1699
  }
1725
1700
  }
1726
1701
  }
1727
- if (canStringify && hoistedCount && context.transformHoist) {
1702
+ if (hoistedCount && context.transformHoist) {
1728
1703
  context.transformHoist(children, context, node);
1729
1704
  }
1730
1705
  // all children were hoisted - the entire children array is hoistable.
@@ -1753,6 +1728,11 @@ function getConstantType(node, context) {
1753
1728
  if (codegenNode.type !== 13 /* VNODE_CALL */) {
1754
1729
  return 0 /* NOT_CONSTANT */;
1755
1730
  }
1731
+ if (codegenNode.isBlock &&
1732
+ node.tag !== 'svg' &&
1733
+ node.tag !== 'foreignObject') {
1734
+ return 0 /* NOT_CONSTANT */;
1735
+ }
1756
1736
  const flag = getPatchFlag(codegenNode);
1757
1737
  if (!flag) {
1758
1738
  let returnType = 3 /* CAN_STRINGIFY */;
@@ -1890,7 +1870,7 @@ function getGeneratedPropsConstantType(node, context) {
1890
1870
  else if (value.type === 14 /* JS_CALL_EXPRESSION */) {
1891
1871
  // some helper calls can be hoisted,
1892
1872
  // such as the `normalizeProps` generated by the compiler for pre-normalize class,
1893
- // in this case we need to respect the ConstantType of the helper's argments
1873
+ // in this case we need to respect the ConstantType of the helper's arguments
1894
1874
  valueType = getConstantTypeOfHelperCall(value, context);
1895
1875
  }
1896
1876
  else {
@@ -3682,10 +3662,7 @@ const transformElement = (node, context) => {
3682
3662
  // updates inside get proper isSVG flag at runtime. (#639, #643)
3683
3663
  // This is technically web-specific, but splitting the logic out of core
3684
3664
  // leads to too much unnecessary complexity.
3685
- (tag === 'svg' ||
3686
- tag === 'foreignObject' ||
3687
- // #938: elements with dynamic keys should be forced into blocks
3688
- findProp(node, 'key', true)));
3665
+ (tag === 'svg' || tag === 'foreignObject'));
3689
3666
  // props
3690
3667
  if (props.length > 0) {
3691
3668
  const propsBuildResult = buildProps(node, context);
@@ -3697,6 +3674,9 @@ const transformElement = (node, context) => {
3697
3674
  directives && directives.length
3698
3675
  ? createArrayExpression(directives.map(dir => buildDirectiveArgs(dir, context)))
3699
3676
  : undefined;
3677
+ if (propsBuildResult.shouldUseBlock) {
3678
+ shouldUseBlock = true;
3679
+ }
3700
3680
  }
3701
3681
  // children
3702
3682
  if (node.children.length > 0) {
@@ -3828,11 +3808,13 @@ function resolveComponentType(node, context, ssr = false) {
3828
3808
  return toValidAssetId(tag, `component`);
3829
3809
  }
3830
3810
  function buildProps(node, context, props = node.props, ssr = false) {
3831
- const { tag, loc: elementLoc } = node;
3811
+ const { tag, loc: elementLoc, children } = node;
3832
3812
  const isComponent = node.tagType === 1 /* COMPONENT */;
3833
3813
  let properties = [];
3834
3814
  const mergeArgs = [];
3835
3815
  const runtimeDirectives = [];
3816
+ const hasChildren = children.length > 0;
3817
+ let shouldUseBlock = false;
3836
3818
  // patchFlag analysis
3837
3819
  let patchFlag = 0;
3838
3820
  let hasRef = false;
@@ -3895,9 +3877,12 @@ function buildProps(node, context, props = node.props, ssr = false) {
3895
3877
  const prop = props[i];
3896
3878
  if (prop.type === 6 /* ATTRIBUTE */) {
3897
3879
  const { loc, name, value } = prop;
3898
- let valueNode = createSimpleExpression(value ? value.content : '', true, value ? value.loc : loc);
3880
+ let isStatic = true;
3899
3881
  if (name === 'ref') {
3900
3882
  hasRef = true;
3883
+ if (context.scopes.vFor > 0) {
3884
+ properties.push(createObjectProperty(createSimpleExpression('ref_for', true), createSimpleExpression('true')));
3885
+ }
3901
3886
  }
3902
3887
  // skip is on <component>, or is="vue:xxx"
3903
3888
  if (name === 'is' &&
@@ -3906,7 +3891,7 @@ function buildProps(node, context, props = node.props, ssr = false) {
3906
3891
  (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context)))) {
3907
3892
  continue;
3908
3893
  }
3909
- properties.push(createObjectProperty(createSimpleExpression(name, true, getInnerRange(loc, 0, name.length)), valueNode));
3894
+ properties.push(createObjectProperty(createSimpleExpression(name, true, getInnerRange(loc, 0, name.length)), createSimpleExpression(value ? value.content : '', isStatic, value ? value.loc : loc)));
3910
3895
  }
3911
3896
  else {
3912
3897
  // directives
@@ -3927,7 +3912,7 @@ function buildProps(node, context, props = node.props, ssr = false) {
3927
3912
  // skip v-is and :is on <component>
3928
3913
  if (name === 'is' ||
3929
3914
  (isVBind &&
3930
- isBindKey(arg, 'is') &&
3915
+ isStaticArgOf(arg, 'is') &&
3931
3916
  (isComponentTag(tag) ||
3932
3917
  (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context))))) {
3933
3918
  continue;
@@ -3936,6 +3921,17 @@ function buildProps(node, context, props = node.props, ssr = false) {
3936
3921
  if (isVOn && ssr) {
3937
3922
  continue;
3938
3923
  }
3924
+ if (
3925
+ // #938: elements with dynamic keys should be forced into blocks
3926
+ (isVBind && isStaticArgOf(arg, 'key')) ||
3927
+ // inline before-update hooks need to force block so that it is invoked
3928
+ // before children
3929
+ (isVOn && hasChildren && isStaticArgOf(arg, 'vue:before-update'))) {
3930
+ shouldUseBlock = true;
3931
+ }
3932
+ if (isVBind && isStaticArgOf(arg, 'ref') && context.scopes.vFor > 0) {
3933
+ properties.push(createObjectProperty(createSimpleExpression('ref_for', true), createSimpleExpression('true')));
3934
+ }
3939
3935
  // special case for v-bind and v-on with no argument
3940
3936
  if (!arg && (isVBind || isVOn)) {
3941
3937
  hasDynamicKeys = true;
@@ -4009,14 +4005,13 @@ function buildProps(node, context, props = node.props, ssr = false) {
4009
4005
  else {
4010
4006
  // no built-in transform, this is a user custom directive.
4011
4007
  runtimeDirectives.push(prop);
4008
+ // custom dirs may use beforeUpdate so they need to force blocks
4009
+ // to ensure before-update gets called before children update
4010
+ if (hasChildren) {
4011
+ shouldUseBlock = true;
4012
+ }
4012
4013
  }
4013
4014
  }
4014
- if (prop.type === 6 /* ATTRIBUTE */ &&
4015
- prop.name === 'ref' &&
4016
- context.scopes.vFor > 0 &&
4017
- checkCompatEnabled("COMPILER_V_FOR_REF" /* COMPILER_V_FOR_REF */, context, prop.loc)) {
4018
- properties.push(createObjectProperty(createSimpleExpression('refInFor', true), createSimpleExpression('true', false)));
4019
- }
4020
4015
  }
4021
4016
  let propsExpression = undefined;
4022
4017
  // has v-bind="object" or v-on="object", wrap with mergeProps
@@ -4053,7 +4048,8 @@ function buildProps(node, context, props = node.props, ssr = false) {
4053
4048
  patchFlag |= 32 /* HYDRATE_EVENTS */;
4054
4049
  }
4055
4050
  }
4056
- if ((patchFlag === 0 || patchFlag === 32 /* HYDRATE_EVENTS */) &&
4051
+ if (!shouldUseBlock &&
4052
+ (patchFlag === 0 || patchFlag === 32 /* HYDRATE_EVENTS */) &&
4057
4053
  (hasRef || hasVnodeHook || runtimeDirectives.length > 0)) {
4058
4054
  patchFlag |= 512 /* NEED_PATCH */;
4059
4055
  }
@@ -4120,7 +4116,8 @@ function buildProps(node, context, props = node.props, ssr = false) {
4120
4116
  props: propsExpression,
4121
4117
  directives: runtimeDirectives,
4122
4118
  patchFlag,
4123
- dynamicPropNames
4119
+ dynamicPropNames,
4120
+ shouldUseBlock
4124
4121
  };
4125
4122
  }
4126
4123
  // Dedupe props in an object literal.
@@ -4208,7 +4205,7 @@ function stringifyDynamicPropNames(props) {
4208
4205
  return propsNamesString + `]`;
4209
4206
  }
4210
4207
  function isComponentTag(tag) {
4211
- return tag[0].toLowerCase() + tag.slice(1) === 'component';
4208
+ return tag === 'component' || tag === 'Component';
4212
4209
  }
4213
4210
 
4214
4211
  (process.env.NODE_ENV !== 'production')
@@ -4275,7 +4272,7 @@ function processSlotOutlet(node, context) {
4275
4272
  }
4276
4273
  }
4277
4274
  else {
4278
- if (p.name === 'bind' && isBindKey(p.arg, 'name')) {
4275
+ if (p.name === 'bind' && isStaticArgOf(p.arg, 'name')) {
4279
4276
  if (p.exp)
4280
4277
  slotName = p.exp;
4281
4278
  }
@@ -4309,7 +4306,11 @@ const transformOn = (dir, node, context, augmentor) => {
4309
4306
  let eventName;
4310
4307
  if (arg.type === 4 /* SIMPLE_EXPRESSION */) {
4311
4308
  if (arg.isStatic) {
4312
- const rawName = arg.content;
4309
+ let rawName = arg.content;
4310
+ // TODO deprecate @vnodeXXX usage
4311
+ if (rawName.startsWith('vue:')) {
4312
+ rawName = `vnode-${rawName.slice(4)}`;
4313
+ }
4313
4314
  // for all event listeners, auto convert it to camelCase. See issue #2249
4314
4315
  eventName = createSimpleExpression(toHandlerKey(camelize$1(rawName)), true, arg.loc);
4315
4316
  }
@@ -4854,4 +4855,4 @@ function baseCompile(template, options = {}) {
4854
4855
 
4855
4856
  const noopDirectiveTransform = () => ({ props: [] });
4856
4857
 
4857
- export { BASE_TRANSITION, CAMELIZE, CAPITALIZE, CREATE_BLOCK, CREATE_COMMENT, CREATE_ELEMENT_BLOCK, CREATE_ELEMENT_VNODE, CREATE_SLOTS, CREATE_STATIC, CREATE_TEXT, CREATE_VNODE, FRAGMENT, GUARD_REACTIVE_PROPS, IS_MEMO_SAME, IS_REF, KEEP_ALIVE, MERGE_PROPS, NORMALIZE_CLASS, NORMALIZE_PROPS, NORMALIZE_STYLE, OPEN_BLOCK, POP_SCOPE_ID, PUSH_SCOPE_ID, RENDER_LIST, RENDER_SLOT, RESOLVE_COMPONENT, RESOLVE_DIRECTIVE, RESOLVE_DYNAMIC_COMPONENT, RESOLVE_FILTER, SET_BLOCK_TRACKING, SUSPENSE, TELEPORT, TO_DISPLAY_STRING, TO_HANDLERS, TO_HANDLER_KEY, UNREF, WITH_CTX, WITH_DIRECTIVES, WITH_MEMO, advancePositionWithClone, advancePositionWithMutation, assert, baseCompile, baseParse, buildProps, buildSlots, checkCompatEnabled, createArrayExpression, createAssignmentExpression, createBlockStatement, createCacheExpression, createCallExpression, createCompilerError, createCompoundExpression, createConditionalExpression, createForLoopParams, createFunctionExpression, createIfStatement, createInterpolation, createObjectExpression, createObjectProperty, createReturnStatement, createRoot, createSequenceExpression, createSimpleExpression, createStructuralDirectiveTransform, createTemplateLiteral, createTransformContext, createVNodeCall, extractIdentifiers, findDir, findProp, generate, getBaseTransformPreset, getInnerRange, getMemoedVNodeCall, getVNodeBlockHelper, getVNodeHelper, hasDynamicKeyVBind, hasScopeRef, helperNameMap, injectProp, isBindKey, isBuiltInType, isCoreComponent, isFunctionType, isInDestructureAssignment, isMemberExpression, isMemberExpressionBrowser, isMemberExpressionNode, isReferencedIdentifier, isSimpleIdentifier, isSlotOutlet, isStaticExp, isStaticProperty, isStaticPropertyKey, isTemplateNode, isText, isVSlot, locStub, makeBlock, noopDirectiveTransform, processExpression, processFor, processIf, processSlotOutlet, registerRuntimeHelpers, resolveComponentType, toValidAssetId, trackSlotScopes, trackVForSlotScopes, transform, transformBind, transformElement, transformExpression, transformModel, transformOn, traverseNode, walkBlockDeclarations, walkFunctionParams, walkIdentifiers, warnDeprecation };
4858
+ export { BASE_TRANSITION, CAMELIZE, CAPITALIZE, CREATE_BLOCK, CREATE_COMMENT, CREATE_ELEMENT_BLOCK, CREATE_ELEMENT_VNODE, CREATE_SLOTS, CREATE_STATIC, CREATE_TEXT, CREATE_VNODE, FRAGMENT, GUARD_REACTIVE_PROPS, IS_MEMO_SAME, IS_REF, KEEP_ALIVE, MERGE_PROPS, NORMALIZE_CLASS, NORMALIZE_PROPS, NORMALIZE_STYLE, OPEN_BLOCK, POP_SCOPE_ID, PUSH_SCOPE_ID, RENDER_LIST, RENDER_SLOT, RESOLVE_COMPONENT, RESOLVE_DIRECTIVE, RESOLVE_DYNAMIC_COMPONENT, RESOLVE_FILTER, SET_BLOCK_TRACKING, SUSPENSE, TELEPORT, TO_DISPLAY_STRING, TO_HANDLERS, TO_HANDLER_KEY, UNREF, WITH_CTX, WITH_DIRECTIVES, WITH_MEMO, advancePositionWithClone, advancePositionWithMutation, assert, baseCompile, baseParse, buildProps, buildSlots, checkCompatEnabled, createArrayExpression, createAssignmentExpression, createBlockStatement, createCacheExpression, createCallExpression, createCompilerError, createCompoundExpression, createConditionalExpression, createForLoopParams, createFunctionExpression, createIfStatement, createInterpolation, createObjectExpression, createObjectProperty, createReturnStatement, createRoot, createSequenceExpression, createSimpleExpression, createStructuralDirectiveTransform, createTemplateLiteral, createTransformContext, createVNodeCall, extractIdentifiers, findDir, findProp, generate, getBaseTransformPreset, getInnerRange, getMemoedVNodeCall, getVNodeBlockHelper, getVNodeHelper, hasDynamicKeyVBind, hasScopeRef, helperNameMap, injectProp, isBuiltInType, isCoreComponent, isFunctionType, isInDestructureAssignment, isMemberExpression, isMemberExpressionBrowser, isMemberExpressionNode, isReferencedIdentifier, isSimpleIdentifier, isSlotOutlet, isStaticArgOf, isStaticExp, isStaticProperty, isStaticPropertyKey, isTemplateNode, isText, isVSlot, locStub, makeBlock, noopDirectiveTransform, processExpression, processFor, processIf, processSlotOutlet, registerRuntimeHelpers, resolveComponentType, toValidAssetId, trackSlotScopes, trackVForSlotScopes, transform, transformBind, transformElement, transformExpression, transformModel, transformOn, traverseNode, walkBlockDeclarations, walkFunctionParams, walkIdentifiers, warnDeprecation };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vue/compiler-core",
3
- "version": "3.2.21",
3
+ "version": "3.2.25",
4
4
  "description": "@vue/compiler-core",
5
5
  "main": "index.js",
6
6
  "module": "dist/compiler-core.esm-bundler.js",
@@ -32,12 +32,12 @@
32
32
  },
33
33
  "homepage": "https://github.com/vuejs/vue-next/tree/master/packages/compiler-core#readme",
34
34
  "dependencies": {
35
- "@vue/shared": "3.2.21",
36
- "@babel/parser": "^7.15.0",
35
+ "@vue/shared": "3.2.25",
36
+ "@babel/parser": "^7.16.4",
37
37
  "estree-walker": "^2.0.2",
38
38
  "source-map": "^0.6.1"
39
39
  },
40
40
  "devDependencies": {
41
- "@babel/types": "^7.15.0"
41
+ "@babel/types": "^7.16.0"
42
42
  }
43
43
  }