@vue/compiler-core 3.0.7 → 3.0.11

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.
@@ -348,7 +348,7 @@ function isCoreComponent(tag) {
348
348
  }
349
349
  const nonIdentifierRE = /^\d|[^\$\w]/;
350
350
  const isSimpleIdentifier = (name) => !nonIdentifierRE.test(name);
351
- const memberExpRE = /^[A-Za-z_$][\w$]*(?:\s*\.\s*[A-Za-z_$][\w$]*|\[[^\]]+\])*$/;
351
+ const memberExpRE = /^[A-Za-z_$\xA0-\uFFFF][\w$\xA0-\uFFFF]*(?:\s*\.\s*[A-Za-z_$\xA0-\uFFFF][\w$\xA0-\uFFFF]*|\[[^\]]+\])*$/;
352
352
  const isMemberExpression = (path) => {
353
353
  if (!path)
354
354
  return false;
@@ -677,7 +677,7 @@ function parseChildren(context, mode, ancestors) {
677
677
  // Whitespace management for more efficient output
678
678
  // (same as v2 whitespace: 'condense')
679
679
  let removedWhitespace = false;
680
- if (mode !== 2 /* RAWTEXT */) {
680
+ if (mode !== 2 /* RAWTEXT */ && mode !== 1 /* RCDATA */) {
681
681
  for (let i = 0; i < nodes.length; i++) {
682
682
  const node = nodes[i];
683
683
  if (!context.inPre && node.type === 2 /* TEXT */) {
@@ -987,7 +987,7 @@ function parseAttribute(context, nameSet) {
987
987
  let arg;
988
988
  if (match[2]) {
989
989
  const isSlot = dirName === 'slot';
990
- const startOffset = name.indexOf(match[2]);
990
+ const startOffset = name.lastIndexOf(match[2]);
991
991
  const loc = getSelection(context, getNewPosition(context, start, startOffset), getNewPosition(context, start, startOffset + match[2].length + ((isSlot && match[3]) || '').length));
992
992
  let content = match[2];
993
993
  let isStatic = true;
@@ -1308,7 +1308,14 @@ function walk(node, context, doNotHoistNode = false) {
1308
1308
  }
1309
1309
  // walk further
1310
1310
  if (child.type === 1 /* ELEMENT */) {
1311
+ const isComponent = child.tagType === 1 /* COMPONENT */;
1312
+ if (isComponent) {
1313
+ context.scopes.vSlot++;
1314
+ }
1311
1315
  walk(child, context);
1316
+ if (isComponent) {
1317
+ context.scopes.vSlot--;
1318
+ }
1312
1319
  }
1313
1320
  else if (child.type === 11 /* FOR */) {
1314
1321
  // Do not hoist v-for single child because it has to be a block
@@ -1390,6 +1397,8 @@ function getConstantType(node, context) {
1390
1397
  // static then they don't need to be blocks since there will be no
1391
1398
  // nested updates.
1392
1399
  if (codegenNode.isBlock) {
1400
+ context.removeHelper(OPEN_BLOCK);
1401
+ context.removeHelper(CREATE_BLOCK);
1393
1402
  codegenNode.isBlock = false;
1394
1403
  context.helper(CREATE_VNODE);
1395
1404
  }
@@ -1471,7 +1480,7 @@ function getPatchFlag(node) {
1471
1480
  return flag ? parseInt(flag, 10) : undefined;
1472
1481
  }
1473
1482
 
1474
- function createTransformContext(root, { filename = '', prefixIdentifiers = false, hoistStatic = false, cacheHandlers = false, nodeTransforms = [], directiveTransforms = {}, transformHoist = null, isBuiltInComponent = shared.NOOP, isCustomElement = shared.NOOP, expressionPlugins = [], scopeId = null, ssr = false, ssrCssVars = ``, bindingMetadata = shared.EMPTY_OBJ, inline = false, isTS = false, onError = defaultOnError }) {
1483
+ function createTransformContext(root, { filename = '', prefixIdentifiers = false, hoistStatic = false, cacheHandlers = false, nodeTransforms = [], directiveTransforms = {}, transformHoist = null, isBuiltInComponent = shared.NOOP, isCustomElement = shared.NOOP, expressionPlugins = [], scopeId = null, slotted = true, ssr = false, ssrCssVars = ``, bindingMetadata = shared.EMPTY_OBJ, inline = false, isTS = false, onError = defaultOnError }) {
1475
1484
  const nameMatch = filename.replace(/\?.*$/, '').match(/([^/\\]+)\.\w+$/);
1476
1485
  const context = {
1477
1486
  // options
@@ -1486,6 +1495,7 @@ function createTransformContext(root, { filename = '', prefixIdentifiers = false
1486
1495
  isCustomElement,
1487
1496
  expressionPlugins,
1488
1497
  scopeId,
1498
+ slotted,
1489
1499
  ssr,
1490
1500
  ssrCssVars,
1491
1501
  bindingMetadata,
@@ -1494,7 +1504,7 @@ function createTransformContext(root, { filename = '', prefixIdentifiers = false
1494
1504
  onError,
1495
1505
  // state
1496
1506
  root,
1497
- helpers: new Set(),
1507
+ helpers: new Map(),
1498
1508
  components: new Set(),
1499
1509
  directives: new Set(),
1500
1510
  hoists: [],
@@ -1514,9 +1524,22 @@ function createTransformContext(root, { filename = '', prefixIdentifiers = false
1514
1524
  childIndex: 0,
1515
1525
  // methods
1516
1526
  helper(name) {
1517
- context.helpers.add(name);
1527
+ const count = context.helpers.get(name) || 0;
1528
+ context.helpers.set(name, count + 1);
1518
1529
  return name;
1519
1530
  },
1531
+ removeHelper(name) {
1532
+ const count = context.helpers.get(name);
1533
+ if (count) {
1534
+ const currentCount = count - 1;
1535
+ if (!currentCount) {
1536
+ context.helpers.delete(name);
1537
+ }
1538
+ else {
1539
+ context.helpers.set(name, currentCount);
1540
+ }
1541
+ }
1542
+ },
1520
1543
  helperString(name) {
1521
1544
  return `_${helperNameMap[context.helper(name)]}`;
1522
1545
  },
@@ -1620,7 +1643,7 @@ function transform(root, options) {
1620
1643
  createRootCodegen(root, context);
1621
1644
  }
1622
1645
  // finalize meta information
1623
- root.helpers = [...context.helpers];
1646
+ root.helpers = [...context.helpers.keys()];
1624
1647
  root.components = [...context.components];
1625
1648
  root.directives = [...context.directives];
1626
1649
  root.imports = context.imports;
@@ -1629,7 +1652,7 @@ function transform(root, options) {
1629
1652
  root.cached = context.cached;
1630
1653
  }
1631
1654
  function createRootCodegen(root, context) {
1632
- const { helper } = context;
1655
+ const { helper, removeHelper } = context;
1633
1656
  const { children } = root;
1634
1657
  if (children.length === 1) {
1635
1658
  const child = children[0];
@@ -1639,9 +1662,12 @@ function createRootCodegen(root, context) {
1639
1662
  // SimpleExpressionNode
1640
1663
  const codegenNode = child.codegenNode;
1641
1664
  if (codegenNode.type === 13 /* VNODE_CALL */) {
1642
- codegenNode.isBlock = true;
1643
- helper(OPEN_BLOCK);
1644
- helper(CREATE_BLOCK);
1665
+ if (!codegenNode.isBlock) {
1666
+ removeHelper(CREATE_VNODE);
1667
+ codegenNode.isBlock = true;
1668
+ helper(OPEN_BLOCK);
1669
+ helper(CREATE_BLOCK);
1670
+ }
1645
1671
  }
1646
1672
  root.codegenNode = codegenNode;
1647
1673
  }
@@ -1771,6 +1797,7 @@ function createStructuralDirectiveTransform(name, fn) {
1771
1797
  }
1772
1798
 
1773
1799
  const PURE_ANNOTATION = `/*#__PURE__*/`;
1800
+ const WITH_ID = `_withId`;
1774
1801
  function createCodegenContext(ast, { mode = 'function', prefixIdentifiers = mode === 'module', sourceMap: sourceMap$1 = false, filename = `template.vue.html`, scopeId = null, optimizeImports = false, runtimeGlobalName = `Vue`, runtimeModuleName = `vue`, ssr = false }) {
1775
1802
  const context = {
1776
1803
  mode,
@@ -1882,13 +1909,12 @@ function generate(ast, options = {}) {
1882
1909
  const signature = options.isTS
1883
1910
  ? args.map(arg => `${arg}: any`).join(',')
1884
1911
  : args.join(', ');
1885
- if (genScopeId) {
1886
- if (isSetupInlined) {
1887
- push(`${PURE_ANNOTATION}_withId(`);
1888
- }
1889
- else {
1890
- push(`const ${functionName} = ${PURE_ANNOTATION}_withId(`);
1891
- }
1912
+ if (genScopeId && !isSetupInlined) {
1913
+ // root-level _withId wrapping is no longer necessary after 3.0.8 and is
1914
+ // a noop, it's only kept so that code compiled with 3.0.8+ can run with
1915
+ // runtime < 3.0.8.
1916
+ // TODO: consider removing in 3.1
1917
+ push(`const ${functionName} = ${PURE_ANNOTATION}${WITH_ID}(`);
1892
1918
  }
1893
1919
  if (isSetupInlined || genScopeId) {
1894
1920
  push(`(${signature}) => {`);
@@ -1949,7 +1975,7 @@ function generate(ast, options = {}) {
1949
1975
  }
1950
1976
  deindent();
1951
1977
  push(`}`);
1952
- if (genScopeId) {
1978
+ if (genScopeId && !isSetupInlined) {
1953
1979
  push(`)`);
1954
1980
  }
1955
1981
  return {
@@ -2007,7 +2033,7 @@ function genFunctionPreamble(ast, context) {
2007
2033
  push(`return `);
2008
2034
  }
2009
2035
  function genModulePreamble(ast, context, genScopeId, inline) {
2010
- const { push, helper, newline, scopeId, optimizeImports, runtimeModuleName } = context;
2036
+ const { push, newline, optimizeImports, runtimeModuleName, scopeId, helper } = context;
2011
2037
  if (genScopeId) {
2012
2038
  ast.helpers.push(WITH_SCOPE_ID);
2013
2039
  if (ast.hoists.length) {
@@ -2044,8 +2070,11 @@ function genModulePreamble(ast, context, genScopeId, inline) {
2044
2070
  genImports(ast.imports, context);
2045
2071
  newline();
2046
2072
  }
2073
+ // we technically don't need this anymore since `withCtx` already sets the
2074
+ // correct scopeId, but this is necessary for backwards compat
2075
+ // TODO: consider removing in 3.1
2047
2076
  if (genScopeId) {
2048
- push(`const _withId = ${PURE_ANNOTATION}${helper(WITH_SCOPE_ID)}("${scopeId}")`);
2077
+ push(`const ${WITH_ID} = ${PURE_ANNOTATION}${helper(WITH_SCOPE_ID)}("${scopeId}")`);
2049
2078
  newline();
2050
2079
  }
2051
2080
  genHoists(ast.hoists, context);
@@ -2057,8 +2086,13 @@ function genModulePreamble(ast, context, genScopeId, inline) {
2057
2086
  function genAssets(assets, type, { helper, push, newline }) {
2058
2087
  const resolver = helper(type === 'component' ? RESOLVE_COMPONENT : RESOLVE_DIRECTIVE);
2059
2088
  for (let i = 0; i < assets.length; i++) {
2060
- const id = assets[i];
2061
- push(`const ${toValidAssetId(id, type)} = ${resolver}(${JSON.stringify(id)})`);
2089
+ let id = assets[i];
2090
+ // potential component implicit self-reference inferred from SFC filename
2091
+ const maybeSelfReference = id.endsWith('__self');
2092
+ if (maybeSelfReference) {
2093
+ id = id.slice(0, -6);
2094
+ }
2095
+ push(`const ${toValidAssetId(id, type)} = ${resolver}(${JSON.stringify(id)}${maybeSelfReference ? `, true` : ``})`);
2062
2096
  if (i < assets.length - 1) {
2063
2097
  newline();
2064
2098
  }
@@ -2361,11 +2395,9 @@ function genFunctionExpression(node, context) {
2361
2395
  const { params, returns, body, newline, isSlot } = node;
2362
2396
  // slot functions also need to push scopeId before rendering its content
2363
2397
  const genScopeId = isSlot && scopeId != null && mode !== 'function';
2364
- if (genScopeId) {
2365
- push(`_withId(`);
2366
- }
2367
- else if (isSlot) {
2368
- push(`_${helperNameMap[WITH_CTX]}(`);
2398
+ if (isSlot) {
2399
+ // wrap slot functions with owner context
2400
+ push(genScopeId ? `${WITH_ID}(` : `_${helperNameMap[WITH_CTX]}(`);
2369
2401
  }
2370
2402
  push(`(`, node);
2371
2403
  if (shared.isArray(params)) {
@@ -2397,7 +2429,7 @@ function genFunctionExpression(node, context) {
2397
2429
  deindent();
2398
2430
  push(`}`);
2399
2431
  }
2400
- if (genScopeId || isSlot) {
2432
+ if (isSlot) {
2401
2433
  push(`)`);
2402
2434
  }
2403
2435
  }
@@ -3013,7 +3045,7 @@ function createCodegenNodeForBranch(branch, keyIndex, context) {
3013
3045
  }
3014
3046
  }
3015
3047
  function createChildrenCodegenNode(branch, keyIndex, context) {
3016
- const { helper } = context;
3048
+ const { helper, removeHelper } = context;
3017
3049
  const keyProperty = createObjectProperty(`key`, createSimpleExpression(`${keyIndex}`, false, locStub, 2 /* CAN_HOIST */));
3018
3050
  const { children } = branch;
3019
3051
  const firstChild = children[0];
@@ -3026,16 +3058,23 @@ function createChildrenCodegenNode(branch, keyIndex, context) {
3026
3058
  return vnodeCall;
3027
3059
  }
3028
3060
  else {
3029
- return createVNodeCall(context, helper(FRAGMENT), createObjectExpression([keyProperty]), children, 64 /* STABLE_FRAGMENT */ +
3030
- (` /* ${shared.PatchFlagNames[64 /* STABLE_FRAGMENT */]} */`
3031
- ), undefined, undefined, true, false, branch.loc);
3061
+ let patchFlag = 64 /* STABLE_FRAGMENT */;
3062
+ let patchFlagText = shared.PatchFlagNames[64 /* STABLE_FRAGMENT */];
3063
+ // check if the fragment actually contains a single valid child with
3064
+ // the rest being comments
3065
+ if (children.filter(c => c.type !== 3 /* COMMENT */).length === 1) {
3066
+ patchFlag |= 2048 /* DEV_ROOT_FRAGMENT */;
3067
+ patchFlagText += `, ${shared.PatchFlagNames[2048 /* DEV_ROOT_FRAGMENT */]}`;
3068
+ }
3069
+ return createVNodeCall(context, helper(FRAGMENT), createObjectExpression([keyProperty]), children, patchFlag + (` /* ${patchFlagText} */` ), undefined, undefined, true, false, branch.loc);
3032
3070
  }
3033
3071
  }
3034
3072
  else {
3035
3073
  const vnodeCall = firstChild
3036
3074
  .codegenNode;
3037
3075
  // Change createVNode to createBlock.
3038
- if (vnodeCall.type === 13 /* VNODE_CALL */) {
3076
+ if (vnodeCall.type === 13 /* VNODE_CALL */ && !vnodeCall.isBlock) {
3077
+ removeHelper(CREATE_VNODE);
3039
3078
  vnodeCall.isBlock = true;
3040
3079
  helper(OPEN_BLOCK);
3041
3080
  helper(CREATE_BLOCK);
@@ -3086,7 +3125,7 @@ function getParentCondition(node) {
3086
3125
  }
3087
3126
 
3088
3127
  const transformFor = createStructuralDirectiveTransform('for', (node, dir, context) => {
3089
- const { helper } = context;
3128
+ const { helper, removeHelper } = context;
3090
3129
  return processFor(node, dir, context, forNode => {
3091
3130
  // create the loop render function expression now, and add the
3092
3131
  // iterator on exit after all children have been traversed
@@ -3166,6 +3205,17 @@ const transformFor = createStructuralDirectiveTransform('for', (node, dir, conte
3166
3205
  if (isTemplate && keyProperty) {
3167
3206
  injectProp(childBlock, keyProperty, context);
3168
3207
  }
3208
+ if (childBlock.isBlock !== !isStableFragment) {
3209
+ if (childBlock.isBlock) {
3210
+ // switch from block to vnode
3211
+ removeHelper(OPEN_BLOCK);
3212
+ removeHelper(CREATE_BLOCK);
3213
+ }
3214
+ else {
3215
+ // switch from vnode to block
3216
+ removeHelper(CREATE_VNODE);
3217
+ }
3218
+ }
3169
3219
  childBlock.isBlock = !isStableFragment;
3170
3220
  if (childBlock.isBlock) {
3171
3221
  helper(OPEN_BLOCK);
@@ -3533,12 +3583,23 @@ function buildDynamicSlot(name, fn) {
3533
3583
  function hasForwardedSlots(children) {
3534
3584
  for (let i = 0; i < children.length; i++) {
3535
3585
  const child = children[i];
3536
- if (child.type === 1 /* ELEMENT */) {
3537
- if (child.tagType === 2 /* SLOT */ ||
3538
- (child.tagType === 0 /* ELEMENT */ &&
3539
- hasForwardedSlots(child.children))) {
3540
- return true;
3541
- }
3586
+ switch (child.type) {
3587
+ case 1 /* ELEMENT */:
3588
+ if (child.tagType === 2 /* SLOT */ ||
3589
+ (child.tagType === 0 /* ELEMENT */ &&
3590
+ hasForwardedSlots(child.children))) {
3591
+ return true;
3592
+ }
3593
+ break;
3594
+ case 9 /* IF */:
3595
+ if (hasForwardedSlots(child.branches))
3596
+ return true;
3597
+ break;
3598
+ case 10 /* IF_BRANCH */:
3599
+ case 11 /* FOR */:
3600
+ if (hasForwardedSlots(child.children))
3601
+ return true;
3602
+ break;
3542
3603
  }
3543
3604
  }
3544
3605
  return false;
@@ -3549,14 +3610,15 @@ function hasForwardedSlots(children) {
3549
3610
  const directiveImportMap = new WeakMap();
3550
3611
  // generate a JavaScript AST for this element's codegen
3551
3612
  const transformElement = (node, context) => {
3552
- if (!(node.type === 1 /* ELEMENT */ &&
3553
- (node.tagType === 0 /* ELEMENT */ ||
3554
- node.tagType === 1 /* COMPONENT */))) {
3555
- return;
3556
- }
3557
3613
  // perform the work on exit, after all child expressions have been
3558
3614
  // processed and merged.
3559
3615
  return function postTransformElement() {
3616
+ node = context.currentNode;
3617
+ if (!(node.type === 1 /* ELEMENT */ &&
3618
+ (node.tagType === 0 /* ELEMENT */ ||
3619
+ node.tagType === 1 /* COMPONENT */))) {
3620
+ return;
3621
+ }
3560
3622
  const { tag, props } = node;
3561
3623
  const isComponent = node.tagType === 1 /* COMPONENT */;
3562
3624
  // The goal of the transform is to create a codegenNode implementing the
@@ -3680,7 +3742,9 @@ const transformElement = (node, context) => {
3680
3742
  function resolveComponentType(node, context, ssr = false) {
3681
3743
  const { tag } = node;
3682
3744
  // 1. dynamic component
3683
- const isProp = node.tag === 'component' ? findProp(node, 'is') : findDir(node, 'is');
3745
+ const isProp = isComponentTag(tag)
3746
+ ? findProp(node, 'is')
3747
+ : findDir(node, 'is');
3684
3748
  if (isProp) {
3685
3749
  const exp = isProp.type === 6 /* ATTRIBUTE */
3686
3750
  ? isProp.value && createSimpleExpression(isProp.value.content, true)
@@ -3710,12 +3774,14 @@ function resolveComponentType(node, context, ssr = false) {
3710
3774
  }
3711
3775
  }
3712
3776
  // 4. Self referencing component (inferred from filename)
3713
- if (context.selfName) {
3714
- if (shared.capitalize(shared.camelize(tag)) === context.selfName) {
3715
- context.helper(RESOLVE_COMPONENT);
3716
- context.components.add(`_self`);
3717
- return toValidAssetId(`_self`, `component`);
3718
- }
3777
+ if (context.selfName &&
3778
+ shared.capitalize(shared.camelize(tag)) === context.selfName) {
3779
+ context.helper(RESOLVE_COMPONENT);
3780
+ // codegen.ts has special check for __self postfix when generating
3781
+ // component imports, which will pass additional `maybeSelfReference` flag
3782
+ // to `resolveComponent`.
3783
+ context.components.add(tag + `__self`);
3784
+ return toValidAssetId(tag, `component`);
3719
3785
  }
3720
3786
  // 5. user component (resolve)
3721
3787
  context.helper(RESOLVE_COMPONENT);
@@ -3724,7 +3790,7 @@ function resolveComponentType(node, context, ssr = false) {
3724
3790
  }
3725
3791
  function resolveSetupReference(name, context) {
3726
3792
  const bindings = context.bindingMetadata;
3727
- if (!bindings) {
3793
+ if (!bindings || bindings.__isScriptSetup === false) {
3728
3794
  return;
3729
3795
  }
3730
3796
  const camelName = shared.camelize(name);
@@ -3830,7 +3896,7 @@ function buildProps(node, context, props = node.props, ssr = false) {
3830
3896
  }
3831
3897
  }
3832
3898
  // skip :is on <component>
3833
- if (name === 'is' && tag === 'component') {
3899
+ if (name === 'is' && isComponentTag(tag)) {
3834
3900
  continue;
3835
3901
  }
3836
3902
  properties.push(createObjectProperty(createSimpleExpression(name, true, getInnerRange(loc, 0, name.length)), createSimpleExpression(value ? value.content : '', isStatic, value ? value.loc : loc)));
@@ -3853,7 +3919,7 @@ function buildProps(node, context, props = node.props, ssr = false) {
3853
3919
  }
3854
3920
  // skip v-is and :is on <component>
3855
3921
  if (name === 'is' ||
3856
- (isBind && tag === 'component' && isBindKey(arg, 'is'))) {
3922
+ (isBind && isComponentTag(tag) && isBindKey(arg, 'is'))) {
3857
3923
  continue;
3858
3924
  }
3859
3925
  // skip v-on in SSR compilation
@@ -4042,6 +4108,9 @@ function stringifyDynamicPropNames(props) {
4042
4108
  propsNamesString += ', ';
4043
4109
  }
4044
4110
  return propsNamesString + `]`;
4111
+ }
4112
+ function isComponentTag(tag) {
4113
+ return tag[0].toLowerCase() + tag.slice(1) === 'component';
4045
4114
  }
4046
4115
 
4047
4116
  Object.freeze({})
@@ -4079,6 +4148,15 @@ const transformSlotOutlet = (node, context) => {
4079
4148
  }
4080
4149
  slotArgs.push(createFunctionExpression([], children, false, false, loc));
4081
4150
  }
4151
+ if (context.scopeId && !context.slotted) {
4152
+ if (!slotProps) {
4153
+ slotArgs.push(`{}`);
4154
+ }
4155
+ if (!children.length) {
4156
+ slotArgs.push(`undefined`);
4157
+ }
4158
+ slotArgs.push(`true`);
4159
+ }
4082
4160
  node.codegenNode = createCallExpression(context.helper(RENDER_SLOT), slotArgs, loc);
4083
4161
  }
4084
4162
  };
@@ -348,7 +348,7 @@ function isCoreComponent(tag) {
348
348
  }
349
349
  const nonIdentifierRE = /^\d|[^\$\w]/;
350
350
  const isSimpleIdentifier = (name) => !nonIdentifierRE.test(name);
351
- const memberExpRE = /^[A-Za-z_$][\w$]*(?:\s*\.\s*[A-Za-z_$][\w$]*|\[[^\]]+\])*$/;
351
+ const memberExpRE = /^[A-Za-z_$\xA0-\uFFFF][\w$\xA0-\uFFFF]*(?:\s*\.\s*[A-Za-z_$\xA0-\uFFFF][\w$\xA0-\uFFFF]*|\[[^\]]+\])*$/;
352
352
  const isMemberExpression = (path) => {
353
353
  if (!path)
354
354
  return false;
@@ -677,7 +677,7 @@ function parseChildren(context, mode, ancestors) {
677
677
  // Whitespace management for more efficient output
678
678
  // (same as v2 whitespace: 'condense')
679
679
  let removedWhitespace = false;
680
- if (mode !== 2 /* RAWTEXT */) {
680
+ if (mode !== 2 /* RAWTEXT */ && mode !== 1 /* RCDATA */) {
681
681
  for (let i = 0; i < nodes.length; i++) {
682
682
  const node = nodes[i];
683
683
  if (!context.inPre && node.type === 2 /* TEXT */) {
@@ -993,7 +993,7 @@ function parseAttribute(context, nameSet) {
993
993
  let arg;
994
994
  if (match[2]) {
995
995
  const isSlot = dirName === 'slot';
996
- const startOffset = name.indexOf(match[2]);
996
+ const startOffset = name.lastIndexOf(match[2]);
997
997
  const loc = getSelection(context, getNewPosition(context, start, startOffset), getNewPosition(context, start, startOffset + match[2].length + ((isSlot && match[3]) || '').length));
998
998
  let content = match[2];
999
999
  let isStatic = true;
@@ -1314,7 +1314,14 @@ function walk(node, context, doNotHoistNode = false) {
1314
1314
  }
1315
1315
  // walk further
1316
1316
  if (child.type === 1 /* ELEMENT */) {
1317
+ const isComponent = child.tagType === 1 /* COMPONENT */;
1318
+ if (isComponent) {
1319
+ context.scopes.vSlot++;
1320
+ }
1317
1321
  walk(child, context);
1322
+ if (isComponent) {
1323
+ context.scopes.vSlot--;
1324
+ }
1318
1325
  }
1319
1326
  else if (child.type === 11 /* FOR */) {
1320
1327
  // Do not hoist v-for single child because it has to be a block
@@ -1396,6 +1403,8 @@ function getConstantType(node, context) {
1396
1403
  // static then they don't need to be blocks since there will be no
1397
1404
  // nested updates.
1398
1405
  if (codegenNode.isBlock) {
1406
+ context.removeHelper(OPEN_BLOCK);
1407
+ context.removeHelper(CREATE_BLOCK);
1399
1408
  codegenNode.isBlock = false;
1400
1409
  context.helper(CREATE_VNODE);
1401
1410
  }
@@ -1477,7 +1486,7 @@ function getPatchFlag(node) {
1477
1486
  return flag ? parseInt(flag, 10) : undefined;
1478
1487
  }
1479
1488
 
1480
- function createTransformContext(root, { filename = '', prefixIdentifiers = false, hoistStatic = false, cacheHandlers = false, nodeTransforms = [], directiveTransforms = {}, transformHoist = null, isBuiltInComponent = shared.NOOP, isCustomElement = shared.NOOP, expressionPlugins = [], scopeId = null, ssr = false, ssrCssVars = ``, bindingMetadata = shared.EMPTY_OBJ, inline = false, isTS = false, onError = defaultOnError }) {
1489
+ function createTransformContext(root, { filename = '', prefixIdentifiers = false, hoistStatic = false, cacheHandlers = false, nodeTransforms = [], directiveTransforms = {}, transformHoist = null, isBuiltInComponent = shared.NOOP, isCustomElement = shared.NOOP, expressionPlugins = [], scopeId = null, slotted = true, ssr = false, ssrCssVars = ``, bindingMetadata = shared.EMPTY_OBJ, inline = false, isTS = false, onError = defaultOnError }) {
1481
1490
  const nameMatch = filename.replace(/\?.*$/, '').match(/([^/\\]+)\.\w+$/);
1482
1491
  const context = {
1483
1492
  // options
@@ -1492,6 +1501,7 @@ function createTransformContext(root, { filename = '', prefixIdentifiers = false
1492
1501
  isCustomElement,
1493
1502
  expressionPlugins,
1494
1503
  scopeId,
1504
+ slotted,
1495
1505
  ssr,
1496
1506
  ssrCssVars,
1497
1507
  bindingMetadata,
@@ -1500,7 +1510,7 @@ function createTransformContext(root, { filename = '', prefixIdentifiers = false
1500
1510
  onError,
1501
1511
  // state
1502
1512
  root,
1503
- helpers: new Set(),
1513
+ helpers: new Map(),
1504
1514
  components: new Set(),
1505
1515
  directives: new Set(),
1506
1516
  hoists: [],
@@ -1520,9 +1530,22 @@ function createTransformContext(root, { filename = '', prefixIdentifiers = false
1520
1530
  childIndex: 0,
1521
1531
  // methods
1522
1532
  helper(name) {
1523
- context.helpers.add(name);
1533
+ const count = context.helpers.get(name) || 0;
1534
+ context.helpers.set(name, count + 1);
1524
1535
  return name;
1525
1536
  },
1537
+ removeHelper(name) {
1538
+ const count = context.helpers.get(name);
1539
+ if (count) {
1540
+ const currentCount = count - 1;
1541
+ if (!currentCount) {
1542
+ context.helpers.delete(name);
1543
+ }
1544
+ else {
1545
+ context.helpers.set(name, currentCount);
1546
+ }
1547
+ }
1548
+ },
1526
1549
  helperString(name) {
1527
1550
  return `_${helperNameMap[context.helper(name)]}`;
1528
1551
  },
@@ -1610,7 +1633,7 @@ function transform(root, options) {
1610
1633
  createRootCodegen(root, context);
1611
1634
  }
1612
1635
  // finalize meta information
1613
- root.helpers = [...context.helpers];
1636
+ root.helpers = [...context.helpers.keys()];
1614
1637
  root.components = [...context.components];
1615
1638
  root.directives = [...context.directives];
1616
1639
  root.imports = context.imports;
@@ -1619,7 +1642,7 @@ function transform(root, options) {
1619
1642
  root.cached = context.cached;
1620
1643
  }
1621
1644
  function createRootCodegen(root, context) {
1622
- const { helper } = context;
1645
+ const { helper, removeHelper } = context;
1623
1646
  const { children } = root;
1624
1647
  if (children.length === 1) {
1625
1648
  const child = children[0];
@@ -1629,9 +1652,12 @@ function createRootCodegen(root, context) {
1629
1652
  // SimpleExpressionNode
1630
1653
  const codegenNode = child.codegenNode;
1631
1654
  if (codegenNode.type === 13 /* VNODE_CALL */) {
1632
- codegenNode.isBlock = true;
1633
- helper(OPEN_BLOCK);
1634
- helper(CREATE_BLOCK);
1655
+ if (!codegenNode.isBlock) {
1656
+ removeHelper(CREATE_VNODE);
1657
+ codegenNode.isBlock = true;
1658
+ helper(OPEN_BLOCK);
1659
+ helper(CREATE_BLOCK);
1660
+ }
1635
1661
  }
1636
1662
  root.codegenNode = codegenNode;
1637
1663
  }
@@ -1755,6 +1781,7 @@ function createStructuralDirectiveTransform(name, fn) {
1755
1781
  }
1756
1782
 
1757
1783
  const PURE_ANNOTATION = `/*#__PURE__*/`;
1784
+ const WITH_ID = `_withId`;
1758
1785
  function createCodegenContext(ast, { mode = 'function', prefixIdentifiers = mode === 'module', sourceMap: sourceMap$1 = false, filename = `template.vue.html`, scopeId = null, optimizeImports = false, runtimeGlobalName = `Vue`, runtimeModuleName = `vue`, ssr = false }) {
1759
1786
  const context = {
1760
1787
  mode,
@@ -1866,13 +1893,12 @@ function generate(ast, options = {}) {
1866
1893
  const signature = options.isTS
1867
1894
  ? args.map(arg => `${arg}: any`).join(',')
1868
1895
  : args.join(', ');
1869
- if (genScopeId) {
1870
- if (isSetupInlined) {
1871
- push(`${PURE_ANNOTATION}_withId(`);
1872
- }
1873
- else {
1874
- push(`const ${functionName} = ${PURE_ANNOTATION}_withId(`);
1875
- }
1896
+ if (genScopeId && !isSetupInlined) {
1897
+ // root-level _withId wrapping is no longer necessary after 3.0.8 and is
1898
+ // a noop, it's only kept so that code compiled with 3.0.8+ can run with
1899
+ // runtime < 3.0.8.
1900
+ // TODO: consider removing in 3.1
1901
+ push(`const ${functionName} = ${PURE_ANNOTATION}${WITH_ID}(`);
1876
1902
  }
1877
1903
  if (isSetupInlined || genScopeId) {
1878
1904
  push(`(${signature}) => {`);
@@ -1933,7 +1959,7 @@ function generate(ast, options = {}) {
1933
1959
  }
1934
1960
  deindent();
1935
1961
  push(`}`);
1936
- if (genScopeId) {
1962
+ if (genScopeId && !isSetupInlined) {
1937
1963
  push(`)`);
1938
1964
  }
1939
1965
  return {
@@ -1991,7 +2017,7 @@ function genFunctionPreamble(ast, context) {
1991
2017
  push(`return `);
1992
2018
  }
1993
2019
  function genModulePreamble(ast, context, genScopeId, inline) {
1994
- const { push, helper, newline, scopeId, optimizeImports, runtimeModuleName } = context;
2020
+ const { push, newline, optimizeImports, runtimeModuleName, scopeId, helper } = context;
1995
2021
  if (genScopeId) {
1996
2022
  ast.helpers.push(WITH_SCOPE_ID);
1997
2023
  if (ast.hoists.length) {
@@ -2028,8 +2054,11 @@ function genModulePreamble(ast, context, genScopeId, inline) {
2028
2054
  genImports(ast.imports, context);
2029
2055
  newline();
2030
2056
  }
2057
+ // we technically don't need this anymore since `withCtx` already sets the
2058
+ // correct scopeId, but this is necessary for backwards compat
2059
+ // TODO: consider removing in 3.1
2031
2060
  if (genScopeId) {
2032
- push(`const _withId = ${PURE_ANNOTATION}${helper(WITH_SCOPE_ID)}("${scopeId}")`);
2061
+ push(`const ${WITH_ID} = ${PURE_ANNOTATION}${helper(WITH_SCOPE_ID)}("${scopeId}")`);
2033
2062
  newline();
2034
2063
  }
2035
2064
  genHoists(ast.hoists, context);
@@ -2041,8 +2070,13 @@ function genModulePreamble(ast, context, genScopeId, inline) {
2041
2070
  function genAssets(assets, type, { helper, push, newline }) {
2042
2071
  const resolver = helper(type === 'component' ? RESOLVE_COMPONENT : RESOLVE_DIRECTIVE);
2043
2072
  for (let i = 0; i < assets.length; i++) {
2044
- const id = assets[i];
2045
- push(`const ${toValidAssetId(id, type)} = ${resolver}(${JSON.stringify(id)})`);
2073
+ let id = assets[i];
2074
+ // potential component implicit self-reference inferred from SFC filename
2075
+ const maybeSelfReference = id.endsWith('__self');
2076
+ if (maybeSelfReference) {
2077
+ id = id.slice(0, -6);
2078
+ }
2079
+ push(`const ${toValidAssetId(id, type)} = ${resolver}(${JSON.stringify(id)}${maybeSelfReference ? `, true` : ``})`);
2046
2080
  if (i < assets.length - 1) {
2047
2081
  newline();
2048
2082
  }
@@ -2322,11 +2356,9 @@ function genFunctionExpression(node, context) {
2322
2356
  const { params, returns, body, newline, isSlot } = node;
2323
2357
  // slot functions also need to push scopeId before rendering its content
2324
2358
  const genScopeId = isSlot && scopeId != null && mode !== 'function';
2325
- if (genScopeId) {
2326
- push(`_withId(`);
2327
- }
2328
- else if (isSlot) {
2329
- push(`_${helperNameMap[WITH_CTX]}(`);
2359
+ if (isSlot) {
2360
+ // wrap slot functions with owner context
2361
+ push(genScopeId ? `${WITH_ID}(` : `_${helperNameMap[WITH_CTX]}(`);
2330
2362
  }
2331
2363
  push(`(`, node);
2332
2364
  if (shared.isArray(params)) {
@@ -2358,7 +2390,7 @@ function genFunctionExpression(node, context) {
2358
2390
  deindent();
2359
2391
  push(`}`);
2360
2392
  }
2361
- if (genScopeId || isSlot) {
2393
+ if (isSlot) {
2362
2394
  push(`)`);
2363
2395
  }
2364
2396
  }
@@ -2965,7 +2997,7 @@ function createCodegenNodeForBranch(branch, keyIndex, context) {
2965
2997
  }
2966
2998
  }
2967
2999
  function createChildrenCodegenNode(branch, keyIndex, context) {
2968
- const { helper } = context;
3000
+ const { helper, removeHelper } = context;
2969
3001
  const keyProperty = createObjectProperty(`key`, createSimpleExpression(`${keyIndex}`, false, locStub, 2 /* CAN_HOIST */));
2970
3002
  const { children } = branch;
2971
3003
  const firstChild = children[0];
@@ -2978,15 +3010,17 @@ function createChildrenCodegenNode(branch, keyIndex, context) {
2978
3010
  return vnodeCall;
2979
3011
  }
2980
3012
  else {
2981
- return createVNodeCall(context, helper(FRAGMENT), createObjectExpression([keyProperty]), children, 64 /* STABLE_FRAGMENT */ +
2982
- (``), undefined, undefined, true, false, branch.loc);
3013
+ let patchFlag = 64 /* STABLE_FRAGMENT */;
3014
+ shared.PatchFlagNames[64 /* STABLE_FRAGMENT */];
3015
+ return createVNodeCall(context, helper(FRAGMENT), createObjectExpression([keyProperty]), children, patchFlag + (``), undefined, undefined, true, false, branch.loc);
2983
3016
  }
2984
3017
  }
2985
3018
  else {
2986
3019
  const vnodeCall = firstChild
2987
3020
  .codegenNode;
2988
3021
  // Change createVNode to createBlock.
2989
- if (vnodeCall.type === 13 /* VNODE_CALL */) {
3022
+ if (vnodeCall.type === 13 /* VNODE_CALL */ && !vnodeCall.isBlock) {
3023
+ removeHelper(CREATE_VNODE);
2990
3024
  vnodeCall.isBlock = true;
2991
3025
  helper(OPEN_BLOCK);
2992
3026
  helper(CREATE_BLOCK);
@@ -3037,7 +3071,7 @@ function getParentCondition(node) {
3037
3071
  }
3038
3072
 
3039
3073
  const transformFor = createStructuralDirectiveTransform('for', (node, dir, context) => {
3040
- const { helper } = context;
3074
+ const { helper, removeHelper } = context;
3041
3075
  return processFor(node, dir, context, forNode => {
3042
3076
  // create the loop render function expression now, and add the
3043
3077
  // iterator on exit after all children have been traversed
@@ -3116,6 +3150,17 @@ const transformFor = createStructuralDirectiveTransform('for', (node, dir, conte
3116
3150
  if (isTemplate && keyProperty) {
3117
3151
  injectProp(childBlock, keyProperty, context);
3118
3152
  }
3153
+ if (childBlock.isBlock !== !isStableFragment) {
3154
+ if (childBlock.isBlock) {
3155
+ // switch from block to vnode
3156
+ removeHelper(OPEN_BLOCK);
3157
+ removeHelper(CREATE_BLOCK);
3158
+ }
3159
+ else {
3160
+ // switch from vnode to block
3161
+ removeHelper(CREATE_VNODE);
3162
+ }
3163
+ }
3119
3164
  childBlock.isBlock = !isStableFragment;
3120
3165
  if (childBlock.isBlock) {
3121
3166
  helper(OPEN_BLOCK);
@@ -3483,12 +3528,23 @@ function buildDynamicSlot(name, fn) {
3483
3528
  function hasForwardedSlots(children) {
3484
3529
  for (let i = 0; i < children.length; i++) {
3485
3530
  const child = children[i];
3486
- if (child.type === 1 /* ELEMENT */) {
3487
- if (child.tagType === 2 /* SLOT */ ||
3488
- (child.tagType === 0 /* ELEMENT */ &&
3489
- hasForwardedSlots(child.children))) {
3490
- return true;
3491
- }
3531
+ switch (child.type) {
3532
+ case 1 /* ELEMENT */:
3533
+ if (child.tagType === 2 /* SLOT */ ||
3534
+ (child.tagType === 0 /* ELEMENT */ &&
3535
+ hasForwardedSlots(child.children))) {
3536
+ return true;
3537
+ }
3538
+ break;
3539
+ case 9 /* IF */:
3540
+ if (hasForwardedSlots(child.branches))
3541
+ return true;
3542
+ break;
3543
+ case 10 /* IF_BRANCH */:
3544
+ case 11 /* FOR */:
3545
+ if (hasForwardedSlots(child.children))
3546
+ return true;
3547
+ break;
3492
3548
  }
3493
3549
  }
3494
3550
  return false;
@@ -3499,14 +3555,15 @@ function hasForwardedSlots(children) {
3499
3555
  const directiveImportMap = new WeakMap();
3500
3556
  // generate a JavaScript AST for this element's codegen
3501
3557
  const transformElement = (node, context) => {
3502
- if (!(node.type === 1 /* ELEMENT */ &&
3503
- (node.tagType === 0 /* ELEMENT */ ||
3504
- node.tagType === 1 /* COMPONENT */))) {
3505
- return;
3506
- }
3507
3558
  // perform the work on exit, after all child expressions have been
3508
3559
  // processed and merged.
3509
3560
  return function postTransformElement() {
3561
+ node = context.currentNode;
3562
+ if (!(node.type === 1 /* ELEMENT */ &&
3563
+ (node.tagType === 0 /* ELEMENT */ ||
3564
+ node.tagType === 1 /* COMPONENT */))) {
3565
+ return;
3566
+ }
3510
3567
  const { tag, props } = node;
3511
3568
  const isComponent = node.tagType === 1 /* COMPONENT */;
3512
3569
  // The goal of the transform is to create a codegenNode implementing the
@@ -3611,7 +3668,9 @@ const transformElement = (node, context) => {
3611
3668
  function resolveComponentType(node, context, ssr = false) {
3612
3669
  const { tag } = node;
3613
3670
  // 1. dynamic component
3614
- const isProp = node.tag === 'component' ? findProp(node, 'is') : findDir(node, 'is');
3671
+ const isProp = isComponentTag(tag)
3672
+ ? findProp(node, 'is')
3673
+ : findDir(node, 'is');
3615
3674
  if (isProp) {
3616
3675
  const exp = isProp.type === 6 /* ATTRIBUTE */
3617
3676
  ? isProp.value && createSimpleExpression(isProp.value.content, true)
@@ -3641,12 +3700,14 @@ function resolveComponentType(node, context, ssr = false) {
3641
3700
  }
3642
3701
  }
3643
3702
  // 4. Self referencing component (inferred from filename)
3644
- if (context.selfName) {
3645
- if (shared.capitalize(shared.camelize(tag)) === context.selfName) {
3646
- context.helper(RESOLVE_COMPONENT);
3647
- context.components.add(`_self`);
3648
- return toValidAssetId(`_self`, `component`);
3649
- }
3703
+ if (context.selfName &&
3704
+ shared.capitalize(shared.camelize(tag)) === context.selfName) {
3705
+ context.helper(RESOLVE_COMPONENT);
3706
+ // codegen.ts has special check for __self postfix when generating
3707
+ // component imports, which will pass additional `maybeSelfReference` flag
3708
+ // to `resolveComponent`.
3709
+ context.components.add(tag + `__self`);
3710
+ return toValidAssetId(tag, `component`);
3650
3711
  }
3651
3712
  // 5. user component (resolve)
3652
3713
  context.helper(RESOLVE_COMPONENT);
@@ -3655,7 +3716,7 @@ function resolveComponentType(node, context, ssr = false) {
3655
3716
  }
3656
3717
  function resolveSetupReference(name, context) {
3657
3718
  const bindings = context.bindingMetadata;
3658
- if (!bindings) {
3719
+ if (!bindings || bindings.__isScriptSetup === false) {
3659
3720
  return;
3660
3721
  }
3661
3722
  const camelName = shared.camelize(name);
@@ -3761,7 +3822,7 @@ function buildProps(node, context, props = node.props, ssr = false) {
3761
3822
  }
3762
3823
  }
3763
3824
  // skip :is on <component>
3764
- if (name === 'is' && tag === 'component') {
3825
+ if (name === 'is' && isComponentTag(tag)) {
3765
3826
  continue;
3766
3827
  }
3767
3828
  properties.push(createObjectProperty(createSimpleExpression(name, true, getInnerRange(loc, 0, name.length)), createSimpleExpression(value ? value.content : '', isStatic, value ? value.loc : loc)));
@@ -3784,7 +3845,7 @@ function buildProps(node, context, props = node.props, ssr = false) {
3784
3845
  }
3785
3846
  // skip v-is and :is on <component>
3786
3847
  if (name === 'is' ||
3787
- (isBind && tag === 'component' && isBindKey(arg, 'is'))) {
3848
+ (isBind && isComponentTag(tag) && isBindKey(arg, 'is'))) {
3788
3849
  continue;
3789
3850
  }
3790
3851
  // skip v-on in SSR compilation
@@ -3973,6 +4034,9 @@ function stringifyDynamicPropNames(props) {
3973
4034
  propsNamesString += ', ';
3974
4035
  }
3975
4036
  return propsNamesString + `]`;
4037
+ }
4038
+ function isComponentTag(tag) {
4039
+ return tag[0].toLowerCase() + tag.slice(1) === 'component';
3976
4040
  }
3977
4041
 
3978
4042
  const cacheStringFunction = (fn) => {
@@ -4007,6 +4071,15 @@ const transformSlotOutlet = (node, context) => {
4007
4071
  }
4008
4072
  slotArgs.push(createFunctionExpression([], children, false, false, loc));
4009
4073
  }
4074
+ if (context.scopeId && !context.slotted) {
4075
+ if (!slotProps) {
4076
+ slotArgs.push(`{}`);
4077
+ }
4078
+ if (!children.length) {
4079
+ slotArgs.push(`undefined`);
4080
+ }
4081
+ slotArgs.push(`true`);
4082
+ }
4010
4083
  node.codegenNode = createCallExpression(context.helper(RENDER_SLOT), slotArgs, loc);
4011
4084
  }
4012
4085
  };
@@ -42,9 +42,11 @@ export declare interface BaseElementNode extends Node_2 {
42
42
 
43
43
  export declare function baseParse(content: string, options?: ParserOptions): RootNode;
44
44
 
45
- export declare interface BindingMetadata {
45
+ export declare type BindingMetadata = {
46
46
  [key: string]: BindingTypes | undefined;
47
- }
47
+ } & {
48
+ __isScriptSetup?: boolean;
49
+ };
48
50
 
49
51
  export declare const enum BindingTypes {
50
52
  /**
@@ -290,7 +292,7 @@ export declare function createStructuralDirectiveTransform(name: string | RegExp
290
292
 
291
293
  export declare function createTemplateLiteral(elements: TemplateLiteral['elements']): TemplateLiteral;
292
294
 
293
- export declare function createTransformContext(root: RootNode, { filename, prefixIdentifiers, hoistStatic, cacheHandlers, nodeTransforms, directiveTransforms, transformHoist, isBuiltInComponent, isCustomElement, expressionPlugins, scopeId, ssr, ssrCssVars, bindingMetadata, inline, isTS, onError }: TransformOptions): TransformContext;
295
+ export declare function createTransformContext(root: RootNode, { filename, prefixIdentifiers, hoistStatic, cacheHandlers, nodeTransforms, directiveTransforms, transformHoist, isBuiltInComponent, isCustomElement, expressionPlugins, scopeId, slotted, ssr, ssrCssVars, bindingMetadata, inline, isTS, onError }: TransformOptions): TransformContext;
294
296
 
295
297
  export declare function createVNodeCall(context: TransformContext | null, tag: VNodeCall['tag'], props?: VNodeCall['props'], children?: VNodeCall['children'], patchFlag?: VNodeCall['patchFlag'], dynamicProps?: VNodeCall['dynamicProps'], directives?: VNodeCall['directives'], isBlock?: VNodeCall['isBlock'], disableTracking?: VNodeCall['disableTracking'], loc?: SourceLocation): VNodeCall;
296
298
 
@@ -725,7 +727,7 @@ export declare interface RootNode extends Node_2 {
725
727
  cached: number;
726
728
  temps: number;
727
729
  ssrHelpers?: symbol[];
728
- codegenNode?: TemplateChildNode | JSChildNode | BlockStatement | undefined;
730
+ codegenNode?: TemplateChildNode | JSChildNode | BlockStatement;
729
731
  }
730
732
 
731
733
  export declare interface SequenceExpression extends Node_2 {
@@ -883,7 +885,7 @@ export declare const transformBind: DirectiveTransform;
883
885
  export declare interface TransformContext extends Required<Omit<TransformOptions, 'filename'>> {
884
886
  selfName: string | null;
885
887
  root: RootNode;
886
- helpers: Set<symbol>;
888
+ helpers: Map<symbol, number>;
887
889
  components: Set<string>;
888
890
  directives: Set<string>;
889
891
  hoists: (JSChildNode | null)[];
@@ -903,6 +905,7 @@ export declare interface TransformContext extends Required<Omit<TransformOptions
903
905
  childIndex: number;
904
906
  currentNode: RootNode | TemplateChildNode | null;
905
907
  helper<T extends symbol>(name: T): T;
908
+ removeHelper<T extends symbol>(name: T): void;
906
909
  helperString(name: symbol): string;
907
910
  replaceNode(node: TemplateChildNode): void;
908
911
  removeNode(node?: TemplateChildNode): void;
@@ -985,6 +988,12 @@ export declare interface TransformOptions extends SharedTransformCodegenOptions
985
988
  * SFC scoped styles ID
986
989
  */
987
990
  scopeId?: string | null;
991
+ /**
992
+ * Indicates this SFC template has used :slotted in its styles
993
+ * Defaults to `true` for backwards compatibility - SFC tooling should set it
994
+ * to `false` if no `:slotted` usage is detected in `<style>`
995
+ */
996
+ slotted?: boolean;
988
997
  /**
989
998
  * SFC `<style vars>` injection string
990
999
  * Should already be an object expression, e.g. `{ 'xxxx-color': color }`
@@ -343,7 +343,7 @@ function isCoreComponent(tag) {
343
343
  }
344
344
  const nonIdentifierRE = /^\d|[^\$\w]/;
345
345
  const isSimpleIdentifier = (name) => !nonIdentifierRE.test(name);
346
- const memberExpRE = /^[A-Za-z_$][\w$]*(?:\s*\.\s*[A-Za-z_$][\w$]*|\[[^\]]+\])*$/;
346
+ const memberExpRE = /^[A-Za-z_$\xA0-\uFFFF][\w$\xA0-\uFFFF]*(?:\s*\.\s*[A-Za-z_$\xA0-\uFFFF][\w$\xA0-\uFFFF]*|\[[^\]]+\])*$/;
347
347
  const isMemberExpression = (path) => {
348
348
  if (!path)
349
349
  return false;
@@ -673,7 +673,7 @@ function parseChildren(context, mode, ancestors) {
673
673
  // Whitespace management for more efficient output
674
674
  // (same as v2 whitespace: 'condense')
675
675
  let removedWhitespace = false;
676
- if (mode !== 2 /* RAWTEXT */) {
676
+ if (mode !== 2 /* RAWTEXT */ && mode !== 1 /* RCDATA */) {
677
677
  for (let i = 0; i < nodes.length; i++) {
678
678
  const node = nodes[i];
679
679
  if (!context.inPre && node.type === 2 /* TEXT */) {
@@ -990,7 +990,7 @@ function parseAttribute(context, nameSet) {
990
990
  let arg;
991
991
  if (match[2]) {
992
992
  const isSlot = dirName === 'slot';
993
- const startOffset = name.indexOf(match[2]);
993
+ const startOffset = name.lastIndexOf(match[2]);
994
994
  const loc = getSelection(context, getNewPosition(context, start, startOffset), getNewPosition(context, start, startOffset + match[2].length + ((isSlot && match[3]) || '').length));
995
995
  let content = match[2];
996
996
  let isStatic = true;
@@ -1311,7 +1311,14 @@ function walk(node, context, doNotHoistNode = false) {
1311
1311
  }
1312
1312
  // walk further
1313
1313
  if (child.type === 1 /* ELEMENT */) {
1314
+ const isComponent = child.tagType === 1 /* COMPONENT */;
1315
+ if (isComponent) {
1316
+ context.scopes.vSlot++;
1317
+ }
1314
1318
  walk(child, context);
1319
+ if (isComponent) {
1320
+ context.scopes.vSlot--;
1321
+ }
1315
1322
  }
1316
1323
  else if (child.type === 11 /* FOR */) {
1317
1324
  // Do not hoist v-for single child because it has to be a block
@@ -1393,6 +1400,8 @@ function getConstantType(node, context) {
1393
1400
  // static then they don't need to be blocks since there will be no
1394
1401
  // nested updates.
1395
1402
  if (codegenNode.isBlock) {
1403
+ context.removeHelper(OPEN_BLOCK);
1404
+ context.removeHelper(CREATE_BLOCK);
1396
1405
  codegenNode.isBlock = false;
1397
1406
  context.helper(CREATE_VNODE);
1398
1407
  }
@@ -1475,7 +1484,7 @@ function getPatchFlag(node) {
1475
1484
  return flag ? parseInt(flag, 10) : undefined;
1476
1485
  }
1477
1486
 
1478
- function createTransformContext(root, { filename = '', prefixIdentifiers = false, hoistStatic = false, cacheHandlers = false, nodeTransforms = [], directiveTransforms = {}, transformHoist = null, isBuiltInComponent = NOOP, isCustomElement = NOOP, expressionPlugins = [], scopeId = null, ssr = false, ssrCssVars = ``, bindingMetadata = EMPTY_OBJ, inline = false, isTS = false, onError = defaultOnError }) {
1487
+ function createTransformContext(root, { filename = '', prefixIdentifiers = false, hoistStatic = false, cacheHandlers = false, nodeTransforms = [], directiveTransforms = {}, transformHoist = null, isBuiltInComponent = NOOP, isCustomElement = NOOP, expressionPlugins = [], scopeId = null, slotted = true, ssr = false, ssrCssVars = ``, bindingMetadata = EMPTY_OBJ, inline = false, isTS = false, onError = defaultOnError }) {
1479
1488
  const nameMatch = filename.replace(/\?.*$/, '').match(/([^/\\]+)\.\w+$/);
1480
1489
  const context = {
1481
1490
  // options
@@ -1490,6 +1499,7 @@ function createTransformContext(root, { filename = '', prefixIdentifiers = false
1490
1499
  isCustomElement,
1491
1500
  expressionPlugins,
1492
1501
  scopeId,
1502
+ slotted,
1493
1503
  ssr,
1494
1504
  ssrCssVars,
1495
1505
  bindingMetadata,
@@ -1498,7 +1508,7 @@ function createTransformContext(root, { filename = '', prefixIdentifiers = false
1498
1508
  onError,
1499
1509
  // state
1500
1510
  root,
1501
- helpers: new Set(),
1511
+ helpers: new Map(),
1502
1512
  components: new Set(),
1503
1513
  directives: new Set(),
1504
1514
  hoists: [],
@@ -1518,9 +1528,22 @@ function createTransformContext(root, { filename = '', prefixIdentifiers = false
1518
1528
  childIndex: 0,
1519
1529
  // methods
1520
1530
  helper(name) {
1521
- context.helpers.add(name);
1531
+ const count = context.helpers.get(name) || 0;
1532
+ context.helpers.set(name, count + 1);
1522
1533
  return name;
1523
1534
  },
1535
+ removeHelper(name) {
1536
+ const count = context.helpers.get(name);
1537
+ if (count) {
1538
+ const currentCount = count - 1;
1539
+ if (!currentCount) {
1540
+ context.helpers.delete(name);
1541
+ }
1542
+ else {
1543
+ context.helpers.set(name, currentCount);
1544
+ }
1545
+ }
1546
+ },
1524
1547
  helperString(name) {
1525
1548
  return `_${helperNameMap[context.helper(name)]}`;
1526
1549
  },
@@ -1591,7 +1614,7 @@ function transform(root, options) {
1591
1614
  createRootCodegen(root, context);
1592
1615
  }
1593
1616
  // finalize meta information
1594
- root.helpers = [...context.helpers];
1617
+ root.helpers = [...context.helpers.keys()];
1595
1618
  root.components = [...context.components];
1596
1619
  root.directives = [...context.directives];
1597
1620
  root.imports = context.imports;
@@ -1600,7 +1623,7 @@ function transform(root, options) {
1600
1623
  root.cached = context.cached;
1601
1624
  }
1602
1625
  function createRootCodegen(root, context) {
1603
- const { helper } = context;
1626
+ const { helper, removeHelper } = context;
1604
1627
  const { children } = root;
1605
1628
  if (children.length === 1) {
1606
1629
  const child = children[0];
@@ -1610,9 +1633,12 @@ function createRootCodegen(root, context) {
1610
1633
  // SimpleExpressionNode
1611
1634
  const codegenNode = child.codegenNode;
1612
1635
  if (codegenNode.type === 13 /* VNODE_CALL */) {
1613
- codegenNode.isBlock = true;
1614
- helper(OPEN_BLOCK);
1615
- helper(CREATE_BLOCK);
1636
+ if (!codegenNode.isBlock) {
1637
+ removeHelper(CREATE_VNODE);
1638
+ codegenNode.isBlock = true;
1639
+ helper(OPEN_BLOCK);
1640
+ helper(CREATE_BLOCK);
1641
+ }
1616
1642
  }
1617
1643
  root.codegenNode = codegenNode;
1618
1644
  }
@@ -1907,8 +1933,13 @@ function genFunctionPreamble(ast, context) {
1907
1933
  function genAssets(assets, type, { helper, push, newline }) {
1908
1934
  const resolver = helper(type === 'component' ? RESOLVE_COMPONENT : RESOLVE_DIRECTIVE);
1909
1935
  for (let i = 0; i < assets.length; i++) {
1910
- const id = assets[i];
1911
- push(`const ${toValidAssetId(id, type)} = ${resolver}(${JSON.stringify(id)})`);
1936
+ let id = assets[i];
1937
+ // potential component implicit self-reference inferred from SFC filename
1938
+ const maybeSelfReference = id.endsWith('__self');
1939
+ if (maybeSelfReference) {
1940
+ id = id.slice(0, -6);
1941
+ }
1942
+ push(`const ${toValidAssetId(id, type)} = ${resolver}(${JSON.stringify(id)}${maybeSelfReference ? `, true` : ``})`);
1912
1943
  if (i < assets.length - 1) {
1913
1944
  newline();
1914
1945
  }
@@ -2184,6 +2215,7 @@ function genFunctionExpression(node, context) {
2184
2215
  const { push, indent, deindent, scopeId, mode } = context;
2185
2216
  const { params, returns, body, newline, isSlot } = node;
2186
2217
  if (isSlot) {
2218
+ // wrap slot functions with owner context
2187
2219
  push(`_${helperNameMap[WITH_CTX]}(`);
2188
2220
  }
2189
2221
  push(`(`, node);
@@ -2492,7 +2524,7 @@ function createCodegenNodeForBranch(branch, keyIndex, context) {
2492
2524
  }
2493
2525
  }
2494
2526
  function createChildrenCodegenNode(branch, keyIndex, context) {
2495
- const { helper } = context;
2527
+ const { helper, removeHelper } = context;
2496
2528
  const keyProperty = createObjectProperty(`key`, createSimpleExpression(`${keyIndex}`, false, locStub, 2 /* CAN_HOIST */));
2497
2529
  const { children } = branch;
2498
2530
  const firstChild = children[0];
@@ -2505,17 +2537,24 @@ function createChildrenCodegenNode(branch, keyIndex, context) {
2505
2537
  return vnodeCall;
2506
2538
  }
2507
2539
  else {
2508
- return createVNodeCall(context, helper(FRAGMENT), createObjectExpression([keyProperty]), children, 64 /* STABLE_FRAGMENT */ +
2509
- ((process.env.NODE_ENV !== 'production')
2510
- ? ` /* ${PatchFlagNames[64 /* STABLE_FRAGMENT */]} */`
2511
- : ``), undefined, undefined, true, false, branch.loc);
2540
+ let patchFlag = 64 /* STABLE_FRAGMENT */;
2541
+ let patchFlagText = PatchFlagNames[64 /* STABLE_FRAGMENT */];
2542
+ // check if the fragment actually contains a single valid child with
2543
+ // the rest being comments
2544
+ if ((process.env.NODE_ENV !== 'production') &&
2545
+ children.filter(c => c.type !== 3 /* COMMENT */).length === 1) {
2546
+ patchFlag |= 2048 /* DEV_ROOT_FRAGMENT */;
2547
+ patchFlagText += `, ${PatchFlagNames[2048 /* DEV_ROOT_FRAGMENT */]}`;
2548
+ }
2549
+ return createVNodeCall(context, helper(FRAGMENT), createObjectExpression([keyProperty]), children, patchFlag + ((process.env.NODE_ENV !== 'production') ? ` /* ${patchFlagText} */` : ``), undefined, undefined, true, false, branch.loc);
2512
2550
  }
2513
2551
  }
2514
2552
  else {
2515
2553
  const vnodeCall = firstChild
2516
2554
  .codegenNode;
2517
2555
  // Change createVNode to createBlock.
2518
- if (vnodeCall.type === 13 /* VNODE_CALL */) {
2556
+ if (vnodeCall.type === 13 /* VNODE_CALL */ && !vnodeCall.isBlock) {
2557
+ removeHelper(CREATE_VNODE);
2519
2558
  vnodeCall.isBlock = true;
2520
2559
  helper(OPEN_BLOCK);
2521
2560
  helper(CREATE_BLOCK);
@@ -2566,7 +2605,7 @@ function getParentCondition(node) {
2566
2605
  }
2567
2606
 
2568
2607
  const transformFor = createStructuralDirectiveTransform('for', (node, dir, context) => {
2569
- const { helper } = context;
2608
+ const { helper, removeHelper } = context;
2570
2609
  return processFor(node, dir, context, forNode => {
2571
2610
  // create the loop render function expression now, and add the
2572
2611
  // iterator on exit after all children have been traversed
@@ -2639,6 +2678,17 @@ const transformFor = createStructuralDirectiveTransform('for', (node, dir, conte
2639
2678
  if (isTemplate && keyProperty) {
2640
2679
  injectProp(childBlock, keyProperty, context);
2641
2680
  }
2681
+ if (childBlock.isBlock !== !isStableFragment) {
2682
+ if (childBlock.isBlock) {
2683
+ // switch from block to vnode
2684
+ removeHelper(OPEN_BLOCK);
2685
+ removeHelper(CREATE_BLOCK);
2686
+ }
2687
+ else {
2688
+ // switch from vnode to block
2689
+ removeHelper(CREATE_VNODE);
2690
+ }
2691
+ }
2642
2692
  childBlock.isBlock = !isStableFragment;
2643
2693
  if (childBlock.isBlock) {
2644
2694
  helper(OPEN_BLOCK);
@@ -2983,12 +3033,23 @@ function buildDynamicSlot(name, fn) {
2983
3033
  function hasForwardedSlots(children) {
2984
3034
  for (let i = 0; i < children.length; i++) {
2985
3035
  const child = children[i];
2986
- if (child.type === 1 /* ELEMENT */) {
2987
- if (child.tagType === 2 /* SLOT */ ||
2988
- (child.tagType === 0 /* ELEMENT */ &&
2989
- hasForwardedSlots(child.children))) {
2990
- return true;
2991
- }
3036
+ switch (child.type) {
3037
+ case 1 /* ELEMENT */:
3038
+ if (child.tagType === 2 /* SLOT */ ||
3039
+ (child.tagType === 0 /* ELEMENT */ &&
3040
+ hasForwardedSlots(child.children))) {
3041
+ return true;
3042
+ }
3043
+ break;
3044
+ case 9 /* IF */:
3045
+ if (hasForwardedSlots(child.branches))
3046
+ return true;
3047
+ break;
3048
+ case 10 /* IF_BRANCH */:
3049
+ case 11 /* FOR */:
3050
+ if (hasForwardedSlots(child.children))
3051
+ return true;
3052
+ break;
2992
3053
  }
2993
3054
  }
2994
3055
  return false;
@@ -2999,14 +3060,15 @@ function hasForwardedSlots(children) {
2999
3060
  const directiveImportMap = new WeakMap();
3000
3061
  // generate a JavaScript AST for this element's codegen
3001
3062
  const transformElement = (node, context) => {
3002
- if (!(node.type === 1 /* ELEMENT */ &&
3003
- (node.tagType === 0 /* ELEMENT */ ||
3004
- node.tagType === 1 /* COMPONENT */))) {
3005
- return;
3006
- }
3007
3063
  // perform the work on exit, after all child expressions have been
3008
3064
  // processed and merged.
3009
3065
  return function postTransformElement() {
3066
+ node = context.currentNode;
3067
+ if (!(node.type === 1 /* ELEMENT */ &&
3068
+ (node.tagType === 0 /* ELEMENT */ ||
3069
+ node.tagType === 1 /* COMPONENT */))) {
3070
+ return;
3071
+ }
3010
3072
  const { tag, props } = node;
3011
3073
  const isComponent = node.tagType === 1 /* COMPONENT */;
3012
3074
  // The goal of the transform is to create a codegenNode implementing the
@@ -3133,7 +3195,9 @@ const transformElement = (node, context) => {
3133
3195
  function resolveComponentType(node, context, ssr = false) {
3134
3196
  const { tag } = node;
3135
3197
  // 1. dynamic component
3136
- const isProp = node.tag === 'component' ? findProp(node, 'is') : findDir(node, 'is');
3198
+ const isProp = isComponentTag(tag)
3199
+ ? findProp(node, 'is')
3200
+ : findDir(node, 'is');
3137
3201
  if (isProp) {
3138
3202
  const exp = isProp.type === 6 /* ATTRIBUTE */
3139
3203
  ? isProp.value && createSimpleExpression(isProp.value.content, true)
@@ -3225,7 +3289,7 @@ function buildProps(node, context, props = node.props, ssr = false) {
3225
3289
  hasRef = true;
3226
3290
  }
3227
3291
  // skip :is on <component>
3228
- if (name === 'is' && tag === 'component') {
3292
+ if (name === 'is' && isComponentTag(tag)) {
3229
3293
  continue;
3230
3294
  }
3231
3295
  properties.push(createObjectProperty(createSimpleExpression(name, true, getInnerRange(loc, 0, name.length)), createSimpleExpression(value ? value.content : '', isStatic, value ? value.loc : loc)));
@@ -3248,7 +3312,7 @@ function buildProps(node, context, props = node.props, ssr = false) {
3248
3312
  }
3249
3313
  // skip v-is and :is on <component>
3250
3314
  if (name === 'is' ||
3251
- (isBind && tag === 'component' && isBindKey(arg, 'is'))) {
3315
+ (isBind && isComponentTag(tag) && isBindKey(arg, 'is'))) {
3252
3316
  continue;
3253
3317
  }
3254
3318
  // skip v-on in SSR compilation
@@ -3431,6 +3495,9 @@ function stringifyDynamicPropNames(props) {
3431
3495
  propsNamesString += ', ';
3432
3496
  }
3433
3497
  return propsNamesString + `]`;
3498
+ }
3499
+ function isComponentTag(tag) {
3500
+ return tag[0].toLowerCase() + tag.slice(1) === 'component';
3434
3501
  }
3435
3502
 
3436
3503
  (process.env.NODE_ENV !== 'production')
@@ -3469,6 +3536,15 @@ const transformSlotOutlet = (node, context) => {
3469
3536
  }
3470
3537
  slotArgs.push(createFunctionExpression([], children, false, false, loc));
3471
3538
  }
3539
+ if (context.scopeId && !context.slotted) {
3540
+ if (!slotProps) {
3541
+ slotArgs.push(`{}`);
3542
+ }
3543
+ if (!children.length) {
3544
+ slotArgs.push(`undefined`);
3545
+ }
3546
+ slotArgs.push(`true`);
3547
+ }
3472
3548
  node.codegenNode = createCallExpression(context.helper(RENDER_SLOT), slotArgs, loc);
3473
3549
  }
3474
3550
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vue/compiler-core",
3
- "version": "3.0.7",
3
+ "version": "3.0.11",
4
4
  "description": "@vue/compiler-core",
5
5
  "main": "index.js",
6
6
  "module": "dist/compiler-core.esm-bundler.js",
@@ -31,7 +31,7 @@
31
31
  },
32
32
  "homepage": "https://github.com/vuejs/vue-next/tree/master/packages/compiler-core#readme",
33
33
  "dependencies": {
34
- "@vue/shared": "3.0.7",
34
+ "@vue/shared": "3.0.11",
35
35
  "@babel/parser": "^7.12.0",
36
36
  "@babel/types": "^7.12.0",
37
37
  "estree-walker": "^2.0.1",