@vue/compiler-sfc 3.2.18 → 3.2.22

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.
@@ -1211,14 +1211,20 @@ function hasSrc(node) {
1211
1211
  * once the empty text nodes (trimmed content) have been filtered out.
1212
1212
  */
1213
1213
  function isEmpty(node) {
1214
- return (node.children.filter(child => child.type !== 2 /* TEXT */ || child.content.trim() !== '').length === 0);
1214
+ for (let i = 0; i < node.children.length; i++) {
1215
+ const child = node.children[i];
1216
+ if (child.type !== 2 /* TEXT */ || child.content.trim() !== '') {
1217
+ return false;
1218
+ }
1219
+ }
1220
+ return true;
1215
1221
  }
1216
1222
 
1217
1223
  function isRelativeUrl(url) {
1218
1224
  const firstChar = url.charAt(0);
1219
1225
  return firstChar === '.' || firstChar === '~' || firstChar === '@';
1220
1226
  }
1221
- const externalRE = /^https?:\/\//;
1227
+ const externalRE = /^(https?:)?\/\//;
1222
1228
  function isExternalUrl(url) {
1223
1229
  return externalRE.test(url);
1224
1230
  }
@@ -15780,6 +15786,8 @@ function compileScript(sfc, options) {
15780
15786
  let { script, scriptSetup, source, filename } = sfc;
15781
15787
  // feature flags
15782
15788
  const enableRefTransform = !!options.refSugar || !!options.refTransform;
15789
+ const enablePropsTransform = !!options.propsDestructureTransform;
15790
+ const isProd = !!options.isProd;
15783
15791
  const genSourceMap = options.sourceMap !== false;
15784
15792
  let refBindings;
15785
15793
  if (!options.id) {
@@ -15795,7 +15803,7 @@ function compileScript(sfc, options) {
15795
15803
  scriptLang === 'tsx' ||
15796
15804
  scriptSetupLang === 'ts' ||
15797
15805
  scriptSetupLang === 'tsx';
15798
- const plugins = [...shared.babelParserDefaultPlugins];
15806
+ const plugins = [];
15799
15807
  if (!isTS || scriptLang === 'tsx' || scriptSetupLang === 'tsx') {
15800
15808
  plugins.push('jsx');
15801
15809
  }
@@ -15842,7 +15850,7 @@ function compileScript(sfc, options) {
15842
15850
  }
15843
15851
  if (cssVars.length) {
15844
15852
  content = rewriteDefault(content, `__default__`, plugins);
15845
- content += genNormalScriptCssVarsCode(cssVars, bindings, scopeId, !!options.isProd);
15853
+ content += genNormalScriptCssVarsCode(cssVars, bindings, scopeId, isProd);
15846
15854
  content += `\nexport default __default__`;
15847
15855
  }
15848
15856
  return Object.assign(Object.assign({}, script), { content,
@@ -15877,6 +15885,8 @@ function compileScript(sfc, options) {
15877
15885
  let hasDefineExposeCall = false;
15878
15886
  let propsRuntimeDecl;
15879
15887
  let propsRuntimeDefaults;
15888
+ let propsDestructureDecl;
15889
+ let propsDestructureRestId;
15880
15890
  let propsTypeDecl;
15881
15891
  let propsTypeDeclRaw;
15882
15892
  let propsIdentifier;
@@ -15891,6 +15901,8 @@ function compileScript(sfc, options) {
15891
15901
  const typeDeclaredEmits = new Set();
15892
15902
  // record declared types for runtime props type generation
15893
15903
  const declaredTypes = {};
15904
+ // props destructure data
15905
+ const propsDestructuredBindings = Object.create(null);
15894
15906
  // magic-string state
15895
15907
  const s = new MagicString__default(source);
15896
15908
  const startOffset = scriptSetup.loc.start.offset;
@@ -15932,7 +15944,7 @@ function compileScript(sfc, options) {
15932
15944
  isUsedInTemplate
15933
15945
  };
15934
15946
  }
15935
- function processDefineProps(node) {
15947
+ function processDefineProps(node, declId) {
15936
15948
  if (!isCallOf(node, DEFINE_PROPS)) {
15937
15949
  return false;
15938
15950
  }
@@ -15954,17 +15966,63 @@ function compileScript(sfc, options) {
15954
15966
  `or a reference to an interface or literal type.`, propsTypeDeclRaw);
15955
15967
  }
15956
15968
  }
15969
+ if (declId) {
15970
+ if (enablePropsTransform && declId.type === 'ObjectPattern') {
15971
+ propsDestructureDecl = declId;
15972
+ // props destructure - handle compilation sugar
15973
+ for (const prop of declId.properties) {
15974
+ if (prop.type === 'ObjectProperty') {
15975
+ if (prop.computed) {
15976
+ error(`${DEFINE_PROPS}() destructure cannot use computed key.`, prop.key);
15977
+ }
15978
+ const propKey = prop.key.name;
15979
+ if (prop.value.type === 'AssignmentPattern') {
15980
+ // default value { foo = 123 }
15981
+ const { left, right } = prop.value;
15982
+ if (left.type !== 'Identifier') {
15983
+ error(`${DEFINE_PROPS}() destructure does not support nested patterns.`, left);
15984
+ }
15985
+ // store default value
15986
+ propsDestructuredBindings[propKey] = {
15987
+ local: left.name,
15988
+ default: right
15989
+ };
15990
+ }
15991
+ else if (prop.value.type === 'Identifier') {
15992
+ // simple destucture
15993
+ propsDestructuredBindings[propKey] = {
15994
+ local: prop.value.name
15995
+ };
15996
+ }
15997
+ else {
15998
+ error(`${DEFINE_PROPS}() destructure does not support nested patterns.`, prop.value);
15999
+ }
16000
+ }
16001
+ else {
16002
+ // rest spread
16003
+ propsDestructureRestId = prop.argument.name;
16004
+ }
16005
+ }
16006
+ }
16007
+ else {
16008
+ propsIdentifier = scriptSetup.content.slice(declId.start, declId.end);
16009
+ }
16010
+ }
15957
16011
  return true;
15958
16012
  }
15959
- function processWithDefaults(node) {
16013
+ function processWithDefaults(node, declId) {
15960
16014
  if (!isCallOf(node, WITH_DEFAULTS)) {
15961
16015
  return false;
15962
16016
  }
15963
- if (processDefineProps(node.arguments[0])) {
16017
+ if (processDefineProps(node.arguments[0], declId)) {
15964
16018
  if (propsRuntimeDecl) {
15965
16019
  error(`${WITH_DEFAULTS} can only be used with type-based ` +
15966
16020
  `${DEFINE_PROPS} declaration.`, node);
15967
16021
  }
16022
+ if (propsDestructureDecl) {
16023
+ error(`${WITH_DEFAULTS}() is unnecessary when using destructure with ${DEFINE_PROPS}().\n` +
16024
+ `Prefer using destructure default values, e.g. const { foo = 1 } = defineProps(...).`, node.callee);
16025
+ }
15968
16026
  propsRuntimeDefaults = node.arguments[1];
15969
16027
  if (!propsRuntimeDefaults ||
15970
16028
  propsRuntimeDefaults.type !== 'ObjectExpression') {
@@ -15976,7 +16034,7 @@ function compileScript(sfc, options) {
15976
16034
  }
15977
16035
  return true;
15978
16036
  }
15979
- function processDefineEmits(node) {
16037
+ function processDefineEmits(node, declId) {
15980
16038
  if (!isCallOf(node, DEFINE_EMITS)) {
15981
16039
  return false;
15982
16040
  }
@@ -15997,6 +16055,9 @@ function compileScript(sfc, options) {
15997
16055
  `a literal type with call signatures, or a reference to the above types.`, emitsTypeDeclRaw);
15998
16056
  }
15999
16057
  }
16058
+ if (declId) {
16059
+ emitIdentifier = scriptSetup.content.slice(declId.start, declId.end);
16060
+ }
16000
16061
  return true;
16001
16062
  }
16002
16063
  function resolveQualifiedType(node, qualifier) {
@@ -16048,7 +16109,7 @@ function compileScript(sfc, options) {
16048
16109
  if (setupBindings[id.name]) {
16049
16110
  error(`\`${method}()\` in <script setup> cannot reference locally ` +
16050
16111
  `declared variables because it will be hoisted outside of the ` +
16051
- `setup() function. If your component options requires initialization ` +
16112
+ `setup() function. If your component options require initialization ` +
16052
16113
  `in the module scope, use a separate normal <script> to export ` +
16053
16114
  `the options instead.`, id);
16054
16115
  }
@@ -16086,7 +16147,7 @@ function compileScript(sfc, options) {
16086
16147
  * static properties, we can directly generate more optimzied default
16087
16148
  * declarations. Otherwise we will have to fallback to runtime merging.
16088
16149
  */
16089
- function checkStaticDefaults() {
16150
+ function hasStaticWithDefaults() {
16090
16151
  return (propsRuntimeDefaults &&
16091
16152
  propsRuntimeDefaults.type === 'ObjectExpression' &&
16092
16153
  propsRuntimeDefaults.properties.every(node => (node.type === 'ObjectProperty' && !node.computed) ||
@@ -16097,13 +16158,17 @@ function compileScript(sfc, options) {
16097
16158
  if (!keys.length) {
16098
16159
  return ``;
16099
16160
  }
16100
- const hasStaticDefaults = checkStaticDefaults();
16161
+ const hasStaticDefaults = hasStaticWithDefaults();
16101
16162
  const scriptSetupSource = scriptSetup.content;
16102
16163
  let propsDecls = `{
16103
16164
  ${keys
16104
16165
  .map(key => {
16105
16166
  let defaultString;
16106
- if (hasStaticDefaults) {
16167
+ const destructured = genDestructuredDefaultValue(key);
16168
+ if (destructured) {
16169
+ defaultString = `default: ${destructured}`;
16170
+ }
16171
+ else if (hasStaticDefaults) {
16107
16172
  const prop = propsRuntimeDefaults.properties.find((node) => node.key.name === key);
16108
16173
  if (prop) {
16109
16174
  if (prop.type === 'ObjectProperty') {
@@ -16115,10 +16180,18 @@ function compileScript(sfc, options) {
16115
16180
  }
16116
16181
  }
16117
16182
  }
16118
- {
16119
- const { type, required } = props[key];
16183
+ const { type, required } = props[key];
16184
+ if (!isProd) {
16120
16185
  return `${key}: { type: ${toRuntimeTypeString(type)}, required: ${required}${defaultString ? `, ${defaultString}` : ``} }`;
16121
16186
  }
16187
+ else if (type.some(el => el === 'Boolean' || (defaultString && el === 'Function'))) {
16188
+ // #4783 production: if boolean or defaultString and function exists, should keep the type.
16189
+ return `${key}: { type: ${toRuntimeTypeString(type)}${defaultString ? `, ${defaultString}` : ``} }`;
16190
+ }
16191
+ else {
16192
+ // production: checks are useless
16193
+ return `${key}: ${defaultString ? `{ ${defaultString} }` : 'null'}`;
16194
+ }
16122
16195
  })
16123
16196
  .join(',\n ')}\n }`;
16124
16197
  if (propsRuntimeDefaults && !hasStaticDefaults) {
@@ -16126,9 +16199,17 @@ function compileScript(sfc, options) {
16126
16199
  }
16127
16200
  return `\n props: ${propsDecls},`;
16128
16201
  }
16202
+ function genDestructuredDefaultValue(key) {
16203
+ const destructured = propsDestructuredBindings[key];
16204
+ if (destructured && destructured.default) {
16205
+ const value = scriptSetup.content.slice(destructured.default.start, destructured.default.end);
16206
+ const isLiteral = destructured.default.type.endsWith('Literal');
16207
+ return isLiteral ? value : `() => ${value}`;
16208
+ }
16209
+ }
16129
16210
  function genSetupPropsType(node) {
16130
16211
  const scriptSetupSource = scriptSetup.content;
16131
- if (checkStaticDefaults()) {
16212
+ if (hasStaticWithDefaults()) {
16132
16213
  // if withDefaults() is used, we need to remove the optional flags
16133
16214
  // on props that have default values
16134
16215
  let res = `{ `;
@@ -16211,14 +16292,15 @@ function compileScript(sfc, options) {
16211
16292
  }
16212
16293
  else if ((node.type === 'VariableDeclaration' ||
16213
16294
  node.type === 'FunctionDeclaration' ||
16214
- node.type === 'ClassDeclaration') &&
16295
+ node.type === 'ClassDeclaration' ||
16296
+ node.type === 'TSEnumDeclaration') &&
16215
16297
  !node.declare) {
16216
16298
  walkDeclaration(node, scriptBindings, userImportAlias);
16217
16299
  }
16218
16300
  }
16219
16301
  // apply ref transform
16220
16302
  if (enableRefTransform && refTransform.shouldTransform(script.content)) {
16221
- const { rootVars, importedHelpers } = refTransform.transformAST(scriptAst, s, scriptStartOffset);
16303
+ const { rootRefs: rootVars, importedHelpers } = refTransform.transformAST(scriptAst, s, scriptStartOffset);
16222
16304
  refBindings = rootVars;
16223
16305
  for (const h of importedHelpers) {
16224
16306
  helperImports.add(h);
@@ -16325,14 +16407,9 @@ function compileScript(sfc, options) {
16325
16407
  const decl = node.declarations[i];
16326
16408
  if (decl.init) {
16327
16409
  // defineProps / defineEmits
16328
- const isDefineProps = processDefineProps(decl.init) || processWithDefaults(decl.init);
16329
- if (isDefineProps) {
16330
- propsIdentifier = scriptSetup.content.slice(decl.id.start, decl.id.end);
16331
- }
16332
- const isDefineEmits = processDefineEmits(decl.init);
16333
- if (isDefineEmits) {
16334
- emitIdentifier = scriptSetup.content.slice(decl.id.start, decl.id.end);
16335
- }
16410
+ const isDefineProps = processDefineProps(decl.init, decl.id) ||
16411
+ processWithDefaults(decl.init, decl.id);
16412
+ const isDefineEmits = processDefineEmits(decl.init, decl.id);
16336
16413
  if (isDefineProps || isDefineEmits) {
16337
16414
  if (left === 1) {
16338
16415
  s.remove(node.start + startOffset, node.end + startOffset);
@@ -16404,9 +16481,10 @@ function compileScript(sfc, options) {
16404
16481
  }
16405
16482
  }
16406
16483
  // 3. Apply ref sugar transform
16407
- if (enableRefTransform && refTransform.shouldTransform(scriptSetup.content)) {
16408
- const { rootVars, importedHelpers } = refTransform.transformAST(scriptSetupAst, s, startOffset, refBindings);
16409
- refBindings = refBindings ? [...refBindings, ...rootVars] : rootVars;
16484
+ if ((enableRefTransform && refTransform.shouldTransform(scriptSetup.content)) ||
16485
+ propsDestructureDecl) {
16486
+ const { rootRefs, importedHelpers } = refTransform.transformAST(scriptSetupAst, s, startOffset, refBindings, propsDestructuredBindings, !enableRefTransform);
16487
+ refBindings = refBindings ? [...refBindings, ...rootRefs] : rootRefs;
16410
16488
  for (const h of importedHelpers) {
16411
16489
  helperImports.add(h);
16412
16490
  }
@@ -16422,6 +16500,7 @@ function compileScript(sfc, options) {
16422
16500
  // variables
16423
16501
  checkInvalidScopeReference(propsRuntimeDecl, DEFINE_PROPS);
16424
16502
  checkInvalidScopeReference(propsRuntimeDefaults, DEFINE_PROPS);
16503
+ checkInvalidScopeReference(propsDestructureDecl, DEFINE_PROPS);
16425
16504
  checkInvalidScopeReference(emitsRuntimeDecl, DEFINE_PROPS);
16426
16505
  // 6. remove non-script content
16427
16506
  if (script) {
@@ -16455,6 +16534,20 @@ function compileScript(sfc, options) {
16455
16534
  for (const key in typeDeclaredProps) {
16456
16535
  bindingMetadata[key] = "props" /* PROPS */;
16457
16536
  }
16537
+ // props aliases
16538
+ if (propsDestructureDecl) {
16539
+ if (propsDestructureRestId) {
16540
+ bindingMetadata[propsDestructureRestId] = "setup-const" /* SETUP_CONST */;
16541
+ }
16542
+ for (const key in propsDestructuredBindings) {
16543
+ const { local } = propsDestructuredBindings[key];
16544
+ if (local !== key) {
16545
+ bindingMetadata[local] = "props-aliased" /* PROPS_ALIASED */;
16546
+ (bindingMetadata.__propsAliases ||
16547
+ (bindingMetadata.__propsAliases = {}))[local] = key;
16548
+ }
16549
+ }
16550
+ }
16458
16551
  for (const [key, { isType, imported, source }] of Object.entries(userImports)) {
16459
16552
  if (isType)
16460
16553
  continue;
@@ -16479,7 +16572,7 @@ function compileScript(sfc, options) {
16479
16572
  if (cssVars.length) {
16480
16573
  helperImports.add(CSS_VARS_HELPER);
16481
16574
  helperImports.add('unref');
16482
- s.prependRight(startOffset, `\n${genCssVarsCode(cssVars, bindingMetadata, scopeId, !!options.isProd)}\n`);
16575
+ s.prependRight(startOffset, `\n${genCssVarsCode(cssVars, bindingMetadata, scopeId, isProd)}\n`);
16483
16576
  }
16484
16577
  // 9. finalize setup() argument signature
16485
16578
  let args = `__props`;
@@ -16493,12 +16586,15 @@ function compileScript(sfc, options) {
16493
16586
  // we use a default __props so that template expressions referencing props
16494
16587
  // can use it directly
16495
16588
  if (propsIdentifier) {
16496
- s.prependRight(startOffset, `\nconst ${propsIdentifier} = __props${propsTypeDecl ? ` as ${genSetupPropsType(propsTypeDecl)}` : ``}`);
16589
+ s.prependLeft(startOffset, `\nconst ${propsIdentifier} = __props${propsTypeDecl ? ` as ${genSetupPropsType(propsTypeDecl)}` : ``}\n`);
16590
+ }
16591
+ if (propsDestructureRestId) {
16592
+ s.prependLeft(startOffset, `\nconst ${propsDestructureRestId} = ${helper(`createPropsRestProxy`)}(__props, ${JSON.stringify(Object.keys(propsDestructuredBindings))})\n`);
16497
16593
  }
16498
16594
  // inject temp variables for async context preservation
16499
16595
  if (hasAwait) {
16500
16596
  const any = isTS ? `: any` : ``;
16501
- s.prependRight(startOffset, `\nlet __temp${any}, __restore${any}\n`);
16597
+ s.prependLeft(startOffset, `\nlet __temp${any}, __restore${any}\n`);
16502
16598
  }
16503
16599
  const destructureElements = hasDefineExposeCall || !options.inlineTemplate ? [`expose`] : [];
16504
16600
  if (emitIdentifier) {
@@ -16582,9 +16678,21 @@ function compileScript(sfc, options) {
16582
16678
  runtimeOptions += `\n __ssrInlineRender: true,`;
16583
16679
  }
16584
16680
  if (propsRuntimeDecl) {
16585
- runtimeOptions += `\n props: ${scriptSetup.content
16681
+ let declCode = scriptSetup.content
16586
16682
  .slice(propsRuntimeDecl.start, propsRuntimeDecl.end)
16587
- .trim()},`;
16683
+ .trim();
16684
+ if (propsDestructureDecl) {
16685
+ const defaults = [];
16686
+ for (const key in propsDestructuredBindings) {
16687
+ const d = genDestructuredDefaultValue(key);
16688
+ if (d)
16689
+ defaults.push(`${key}: ${d}`);
16690
+ }
16691
+ if (defaults.length) {
16692
+ declCode = `${helper(`mergeDefaults`)}(${declCode}, {\n ${defaults.join(',\n ')}\n})`;
16693
+ }
16694
+ }
16695
+ runtimeOptions += `\n props: ${declCode},`;
16588
16696
  }
16589
16697
  else if (propsTypeDecl) {
16590
16698
  runtimeOptions += genRuntimeProps(typeDeclaredProps);
@@ -16599,7 +16707,7 @@ function compileScript(sfc, options) {
16599
16707
  }
16600
16708
  // <script setup> components are closed by default. If the user did not
16601
16709
  // explicitly call `defineExpose`, call expose() with no args.
16602
- const exposeCall = hasDefineExposeCall || options.inlineTemplate ? `` : ` expose()\n`;
16710
+ const exposeCall = hasDefineExposeCall || options.inlineTemplate ? `` : ` expose();\n`;
16603
16711
  if (isTS) {
16604
16712
  // for TS, make sure the exported type is still valid type with
16605
16713
  // correct props information
@@ -16682,15 +16790,22 @@ function walkDeclaration(node, bindings, userImportAlias) {
16682
16790
  }
16683
16791
  registerBinding(bindings, id, bindingType);
16684
16792
  }
16685
- else if (id.type === 'ObjectPattern') {
16686
- walkObjectPattern(id, bindings, isConst, isDefineCall);
16687
- }
16688
- else if (id.type === 'ArrayPattern') {
16689
- walkArrayPattern(id, bindings, isConst, isDefineCall);
16793
+ else {
16794
+ if (isCallOf(init, DEFINE_PROPS)) {
16795
+ // skip walking props destructure
16796
+ return;
16797
+ }
16798
+ if (id.type === 'ObjectPattern') {
16799
+ walkObjectPattern(id, bindings, isConst, isDefineCall);
16800
+ }
16801
+ else if (id.type === 'ArrayPattern') {
16802
+ walkArrayPattern(id, bindings, isConst, isDefineCall);
16803
+ }
16690
16804
  }
16691
16805
  }
16692
16806
  }
16693
- else if (node.type === 'FunctionDeclaration' ||
16807
+ else if (node.type === 'TSEnumDeclaration' ||
16808
+ node.type === 'FunctionDeclaration' ||
16694
16809
  node.type === 'ClassDeclaration') {
16695
16810
  // export function foo() {} / export class Foo {}
16696
16811
  // export declarations must be named.
@@ -16771,19 +16886,17 @@ function recordType(node, declaredTypes) {
16771
16886
  recordType(node.declaration, declaredTypes);
16772
16887
  }
16773
16888
  }
16774
- function extractRuntimeProps(node, props, declaredTypes) {
16889
+ function extractRuntimeProps(node, props, declaredTypes, isProd) {
16775
16890
  const members = node.type === 'TSTypeLiteral' ? node.members : node.body;
16776
16891
  for (const m of members) {
16777
16892
  if ((m.type === 'TSPropertySignature' || m.type === 'TSMethodSignature') &&
16778
16893
  m.key.type === 'Identifier') {
16779
16894
  let type;
16780
- {
16781
- if (m.type === 'TSMethodSignature') {
16782
- type = ['Function'];
16783
- }
16784
- else if (m.typeAnnotation) {
16785
- type = inferRuntimeType(m.typeAnnotation.typeAnnotation, declaredTypes);
16786
- }
16895
+ if (m.type === 'TSMethodSignature') {
16896
+ type = ['Function'];
16897
+ }
16898
+ else if (m.typeAnnotation) {
16899
+ type = inferRuntimeType(m.typeAnnotation.typeAnnotation, declaredTypes);
16787
16900
  }
16788
16901
  props[m.key.name] = {
16789
16902
  key: m.key.name,
@@ -169,9 +169,15 @@ export declare interface SFCScriptCompileOptions {
169
169
  /**
170
170
  * (Experimental) Enable syntax transform for using refs without `.value`
171
171
  * https://github.com/vuejs/rfcs/discussions/369
172
- * @default true
172
+ * @default false
173
173
  */
174
174
  refTransform?: boolean;
175
+ /**
176
+ * (Experimental) Enable syntax transform for destructuring from defineProps()
177
+ * https://github.com/vuejs/rfcs/discussions/394
178
+ * @default false
179
+ */
180
+ propsDestructureTransform?: boolean;
175
181
  /**
176
182
  * @deprecated use `refTransform` instead.
177
183
  */